Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1519)

Unified Diff: mojo/public/tools/bindings/generators/mojom_java_generator.py

Issue 291903003: Generate java bindings for constants. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Follow review Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..1cfcef313b9573dd51371154110f72524cebf81c
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -0,0 +1,187 @@
+# 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 re
+
+import mojom.generate.generator as generator
+import mojom.generate.module as mojom
+from mojom.generate.template_expander import UseJinja
+
+
+GENERATOR_PREFIX = 'java'
+
+_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',
+}
+
+
+def NameToComponent(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
rmcilroy 2014/05/26 11:13:48 How about using the regex's I suggested in the las
qsr 2014/05/26 12:05:42 Done, but I do not find that clearer. Also didn't
+ if '_' in name:
+ return [item for sublist in [NameToComponent(y) for y in name.split('_')]
+ for item in sublist]
+ pos = [i for i in xrange(len(name) + 1) if _IsCut(i)]
+ return [name[pos[j]:pos[j+1]].lower() for j in xrange(len(pos)-1)]
+
+def CapitalizeFirst(string):
+ return string[0].upper() + string[1:]
+
+def UpperCamelCase(name):
+ return ''.join([CapitalizeFirst(x) for x in NameToComponent(name)])
+
+def CamelCase(name):
+ uccc = UpperCamelCase(name)
+ return uccc[0].lower() + uccc[1:]
+
+def UpperCaseHackerStyle(name):
rmcilroy 2014/05/26 11:13:48 I've never heard of hacker style and can't find it
qsr 2014/05/26 12:05:42 Done. Don't remember where I found it was called h
+ components = NameToComponent(name)
+ if components[0] == 'k':
+ components = components[1:]
+ return '_'.join([x.upper() for x in components])
+
+def GetNameForElement(element):
+ if (isinstance(element, mojom.Enum) or
+ isinstance(element, mojom.Interface) or
+ isinstance(element, mojom.Struct)):
+ return UpperCamelCase(element.name)
+ if (isinstance(element, mojom.Method) or
+ isinstance(element, mojom.Parameter) or
+ isinstance(element, mojom.Field)):
+ return CamelCase(element.name)
+ if isinstance(element, mojom.EnumValue):
+ return (UpperCamelCase(element.enum_name) + '.' +
+ UpperCaseHackerStyle(element.name))
+ if (isinstance(element, mojom.NamedValue) or
+ isinstance(element, mojom.Constant)):
+ return UpperCaseHackerStyle(element.name)
+ raise Exception("Unexpected element: " % element)
+
+def GetPackage(module):
+ if 'JavaPackage' not in module.attributes:
rmcilroy 2014/05/26 11:13:48 In the case of this function, I still think if/els
qsr 2014/05/26 12:05:42 Move the conditional back. But I really don't like
rmcilroy 2014/05/27 09:44:34 OK, we disagree on this, but I'm not going to bike
+ return "org.chromium.mojom." + module.namespace
+ 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')
+
+def GetNameForKind(kind):
+ def _GetNameHierachy(kind):
+ hierachy = []
+ if kind.parent_kind:
+ hierachy = _GetNameHierachy(kind.parent_kind)
+ hierachy.append(kind.name)
+ return hierachy
+
+ elements = [GetPackage(kind.module)]
+ elements += _GetNameHierachy(kind)
+ return '.'.join(elements)
+
+def GetJavaType(kind):
+ if isinstance(kind, (mojom.Struct, mojom.Interface)):
+ return GetNameForKind(kind)
+ if isinstance(kind, mojom.Array):
+ return "%s[]" % GetJavaType(kind.kind)
+ if isinstance(kind, mojom.Enum):
+ return "int"
+ return _spec_to_java_type[kind.spec]
+
+def TranslateConstants(token, module):
+ def _TranslateNamedValue(named_value):
+ entity_value = GetNameForElement(named_value)
rmcilroy 2014/05/26 11:13:48 /s/entity_value/entity_name I think.
qsr 2014/05/26 12:05:42 Done.
+ # Handle the case where named_value is a module level constant:
+ if (not isinstance(named_value, mojom.EnumValue) and
rmcilroy 2014/05/26 11:13:48 This seems a bit confusing to me, how about: if n
qsr 2014/05/26 12:05:42 I still think the else after a return is not in an
rmcilroy 2014/05/27 09:44:34 Ok, this looks better, thanks.
+ not named_value.parent_kind):
+ return (GetConstantsMainEntityFullyQualifiedName(named_value.module) +
+ '.'+ entity_value)
+ if named_value.parent_kind:
+ return GetJavaType(named_value.parent_kind) + '.' + entity_value
+ return GetPackage(named_value.module) + '.' + entity_value
+
+ if isinstance(token, mojom.NamedValue):
+ return _TranslateNamedValue(token)
+ if re.match('^[0-9]+$', token):
rmcilroy 2014/05/26 11:13:48 Comment that you add Long suffix to all number lit
qsr 2014/05/26 12:05:42 Done.
+ return token + 'L'
+ 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 GetConstantsMainEntityFullyQualifiedName(module):
+ package = GetPackage(module)
+ return GetPackage(module) + '.' + GetConstantsMainEntityName(module)
+
+def GetConstantsMainEntityName(module):
+ # This constructs the name of the embedding classes for module level constants
+ # by extracting the mojom's filename and prepending it to Constants.
+ return (UpperCamelCase(module.path.split('/')[-1].rsplit('.', 1)[0]) +
+ 'Constants')
+
+class Generator(generator.Generator):
+
+ java_filters = {
+ "expression_to_text": ExpressionToText,
+ "java_type": GetJavaType,
+ "name": GetNameForElement,
+ "verify_token_type": generator.VerifyTokenType,
+ }
+
+ def GetJinjaExports(self):
+ return {
+ "module": self.module,
+ "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))

Powered by Google App Engine
This is Rietveld 408576698