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

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

Issue 1433183002: Generate Mojom Types for Dart (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Add test_included_unions to the _mojo_for_test_only package Created 5 years, 1 month 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_dart_generator.py
diff --git a/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/mojo/public/tools/bindings/generators/mojom_dart_generator.py
index 034588680ec55e6a4a00a4cedc2f2b8a4e1cfe89..c95cb9d5b76719ded6e44d9b89ae03127e5341ee 100644
--- a/mojo/public/tools/bindings/generators/mojom_dart_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_dart_generator.py
@@ -70,6 +70,32 @@ _kind_to_dart_decl_type = {
mojom.NULLABLE_STRING: "String"
}
+_kind_to_mojom_type = {
+ mojom.BOOL: "BOOL",
+ mojom.INT8: "INT8",
+ mojom.UINT8: "UINT8",
+ mojom.INT16: "INT16",
+ mojom.UINT16: "UINT16",
+ mojom.INT32: "INT32",
+ mojom.UINT32: "UINT32",
+ mojom.FLOAT: "FLOAT",
+ mojom.HANDLE: "UNSPECIFIED",
+ mojom.DCPIPE: "DATA_PIPE_CONSUMER",
+ mojom.DPPIPE: "DATA_PIPE_PRODUCER",
+ mojom.MSGPIPE: "MESSAGE_PIPE",
+ mojom.SHAREDBUFFER: "SHARED_BUFFER",
+ mojom.NULLABLE_HANDLE: "UNSPECIFIED",
+ mojom.NULLABLE_DCPIPE: "DATA_PIPE_CONSUMER",
+ mojom.NULLABLE_DPPIPE: "DATA_PIPE_PRODUCER",
+ mojom.NULLABLE_MSGPIPE: "MESSAGE_PIPE",
+ mojom.NULLABLE_SHAREDBUFFER: "SHARED_BUFFER",
+ mojom.INT64: "INT64",
+ mojom.UINT64: "UINT64",
+ mojom.DOUBLE: "DOUBLE",
+ mojom.STRING: "STRING",
+ mojom.NULLABLE_STRING: "STRING"
+}
+
_spec_to_decode_method = {
mojom.BOOL.spec: 'decodeBool',
mojom.DCPIPE.spec: 'decodeConsumerHandle',
@@ -122,6 +148,15 @@ _spec_to_encode_method = {
mojom.UINT8.spec: 'encodeUint8',
}
+# The mojom_types.mojom and service_describer.mojom files are special because
+# they are used to generate mojom Type's and ServiceDescription implementations.
+_service_describer_pkg_short = "service_describer"
+_service_describer_pkg = "package:mojo/mojo/%s.mojom.dart" % \
+ _service_describer_pkg_short
+_mojom_types_pkg_short = "mojom_types"
+_mojom_types_pkg = "package:mojo/mojo/%s.mojom.dart" % \
+ _mojom_types_pkg_short
+
def GetDartType(kind):
if kind.imported_from:
return kind.imported_from["unique_name"] + "." + GetNameForElement(kind)
@@ -172,6 +207,27 @@ def DartDeclType(kind):
if mojom.IsEnumKind(kind):
return GetDartType(kind)
+def GetMojomTypeValue(kind, typepkg=''):
+ if not kind in _kind_to_mojom_type:
+ return ''
+
+ nullable = 'true' if mojom.IsNullableKind(kind) else 'false'
+ w = _kind_to_mojom_type[kind]
+ if kind == mojom.BOOL or kind == mojom.FLOAT or kind == mojom.DOUBLE or \
+ mojom.IsIntegralKind(kind):
+
+ return 'new %sType()..simpleType = %sSimpleType.%s' % (typepkg, typepkg, w)
+ elif mojom.IsAnyHandleKind(kind):
+ return ('new %sType()\n..handleType = (new %sHandleType()' +
+ '\n..kind = %sHandleTypeKind.%s' +
+ '\n..nullable = %s)') % \
+ (typepkg, typepkg, typepkg, w, nullable)
+ elif mojom.IsStringKind(kind):
+ return 'new %sType()\n..stringType = (new %sStringType()..nullable = %s)' \
+ % (typepkg, typepkg, nullable)
+ else:
+ raise Exception('Missing case for kind: %s' % kind)
+
def NameToComponent(name):
# insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
# HTTP_Entry2_FooBar)
@@ -382,6 +438,9 @@ def IsPointerArrayKind(kind):
def IsEnumArrayKind(kind):
return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind)
+def IsImportedKind(kind):
+ return hasattr(kind, 'imported_from') and kind.imported_from is not None
azani 2015/11/20 20:17:58 unless you need to differentiate between an empty
alexfandrianto 2015/11/21 03:58:34 I didn't know that, thanks. (I like being very spe
+
def ParseStringAttribute(attribute):
assert isinstance(attribute, basestring)
return attribute
@@ -392,12 +451,48 @@ def GetPackage(module):
# Default package.
return 'mojom'
+def GetPackageName(module):
+ return module.name.split('.')[0]
+
def GetImportUri(module):
package = GetPackage(module);
elements = module.namespace.split('.')
elements.append("%s" % module.name)
return os.path.join(package, *elements)
+identifier_cache = {}
azani 2015/11/20 20:17:59 I don't think you're actually using this as a cach
alexfandrianto 2015/11/21 03:58:34 How about identifier_store?
+def GetIdentifier(kind):
+ # Use the kind's module to determine the package name.
+ if hasattr(kind, 'module'):
+ package = GetPackageName(kind.module)
+ elif mojom.IsInterfaceRequestKind(kind):
+ package = GetPackageName(kind.kind.module)
+ else:
+ return ''
azani 2015/11/20 20:17:58 This looks like an error condition. Can you raise
alexfandrianto 2015/11/21 03:58:34 I call GetIdentifier with every kind, including si
+
+ # Most kinds have a name, but those that don't should rely on their spec.
azani 2015/11/20 20:17:58 In which case does a kind not have a name? You sho
alexfandrianto 2015/11/21 03:58:34 I moved the name computation earlier, so I have no
+ # Since spec can have : and ? characters, these must be replaced. Since ? is
+ # replaced with '', the caller must keep track of optionality on its own.
+ name_or_spec = (kind.name if hasattr(kind, 'name') else kind.spec)
+ package_unique = name_or_spec.replace(':', '_').replace('?', '')
+ return '%s_%s' % (package, package_unique)
+
+def StoreIdentifier(identifier, cache_name):
+ if not cache_name in identifier_cache:
+ identifier_cache[cache_name] = {}
azani 2015/11/20 20:17:58 You could use a defaultdict instead.
alexfandrianto 2015/11/21 03:58:34 I'll use defaultdict(lambda : defaultdict(bool))
+ identifier_cache[cache_name][identifier] = True
+ return ''
+
+def CheckIdentifier(identifier, cache_name):
+ if not cache_name in identifier_cache:
+ identifier_cache[cache_name] = {}
+ return identifier in identifier_cache[cache_name]
+
+# Get the mojom type's identifier suffix.
azani 2015/11/20 20:17:59 Put this comment in the function's =docstring.
alexfandrianto 2015/11/21 03:58:34 Done.
+def GetMojomTypeIdentifier(kind):
+ # Since this should be unique, it is based on the type's identifier.
+ return "_%s__" % GetIdentifier(kind)
+
class Generator(generator.Generator):
dart_filters = {
@@ -407,6 +502,13 @@ class Generator(generator.Generator):
'default_value': DartDefaultValue,
'encode_method': EncodeMethod,
'expression_to_text': ExpressionToText,
+ 'identifier': GetIdentifier,
+ 'identifier_check': CheckIdentifier,
azani 2015/11/20 20:17:59 Can you explain what the purpose of identifier_sto
alexfandrianto 2015/11/21 03:58:34 The purpose is to detect if we have already genera
+ 'identifier_store': StoreIdentifier,
+ 'mojom_type_value': GetMojomTypeValue,
+ 'mojom_type_identifier': GetMojomTypeIdentifier,
+ 'is_imported_kind': IsImportedKind,
+ 'is_array_kind': mojom.IsArrayKind,
'is_map_kind': mojom.IsMapKind,
'is_nullable_kind': mojom.IsNullableKind,
'is_pointer_array_kind': IsPointerArrayKind,
@@ -414,6 +516,8 @@ class Generator(generator.Generator):
'is_struct_kind': mojom.IsStructKind,
'is_union_kind': mojom.IsUnionKind,
'is_enum_kind': mojom.IsEnumKind,
+ 'is_interface_kind': mojom.IsInterfaceKind,
+ 'is_interface_request_kind': mojom.IsInterfaceRequestKind,
'dart_true_false': GetDartTrueFalse,
'dart_type': DartDeclType,
'name': GetNameForElement,
@@ -421,9 +525,17 @@ class Generator(generator.Generator):
'interface_response_name': GetInterfaceResponseName,
'dot_to_underscore': DotToUnderscore,
'is_cloneable_kind': mojom.IsCloneableKind,
+ 'upper_camel': UpperCamelCase,
}
+ # TODO: This value should be settable via arguments. If False, then mojom type
+ # information will not be generated.
+ should_gen_mojom_types = True
azani 2015/11/20 20:17:59 Given that most people likely won't want to genera
alexfandrianto 2015/11/21 03:58:34 I tried to plumb this most of the way through. Thi
+
def GetParameters(self, args):
+ package = GetPackageName(self.module)
+ defInterface = len(self.module.interfaces) > 0
+
return {
"namespace": self.module.namespace,
"imports": self.GetImports(args),
@@ -435,6 +547,21 @@ class Generator(generator.Generator):
"interfaces": self.GetInterfaces(),
"imported_interfaces": self.GetImportedInterfaces(),
"imported_from": self.ImportedFrom(),
+ "typepkg": '%s.' % _mojom_types_pkg_short \
azani 2015/11/20 20:17:59 In order to enhance readability, you could just se
alexfandrianto 2015/11/21 03:58:34 Done.
+ if package != _mojom_types_pkg_short else '',
+ "descpkg": '%s.' % _service_describer_pkg_short \
+ if package != _service_describer_pkg_short else '',
+ "mojom_types_import": 'import \'%s\' as %s;' % \
+ (_mojom_types_pkg, _mojom_types_pkg_short) \
+ if package != _mojom_types_pkg_short else '',
+ "service_describer_import": 'import \'%s\' as %s;' % \
+ (_service_describer_pkg, _service_describer_pkg_short) \
+ if defInterface and package != _service_describer_pkg_short else '',
+ }
+
+ def GetGlobals(self):
+ return {
+ 'should_gen_mojom_types': self.should_gen_mojom_types,
}
@UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)

Powered by Google App Engine
This is Rietveld 408576698