Index: mojo/public/tools/bindings/generators/mojom_java_generator.py |
diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..96934172c8125f4b9aeb08c1ff1304e66ae5f8b5 |
--- /dev/null |
+++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py |
@@ -0,0 +1,272 @@ |
+# Copyright 2013 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Generates java source files from a mojom.Module.""" |
+ |
+import argparse |
+import os |
+ |
+import mojom.generate.generator as generator |
+import mojom.generate.module as mojom |
+import mojom.generate.pack as pack |
+from mojom.generate.template_expander import UseJinja |
+ |
+ |
+GENERATOR_PREFIX = 'java' |
+ |
+_HEADER_SIZE = 8 |
+ |
+_spec_to_java_type = { |
+ 'b': "boolean", |
+ 'd': "double", |
+ 'f': "float", |
+ 'h:d:c': "org.chromium.mojo.system.DataPipe.ConsumerHandle", |
+ 'h:d:p': "org.chromium.mojo.system.DataPipe.ProducerHandle", |
+ 'h:m': "org.chromium.mojo.system.MessagePipeHandle", |
+ 'h': "org.chromium.mojo.system.UntypedHandle", |
+ 'h:s': "org.chromium.mojo.system.SharedBufferHandle", |
+ 'i16': "short", |
+ 'i32': "int", |
+ 'i64': "long", |
+ 'i8': "byte", |
+ 's': "String", |
+ 'u16': "short", |
+ 'u32': "int", |
+ 'u64': "long", |
+ 'u8': "byte", |
+} |
+ |
+_spec_to_decryption_method = { |
rmcilroy
2014/05/20 12:43:29
should this be _spec_to_encode_method?
qsr
2014/05/20 13:12:45
Hum, nope, decode is the right name here, and my m
rmcilroy
2014/05/22 15:52:07
Well "decryption" wasn't the right name either ;).
|
+ 'b': "readBoolean", |
+ 'd': "readDouble", |
+ 'f': "readFloat", |
+ 'h:d:c': "readConsumerHandle", |
+ 'h:d:p': "readProducerHandle", |
+ 'h:m': "readMessagePipeHandle", |
+ 'h': "readUntypedHandle", |
+ 'h:s': "readSharedBufferHandle", |
+ 'i16': "readShort", |
+ 'i32': "readInt", |
+ 'i64': "readLong", |
+ 'i8': "readByte", |
+ 's': "readString", |
+ 'u16': "readShort", |
+ 'u32': "readInt", |
+ 'u64': "readLong", |
+ 'u8': "readByte", |
+} |
+ |
+ |
+def EncodeMethod(kind): |
+ if isinstance(kind, mojom.Array): |
+ return EncodeMethod(kind.kind) + 's' |
+ if isinstance(kind, mojom.Enum): |
+ return EncodeMethod(mojom.INT32) |
+ if isinstance(kind, mojom.Interface): |
+ return "readServiceInterface" |
+ return _spec_to_decryption_method[kind.spec] |
+ |
+def NamespaceToArray(namespace): |
+ return namespace.split('.') |
+ |
+def GetNameFromString(string): |
+ return CapitalizeFirst(CamelCase(string)) |
+ |
+def GetName(kind): |
+ return GetNameFromString(kind.name) |
+ |
+def GetPackage(module): |
+ if 'JavaPackage' in module.attributes: |
+ package = module.attributes['JavaPackage'] |
+ if isinstance(package, basestring): |
+ return package |
+ assert package[0] == 'EXPRESSION' |
+ assert len(package[1]) == 1 |
+ return package[1][0][1:-1].encode('string_escape') |
+ return "org.chromium.mojom." + module.namespace |
+ |
+def GetSuperClass(method): |
+ if method: |
+ if method.response_parameters: |
+ return "org.chromium.mojo.bindings.MessageWithRequestId" |
+ return "org.chromium.mojo.bindings.Message" |
+ return "org.chromium.mojo.bindings.Struct" |
+ |
+def GetFlags(method, is_parameter): |
+ if method.response_parameters: |
+ if is_parameter: |
+ return "MESSAGE_EXPECTS_RESPONSE_FLAG" |
+ return "MESSAGE_IS_RESPONSE_FLAG" |
+ return "0" |
+ |
+def NewArray(kind, size): |
+ if isinstance(kind.kind, mojom.Array): |
+ return NewArray(kind.kind, size) + '[]' |
+ return 'new %s[%s]' % (GetJavaType(kind.kind), size) |
+ |
+def GetNameHierachy(kind): |
+ hierachy = [] |
+ if kind.parent_kind: |
+ hierachy = GetNameHierachy(kind.parent_kind) |
+ hierachy.append(kind.name) |
+ return hierachy |
+ |
+def GetNameForKind(kind): |
+ elements = [GetPackage(kind.module)] |
+ elements += GetNameHierachy(kind) |
+ return '.'.join(elements) |
+ |
+def GetJavaGetterPrefix(kind): |
+ if kind == mojom.BOOL: |
+ return "is" |
+ return "get" |
+ |
+def GetJavaType(kind): |
+ if isinstance(kind, mojom.Struct): |
+ return GetNameForKind(kind) |
+ if isinstance(kind, mojom.Array): |
+ return "%s[]" % GetJavaType(kind.kind) |
+ if isinstance(kind, mojom.Interface): |
+ return "org.chromium.mojo.bindings.ServiceHandle<%s>" % GetNameForKind(kind) |
+ if isinstance(kind, mojom.Enum): |
+ return "int" |
+ return _spec_to_java_type[kind.spec] |
+ |
+def TranslateConstants(token, module): |
+ if isinstance(token, (mojom.NamedValue, mojom.EnumValue)): |
+ if isinstance(token, mojom.EnumValue): |
+ entity_value = token.enum_name + '.' + token.name |
+ else: |
+ entity_value = ConstantName(token) |
+ if not token.parent_kind: |
+ entity_value = (GetConstantsMainEntityName(token.module) + |
+ '.' + entity_value) |
+ if token.parent_kind: |
+ return GetJavaType(token.parent_kind) + '.' + entity_value |
+ return GetPackage(token.module) + '.' + entity_value |
+ return token |
+ |
+def ExpressionToText(value, module): |
+ if value[0] != "EXPRESSION": |
+ raise Exception("Expected EXPRESSION, got" + value) |
+ return "".join(generator.ExpressionMapper(value, |
+ lambda token: TranslateConstants(token, module))) |
+ |
+def CapitalizeFirst(string): |
+ return string[0].upper() + string[1:] |
+ |
+def CamelCase(string): |
+ elements = string.split('_') |
+ return elements[0] + ''.join([x.capitalize() for x in elements[1:]]) |
+ |
+def UpperCaseConstant(name): |
+ def _IsCut(i): |
+ if i == 0 or i == len(name): |
+ return True |
+ if name[i].islower(): |
+ return False |
+ if name[i-1].isupper() and (i == len(name) -1 or name[i+1].isupper()): |
+ return False |
+ return True |
+ pos = [i for i in xrange(len(name) + 1) if _IsCut(i)] |
+ parts = [name[pos[j]:pos[j+1]] for j in xrange(len(pos)-1)] |
+ return '_'.join([x.upper() for x in parts]) |
+ |
+def DefaultValueConstant(field): |
+ return 'DEFAULT_' + UpperCaseConstant(GetName(field)) |
+ |
+def FieldName(field): |
+ return 'm' + GetName(field) |
+ |
+def ConstantName(constant): |
+ main_name = constant.name |
+ if main_name[0] == 'k': |
+ main_name = main_name[1:] |
+ return UpperCaseConstant(main_name) |
+ |
+def IsPointerArrayKind(kind): |
+ if not isinstance(kind, mojom.Array): |
+ return False |
+ sub_kind = kind.kind |
+ return generator.IsObjectKind(sub_kind) |
+ |
+def GetResponseStructFromMethod(method): |
+ return generator.GetDataHeader( |
+ False, generator.GetResponseStructFromMethod(method)) |
+ |
+def GetStructFromMethod(method): |
+ return generator.GetDataHeader( |
+ False, generator.GetStructFromMethod(method)) |
+ |
+def GetMethodName(method): |
+ return (UpperCaseConstant(method.interface.name) + "_" + |
+ UpperCaseConstant(method.name) + "_NAME") |
+ |
+def GetConstantsMainEntityFullyQualifiedName(module): |
+ package = GetPackage(module) |
+ return GetPackage(module) + '.' + GetConstantsMainEntityName(module) |
+ |
+def GetConstantsMainEntityName(module): |
+ return (GetNameFromString(module.path.split('/')[-1].rsplit('.', 1)[0]) + |
+ 'Constants') |
+ |
+class Generator(generator.Generator): |
+ |
+ java_filters = { |
+ "camelcase": CamelCase, |
+ "capitalize_first": CapitalizeFirst, |
+ "default_value_constant": DefaultValueConstant, |
+ "encode_method": EncodeMethod, |
+ "expression_to_text": ExpressionToText, |
+ "field_name": FieldName, |
+ "flags": GetFlags, |
+ "is_bool": lambda kind: kind == mojom.BOOL, |
+ "is_array_kind": lambda kind: isinstance(kind, mojom.Array), |
+ "is_object_kind": generator.IsObjectKind, |
+ "is_pointer_array_kind": IsPointerArrayKind, |
+ "is_string_kind": generator.IsStringKind, |
+ "is_struct_kind": lambda kind: isinstance(kind, mojom.Struct), |
+ "java_getter_prefix": GetJavaGetterPrefix, |
+ "java_type": GetJavaType, |
+ "method_name": GetMethodName, |
+ "new_array": NewArray, |
+ "response_struct_from_method": GetResponseStructFromMethod, |
+ "struct_from_method": GetStructFromMethod, |
+ "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE, |
+ "super_class": GetSuperClass, |
+ "constant_name": ConstantName, |
+ "verify_token_type": generator.VerifyTokenType, |
+ } |
+ |
+ def GetJinjaExports(self): |
+ return { |
+ "interfaces": self.module.interfaces, |
+ "kinds": self.module.kinds, |
+ "method_structs": self.GetStructsFromMethods(), |
+ "module": self.module, |
+ "namespace": self.module.namespace, |
+ "package": GetPackage(self.module), |
+ } |
+ |
+ @UseJinja("java_templates/constants.java.tmpl", filters=java_filters, |
+ lstrip_blocks=True, trim_blocks=True) |
+ def GenerateConstantsSource(self, module): |
+ exports = self.GetJinjaExports() |
+ exports.update({"main_entity": GetConstantsMainEntityName(module), |
+ "constants": module.constants}) |
+ return exports |
+ |
+ def GenerateFiles(self, unparsed_args): |
+ parser = argparse.ArgumentParser() |
+ parser.add_argument("--java_output_directory", dest="java_output_directory") |
+ args = parser.parse_args(unparsed_args) |
+ if self.output_dir and args.java_output_directory: |
+ self.output_dir = os.path.join(args.java_output_directory, |
+ GetPackage(self.module).replace('.', '/')) |
+ if not os.path.exists(self.output_dir): |
+ os.makedirs(self.output_dir) |
+ |
+ if self.module.constants: |
+ self.Write(self.GenerateConstantsSource(self.module), |
+ "%s.java" % GetConstantsMainEntityName(self.module)) |