Chromium Code Reviews| 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): |