Mojo code generator: change where to add computed data to mojom definitions
So that the same work is not done multiple times.
BUG=718614
Review-Url: https://codereview.chromium.org/2863353002
Cr-Commit-Position: refs/heads/master@{#470986}
CrOS-Libchrome-Original-Commit: 121205ac1fd5cf2274a6f429dec741fb602f7081
diff --git a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
index 85d95d6..afee2ba 100644
--- a/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl
@@ -204,7 +204,7 @@
}
var {{interface.name}} = {
- name: '{{namespace|replace(".","::")}}::{{interface.name}}',
+ name: '{{module.namespace|replace(".","::")}}::{{interface.name}}',
kVersion: {{interface.version}},
ptrClass: {{interface.name}}Ptr,
proxyClass: {{interface.name}}Proxy,
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index d2930d1..7b55afc 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -278,12 +278,10 @@
yield param.kind
def _GetJinjaExports(self):
- structs = self.GetStructs()
- interfaces = self.GetInterfaces()
all_enums = list(self.module.enums)
- for struct in structs:
+ for struct in self.module.structs:
all_enums.extend(struct.enums)
- for interface in interfaces:
+ for interface in self.module.interfaces:
all_enums.extend(interface.enums)
return {
@@ -294,9 +292,9 @@
"kinds": self.module.kinds,
"enums": self.module.enums,
"all_enums": all_enums,
- "structs": structs,
- "unions": self.GetUnions(),
- "interfaces": interfaces,
+ "structs": self.module.structs,
+ "unions": self.module.unions,
+ "interfaces": self.module.interfaces,
"variant": self.variant,
"extra_traits_headers": self._GetExtraTraitsHeaders(),
"extra_public_headers": self._GetExtraPublicHeaders(),
@@ -356,7 +354,7 @@
"is_union_kind": mojom.IsUnionKind,
"passes_associated_kinds": mojom.PassesAssociatedKinds,
"struct_constructors": self._GetStructConstructors,
- "under_to_camel": generator.UnderToCamel,
+ "under_to_camel": generator.ToCamel,
"unmapped_type_for_serializer": self._GetUnmappedTypeForSerializer,
"wtf_hash_fn_name_for_enum": GetWtfHashFnNameForEnum,
}
diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 33c47c8..3e6f63a 100644
--- a/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -486,9 +486,7 @@
def _DoGenerateFiles(self):
fileutil.EnsureDirectoryExists(self.output_dir)
- # Keep this above the others as .GetStructs() changes the state of the
- # module, annotating structs with required information.
- for struct in self.GetStructs():
+ for struct in self.module.structs:
self.Write(self._GenerateStructSource(struct),
'%s.java' % GetNameForElement(struct))
@@ -500,7 +498,7 @@
self.Write(self._GenerateEnumSource(enum),
'%s.java' % GetNameForElement(enum))
- for interface in self.GetInterfaces():
+ for interface in self.module.interfaces:
self.Write(self._GenerateInterfaceSource(interface),
'%s.java' % GetNameForElement(interface))
self.Write(self._GenerateInterfaceInternalSource(interface),
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index 20a2b23..ef4c2ef 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -95,16 +95,14 @@
class Generator(generator.Generator):
def _GetParameters(self):
return {
- "namespace": self.module.namespace,
- "imports": self._GetImports(),
- "kinds": self.module.kinds,
"enums": self.module.enums,
+ "imports": self.module.imports,
+ "interfaces": self.module.interfaces,
+ "kinds": self.module.kinds,
"module": self.module,
- "structs": self.GetStructs() + self.GetStructsFromMethods(),
- "unions": self.GetUnions(),
+ "structs": self.module.structs + self._GetStructsFromMethods(),
+ "unions": self.module.unions,
"use_new_js_bindings": self.use_new_js_bindings,
- "interfaces": self.GetInterfaces(),
- "imported_interfaces": self._GetImportedInterfaces(),
}
@staticmethod
@@ -118,6 +116,7 @@
"encode_snippet": self._JavaScriptEncodeSnippet,
"expression_to_text": self._ExpressionToText,
"field_offset": JavaScriptFieldOffset,
+ "get_relative_path": GetRelativePath,
"has_callbacks": mojom.HasCallbacks,
"is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind,
"is_array_kind": mojom.IsArrayKind,
@@ -137,8 +136,8 @@
"js_type": self._JavaScriptType,
"method_passes_associated_kinds": mojom.MethodPassesAssociatedKinds,
"payload_size": JavaScriptPayloadSize,
- "get_relative_path": GetRelativePath,
- "stylize_method": generator.StudlyCapsToCamel,
+ "stylize_method": lambda x: generator.ToCamel(x, lower_initial=True),
+ "to_camel": generator.ToCamel,
"union_decode_snippet": self._JavaScriptUnionDecodeSnippet,
"union_encode_snippet": self._JavaScriptUnionEncodeSnippet,
"validate_array_params": self._JavaScriptValidateArrayParams,
@@ -158,11 +157,13 @@
if self.variant:
raise Exception("Variants not supported in JavaScript bindings.")
+ # TODO(yzshen): Remove this method once the old JS bindings go away.
+ self._SetUniqueNameForImports()
+
self.Write(self._GenerateAMDModule(),
self.MatchMojomFilePath("%s.js" % self.module.name))
- def _GetImports(self):
- # TODO(yzshen): Remove this method once the old JS bindings go away.
+ def _SetUniqueNameForImports(self):
used_names = set()
for each_import in self.module.imports:
simple_name = each_import.name.split(".")[0]
@@ -178,15 +179,6 @@
used_names.add(unique_name)
each_import.unique_name = unique_name + "$"
counter += 1
- return self.module.imports
-
- def _GetImportedInterfaces(self):
- interface_to_import = {};
- for each_import in self.module.imports:
- for each_interface in each_import.interfaces:
- name = each_interface.name
- interface_to_import[name] = each_import.unique_name + "." + name
- return interface_to_import;
def _JavaScriptType(self, kind):
name = []
@@ -381,3 +373,11 @@
def _ExpressionToText(self, value):
return self._TranslateConstants(value)
+ def _GetStructsFromMethods(self):
+ result = []
+ for interface in self.module.interfaces:
+ for method in interface.methods:
+ result.append(method.param_struct)
+ if method.response_param_struct is not None:
+ result.append(method.response_param_struct)
+ return result
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py
index 24fe610..c6f90a3 100755
--- a/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -41,6 +41,7 @@
import mojom.fileutil as fileutil
from mojom.generate import translate
from mojom.generate import template_expander
+from mojom.generate.generator import AddComputedData
from mojom.parse.parser import Parse
@@ -198,6 +199,7 @@
module.path = module.path.replace('\\', '/')
if self._should_generate(rel_filename.path):
+ AddComputedData(module)
for language, generator_module in generator_modules.iteritems():
generator = generator_module.Generator(
module, args.output_dir, typemap=self._typemap.get(language, {}),
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
index 0e64af7..04850d7 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -12,17 +12,25 @@
import mojom.fileutil as fileutil
import pack
+
def ExpectedArraySize(kind):
if mojom.IsArrayKind(kind):
return kind.length
return None
-def StudlyCapsToCamel(studly):
- return studly[0].lower() + studly[1:]
-def UnderToCamel(under):
- """Converts underscore_separated strings to CamelCase strings."""
- return ''.join(word.capitalize() for word in under.split('_'))
+def ToCamel(identifier, lower_initial=False, dilimiter='_'):
+ """Splits |identifier| using |dilimiter|, makes the first character of each
+ word uppercased (but makes the first character of the first word lowercased
+ if |lower_initial| is set to True), and joins the words. Please note that for
+ each word, all the characters except the first one are untouched.
+ """
+ result = ''.join(
+ word[0].upper() + word[1:] for word in identifier.split(dilimiter))
+ if lower_initial:
+ result = result[0].lower() + result[1:]
+ return result
+
def WriteFile(contents, full_path):
# Make sure the containing directory exists.
@@ -33,6 +41,76 @@
with open(full_path, "w+") as f:
f.write(contents)
+
+def AddComputedData(module):
+ """Adds computed data to the given module. The data is computed once and
+ used repeatedly in the generation process."""
+
+ def _AddStructComputedData(exported, struct):
+ struct.packed = pack.PackedStruct(struct)
+ struct.bytes = pack.GetByteLayout(struct.packed)
+ struct.versions = pack.GetVersionInfo(struct.packed)
+ struct.exported = exported
+
+ def _AddUnionComputedData(union):
+ ordinal = 0
+ for field in union.fields:
+ if field.ordinal is not None:
+ ordinal = field.ordinal
+ field.ordinal = ordinal
+ ordinal += 1
+
+ def _AddInterfaceComputedData(interface):
+ next_ordinal = 0
+ interface.version = 0
+ for method in interface.methods:
+ if method.ordinal is None:
+ method.ordinal = next_ordinal
+ next_ordinal = method.ordinal + 1
+
+ if method.min_version is not None:
+ interface.version = max(interface.version, method.min_version)
+
+ method.param_struct = _GetStructFromMethod(method)
+ interface.version = max(interface.version,
+ method.param_struct.versions[-1].version)
+
+ if method.response_parameters is not None:
+ method.response_param_struct = _GetResponseStructFromMethod(method)
+ interface.version = max(
+ interface.version,
+ method.response_param_struct.versions[-1].version)
+ else:
+ method.response_param_struct = None
+
+ def _GetStructFromMethod(method):
+ """Converts a method's parameters into the fields of a struct."""
+ params_class = "%s_%s_Params" % (method.interface.name, method.name)
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.parameters:
+ struct.AddField(param.name, param.kind, param.ordinal,
+ attributes=param.attributes)
+ _AddStructComputedData(False, struct)
+ return struct
+
+ def _GetResponseStructFromMethod(method):
+ """Converts a method's response_parameters into the fields of a struct."""
+ params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
+ struct = mojom.Struct(params_class, module=method.interface.module)
+ for param in method.response_parameters:
+ struct.AddField(param.name, param.kind, param.ordinal,
+ attributes=param.attributes)
+ _AddStructComputedData(False, struct)
+ return struct
+
+ for struct in module.structs:
+ _AddStructComputedData(True, struct)
+ for union in module.unions:
+ _AddUnionComputedData(union)
+ for interface in module.interfaces:
+ _AddInterfaceComputedData(interface)
+
+
class Generator(object):
# Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
# files to stdout.
@@ -52,24 +130,6 @@
self.export_header = export_header
self.generate_non_variant_code = generate_non_variant_code
- def GetStructsFromMethods(self):
- result = []
- for interface in self.module.interfaces:
- for method in interface.methods:
- result.append(self._GetStructFromMethod(method))
- if method.response_parameters != None:
- result.append(self._GetResponseStructFromMethod(method))
- return result
-
- def GetStructs(self):
- return map(partial(self._AddStructComputedData, True), self.module.structs)
-
- def GetUnions(self):
- return map(self._AddUnionComputedData, self.module.unions)
-
- def GetInterfaces(self):
- return map(self._AddInterfaceComputedData, self.module.interfaces)
-
# Prepend the filename with a directory that matches the directory of the
# original .mojom file, relative to the import root.
def MatchMojomFilePath(self, filename):
@@ -93,61 +153,3 @@
"""Returns global mappings for the template generation."""
return {}
- def _AddStructComputedData(self, exported, struct):
- """Adds computed data to the given struct. The data is computed once and
- used repeatedly in the generation process."""
- struct.packed = pack.PackedStruct(struct)
- struct.bytes = pack.GetByteLayout(struct.packed)
- struct.versions = pack.GetVersionInfo(struct.packed)
- struct.exported = exported
- return struct
-
- def _AddUnionComputedData(self, union):
- """Adds computed data to the given union. The data is computed once and
- used repeatedly in the generation process."""
- ordinal = 0
- for field in union.fields:
- if field.ordinal is not None:
- ordinal = field.ordinal
- field.ordinal = ordinal
- ordinal += 1
- return union
-
- def _AddInterfaceComputedData(self, interface):
- """Adds computed data to the given interface. The data is computed once and
- used repeatedly in the generation process."""
- interface.version = 0
- for method in interface.methods:
- if method.min_version is not None:
- interface.version = max(interface.version, method.min_version)
-
- method.param_struct = self._GetStructFromMethod(method)
- interface.version = max(interface.version,
- method.param_struct.versions[-1].version)
-
- if method.response_parameters is not None:
- method.response_param_struct = self._GetResponseStructFromMethod(method)
- interface.version = max(
- interface.version,
- method.response_param_struct.versions[-1].version)
- else:
- method.response_param_struct = None
- return interface
-
- def _GetStructFromMethod(self, method):
- """Converts a method's parameters into the fields of a struct."""
- params_class = "%s_%s_Params" % (method.interface.name, method.name)
- struct = mojom.Struct(params_class, module=method.interface.module)
- for param in method.parameters:
- struct.AddField(param.name, param.kind, param.ordinal,
- attributes=param.attributes)
- return self._AddStructComputedData(False, struct)
-
- def _GetResponseStructFromMethod(self, method):
- """Converts a method's response_parameters into the fields of a struct."""
- params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
- struct = mojom.Struct(params_class, module=method.interface.module)
- for param in method.response_parameters:
- struct.AddField(param.name, param.kind, param.ordinal,
- attributes=param.attributes)
- return self._AddStructComputedData(False, struct)
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py
deleted file mode 100644
index 9966b0b..0000000
--- a/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2015 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.
-
-import unittest
-
-import module as mojom
-import generator
-
-class TestGenerator(unittest.TestCase):
-
- def testGetUnionsAddsOrdinals(self):
- module = mojom.Module()
- union = module.AddUnion('a')
- union.AddField('a', mojom.BOOL)
- union.AddField('b', mojom.BOOL)
- union.AddField('c', mojom.BOOL, ordinal=10)
- union.AddField('d', mojom.BOOL)
-
- gen = generator.Generator(module)
- union = gen.GetUnions()[0]
- ordinals = [field.ordinal for field in union.fields]
-
- self.assertEquals([0, 1, 10, 11], ordinals)
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index fd346e2..906d3fd 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -623,9 +623,8 @@
class Module(object):
- def __init__(self, name=None, namespace=None, attributes=None):
- self.name = name
- self.path = name
+ def __init__(self, path=None, namespace=None, attributes=None):
+ self.path = path
self.namespace = namespace
self.structs = []
self.unions = []
@@ -639,10 +638,10 @@
def Repr(self, as_ref=True):
if as_ref:
- return '<%s name=%r namespace=%r>' % (
- self.__class__.__name__, self.name, self.namespace)
+ return '<%s path=%r namespace=%r>' % (
+ self.__class__.__name__, self.path, self.namespace)
else:
- return GenericRepr(self, {'name': False, 'namespace': False,
+ return GenericRepr(self, {'path': False, 'namespace': False,
'attributes': False, 'structs': False,
'interfaces': False, 'unions': False})
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
index bd5f326..5e4183a 100644
--- a/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
+++ b/mojo/public/tools/bindings/pylib/mojom/generate/translate.py
@@ -608,10 +608,4 @@
{mojom.Module} An AST for the mojom.
"""
module = _Module(tree, name, imports)
- for interface in module.interfaces:
- next_ordinal = 0
- for method in interface.methods:
- if method.ordinal is None:
- method.ordinal = next_ordinal
- next_ordinal = method.ordinal + 1
return module
diff --git a/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py b/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py
index a684773..e037c96 100644
--- a/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py
+++ b/mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py
@@ -27,10 +27,14 @@
class StringManipulationTest(unittest.TestCase):
"""generator contains some string utilities, this tests only those."""
- def testUnderToCamel(self):
- """Tests UnderToCamel which converts underscore_separated to CamelCase."""
- self.assertEquals("CamelCase", generator.UnderToCamel("camel_case"))
- self.assertEquals("CamelCase", generator.UnderToCamel("CAMEL_CASE"))
+ def testToCamel(self):
+ self.assertEquals("CamelCase", generator.ToCamel("camel_case"))
+ self.assertEquals("CAMELCASE", generator.ToCamel("CAMEL_CASE"))
+ self.assertEquals("camelCase", generator.ToCamel("camel_case",
+ lower_initial=True))
+ self.assertEquals("CamelCase", generator.ToCamel("camel case",
+ dilimiter=' '))
+ self.assertEquals("CaMelCaSe", generator.ToCamel("caMel_caSe"))
if __name__ == "__main__":
unittest.main()