Index: mojo/public/tools/bindings/generators/mojom_go_generator.py |
diff --git a/mojo/public/tools/bindings/generators/mojom_go_generator.py b/mojo/public/tools/bindings/generators/mojom_go_generator.py |
index 7b1c7ac8920cce3fc3d6ca2834880a4a8f1aa672..1443665294dc464d09f2926f894d656c24a25a4b 100644 |
--- a/mojo/public/tools/bindings/generators/mojom_go_generator.py |
+++ b/mojo/public/tools/bindings/generators/mojom_go_generator.py |
@@ -5,6 +5,7 @@ |
'''Generates Go source files from a mojom.Module.''' |
from itertools import chain |
+import base64 |
import os |
import re |
@@ -15,50 +16,62 @@ import mojom.generate.module as mojom |
import mojom.generate.pack as pack |
class KindInfo(object): |
- def __init__(self, go_type, encode_suffix, decode_suffix, bit_size): |
+ def __init__(self, go_type, encode_suffix, decode_suffix, bit_size, type_template): |
azani
2015/10/12 21:13:08
Can you construct the type_template programmatical
alexfandrianto
2015/10/16 21:25:49
Done.
|
self.go_type = go_type |
self.encode_suffix = encode_suffix |
self.decode_suffix = decode_suffix |
self.bit_size = bit_size |
+ self.type_template = type_template |
_kind_infos = { |
- mojom.BOOL: KindInfo('bool', 'Bool', 'Bool', 1), |
- mojom.INT8: KindInfo('int8', 'Int8', 'Int8', 8), |
- mojom.UINT8: KindInfo('uint8', 'Uint8', 'Uint8', 8), |
- mojom.INT16: KindInfo('int16', 'Int16', 'Int16', 16), |
- mojom.UINT16: KindInfo('uint16', 'Uint16', 'Uint16', 16), |
- mojom.INT32: KindInfo('int32', 'Int32', 'Int32', 32), |
- mojom.UINT32: KindInfo('uint32', 'Uint32', 'Uint32', 32), |
- mojom.FLOAT: KindInfo('float32', 'Float32', 'Float32', 32), |
+ mojom.BOOL: KindInfo('bool', 'Bool', 'Bool', 1, '%sTypeSimpleType{%sSimpleType_Bool}'), |
+ mojom.INT8: KindInfo('int8', 'Int8', 'Int8', 8, '%sTypeSimpleType{%sSimpleType_InT8}'), |
+ mojom.UINT8: KindInfo('uint8', 'Uint8', 'Uint8', 8, '%sTypeSimpleType{%sSimpleType_UinT8}'), |
+ mojom.INT16: KindInfo('int16', 'Int16', 'Int16', 16, '%sTypeSimpleType{%sSimpleType_InT16}'), |
+ mojom.UINT16: KindInfo('uint16', 'Uint16', 'Uint16', 16, '%sTypeSimpleType{%sSimpleType_UinT16}'), |
+ mojom.INT32: KindInfo('int32', 'Int32', 'Int32', 32, '%sTypeSimpleType{%sSimpleType_InT32}'), |
+ mojom.UINT32: KindInfo('uint32', 'Uint32', 'Uint32', 32, '%sTypeSimpleType{%sSimpleType_UinT32}'), |
+ mojom.FLOAT: KindInfo('float32', 'Float32', 'Float32', 32, '%sTypeSimpleType{%sSimpleType_Float}'), |
mojom.HANDLE: KindInfo( |
- 'system.Handle', 'Handle', 'Handle', 32), |
+ 'system.Handle', 'Handle', 'Handle', 32, '%sTypeHandleType{%sHandleType{Nullable: false, Kind: %sHandleType_Kind_Unspecified}}'), |
mojom.DCPIPE: KindInfo( |
- 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32), |
+ 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: false, Kind: %sHandleType_Kind_DataPipeConsumer}}'), |
mojom.DPPIPE: KindInfo( |
- 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32), |
+ 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: false, Kind: %sHandleType_Kind_DataPipeProducer}}'), |
mojom.MSGPIPE: KindInfo( |
- 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32), |
+ 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: false, Kind: %sHandleType_Kind_MessagePipe}}'), |
mojom.SHAREDBUFFER: KindInfo( |
- 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32), |
+ 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: false, Kind: %sHandleType_Kind_SharedBuffer}}'), |
mojom.NULLABLE_HANDLE: KindInfo( |
- 'system.Handle', 'Handle', 'Handle', 32), |
+ 'system.Handle', 'Handle', 'Handle', 32, '%sTypeHandleType{%sHandleType{Nullable: true, Kind: %sHandleType_Kind_Unspecified}}'), |
mojom.NULLABLE_DCPIPE: KindInfo( |
- 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32), |
+ 'system.ConsumerHandle', 'Handle', 'ConsumerHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: true, Kind: %sHandleType_Kind_DataPipeConsumer}}'), |
mojom.NULLABLE_DPPIPE: KindInfo( |
- 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32), |
+ 'system.ProducerHandle', 'Handle', 'ProducerHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: true, Kind: %sHandleType_Kind_DataPipeProducer}}'), |
mojom.NULLABLE_MSGPIPE: KindInfo( |
- 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32), |
+ 'system.MessagePipeHandle', 'Handle', 'MessagePipeHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: true, Kind: %sHandleType_Kind_MessagePipe}}'), |
mojom.NULLABLE_SHAREDBUFFER: KindInfo( |
- 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32), |
- mojom.INT64: KindInfo('int64', 'Int64', 'Int64', 64), |
- mojom.UINT64: KindInfo('uint64', 'Uint64', 'Uint64', 64), |
- mojom.DOUBLE: KindInfo('float64', 'Float64', 'Float64', 64), |
- mojom.STRING: KindInfo('string', 'String', 'String', 64), |
- mojom.NULLABLE_STRING: KindInfo('string', 'String', 'String', 64), |
+ 'system.SharedBufferHandle', 'Handle', 'SharedBufferHandle', 32, '%sTypeHandleType{%sHandleType{Nullable: true, Kind: %sHandleType_Kind_SharedBuffer}}'), |
+ mojom.INT64: KindInfo('int64', 'Int64', 'Int64', 64, '%sTypeSimpleType{%sSimpleType_InT64}'), |
+ mojom.UINT64: KindInfo('uint64', 'Uint64', 'Uint64', 64, '%sTypeSimpleType{%sSimpleType_UinT64}'), |
+ mojom.DOUBLE: KindInfo('float64', 'Float64', 'Float64', 64, '%sTypeSimpleType{%sSimpleType_Double}'), |
+ mojom.STRING: KindInfo('string', 'String', 'String', 64, '%sTypeStringType{%sStringType{false}}'), |
+ mojom.NULLABLE_STRING: KindInfo('string', 'String', 'String', 64, '%sTypeStringType{%sStringType{true}}'), |
} |
+# _imports keeps track of the imports that the .go.mojom file needs to import. |
_imports = {} |
+# _mojom_imports keeps a list of the other .mojom files imported by this one. |
+_mojom_imports = {} |
+ |
+# 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 = "mojo/public/interfaces/bindings/service_describer" |
azani
2015/10/12 21:13:07
Maybe do:
_service_describer_pkg_short = "service_
alexfandrianto
2015/10/16 21:25:49
Done.
|
+_service_describer_pkg_short = "service_describer" |
+_mojom_types_pkg = "mojo/public/interfaces/bindings/mojom_types" |
+_mojom_types_pkg_short = "mojom_types" |
+ |
def GetBitSize(kind): |
if isinstance(kind, (mojom.Union)): |
return 128 |
@@ -186,18 +199,27 @@ def EncodeSuffix(kind): |
return EncodeSuffix(mojom.MSGPIPE) |
return _kind_infos[kind].encode_suffix |
+# This helper assists in the production of mojom_types.Type for simple kinds. |
+# See _kind_infos above. |
+def GetMojomTypeValue(kind, typepkg=''): |
+ if not kind in _kind_infos: |
+ return '' |
+ if mojom.IsAnyHandleKind(kind): |
+ return _kind_infos[kind].type_template % (typepkg, typepkg, typepkg) |
+ return _kind_infos[kind].type_template % (typepkg, typepkg) |
+ |
def GetPackageName(module): |
return module.name.split('.')[0] |
-def GetPackageNameForElement(element): |
+def GetPackageNameForElement(element, default=''): |
if not hasattr(element, 'imported_from') or not element.imported_from: |
- return '' |
+ return default |
path = '' |
if element.imported_from['module'].path: |
path += GetPackagePath(element.imported_from['module']) |
if path in _imports: |
return _imports[path] |
- return '' |
+ return default |
def GetQualifiedName(name, package=None, exported=True): |
if not package: |
@@ -220,6 +242,7 @@ def GetAllEnums(module): |
# Adds an import required to use the provided |element|. |
# The required import is stored at '_imports'. |
+# The mojom imports are also stored separately in '_mojom_imports'. |
def AddImport(module, element): |
if not isinstance(element, mojom.Kind): |
return |
@@ -244,10 +267,34 @@ def AddImport(module, element): |
if path in _imports: |
return |
name = GetPackageName(imported['module']) |
- while name in _imports.values(): |
+ while name in _imports.values(): # This avoids repeated names. |
name += '_' |
_imports[path] = name |
+ _mojom_imports[path] = name |
+ |
+# The identifier cache is used by the Type generator to determine if a type has |
+# already been generated or not. This prevents over-generation of the same type |
+# when it is referred to in multiple ways. |
+identifier_cache = {} |
+def GetIdentifier(kind, default): |
+ package = GetPackageNameForElement(kind, default) |
+ |
+ # Most kinds have a name, but those that don't should rely on their spec. |
+ # Since spec can have : and ? characters, these must be replaced. Since ? is |
+ # replaced with '', the caller must keep track of optionality on its own. |
+ package_unique = (kind.name if hasattr(kind, 'name') else kind.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] = {} |
+ 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] |
class Generator(generator.Generator): |
go_filters = { |
@@ -258,6 +305,9 @@ class Generator(generator.Generator): |
'go_type': GetGoType, |
'expression_to_text': ExpressionToText, |
'has_response': lambda method: method.response_parameters is not None, |
+ 'identifier': GetIdentifier, |
+ 'identifier_check': CheckIdentifier, |
+ 'identifier_store': StoreIdentifier, |
'is_array': mojom.IsArrayKind, |
'is_enum': mojom.IsEnumKind, |
'is_handle': mojom.IsAnyHandleKind, |
@@ -271,6 +321,7 @@ class Generator(generator.Generator): |
'is_struct': mojom.IsStructKind, |
'is_union': mojom.IsUnionKind, |
'qualified': GetQualifiedName, |
+ 'mojom_type': GetMojomTypeValue, |
'name': GetNameForElement, |
'unqualified_name': GetUnqualifiedNameForElement, |
'package': GetPackageNameForElement, |
@@ -278,13 +329,17 @@ class Generator(generator.Generator): |
} |
def GetParameters(self): |
+ package = GetPackageName(self.module) |
return { |
'enums': GetAllEnums(self.module), |
'imports': self.GetImports(), |
'interfaces': self.GetInterfaces(), |
- 'package': GetPackageName(self.module), |
+ 'mojom_imports': self.GetMojomImports(), |
+ 'package': package, |
'structs': self.GetStructs(), |
- 'unions': self.GetUnions(), |
+ 'descpkg': '%s.' % _service_describer_pkg_short if package != _service_describer_pkg_short else '', |
+ 'typepkg': '%s.' % _mojom_types_pkg_short if package != _mojom_types_pkg_short else '', |
+ 'unions': self.GetUnions() |
} |
@UseJinja('go_templates/source.tmpl', filters=go_filters) |
@@ -344,6 +399,17 @@ class Generator(generator.Generator): |
if field.value: |
AddImport(self.module, field.value) |
+ num_user_defined_types = len(self.module.interfaces) + \ |
+ len(self.module.unions) + len(all_structs) + len(GetAllEnums(self.module)) |
+ if num_user_defined_types > 0 \ |
+ and GetPackageName(self.module) != _mojom_types_pkg_short: |
+ _imports[_mojom_types_pkg] = _mojom_types_pkg_short |
+ |
+ if len(self.module.interfaces) > 0 \ |
+ and GetPackageName(self.module) != _mojom_types_pkg_short \ |
+ and GetPackageName(self.module) != _service_describer_pkg_short: |
+ _imports[_service_describer_pkg] = _service_describer_pkg_short |
+ |
# TODO(rogulenko): add these after generating constants and struct defaults. |
# for constant in GetAllConstants(self.module): |
# AddImport(self.module, constant.value) |
@@ -356,6 +422,11 @@ class Generator(generator.Generator): |
imports_list.append('%s "%s"' % (_imports[i], i)) |
return sorted(imports_list) |
+ def GetMojomImports(self): |
azani
2015/10/12 21:13:07
Instead, change GetImports to return a tuple of it
alexfandrianto
2015/10/16 21:25:49
Done.
|
+ # GetImports (idempotent) prepares the _imports and _mojom_imports maps. |
+ self.GetImports() |
+ return _mojom_imports |
+ |
# Overrides the implementation from the base class in order to customize the |
# struct and field names. |
def _GetStructFromMethod(self, method): |