| 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..e9b6bfb9735de334c6ac5d52fe6ea575675654ad 100644
|
| --- a/mojo/public/tools/bindings/generators/mojom_go_generator.py
|
| +++ b/mojo/public/tools/bindings/generators/mojom_go_generator.py
|
| @@ -57,8 +57,20 @@ _kind_infos = {
|
| mojom.NULLABLE_STRING: KindInfo('string', 'String', 'String', 64),
|
| }
|
|
|
| +# _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_short = "service_describer"
|
| +_service_describer_pkg = "mojo/public/interfaces/bindings/%s" % \
|
| + _service_describer_pkg_short
|
| +_mojom_types_pkg_short = "mojom_types"
|
| +_mojom_types_pkg = "mojo/public/interfaces/bindings/%s" % _mojom_types_pkg_short
|
| +
|
| def GetBitSize(kind):
|
| if isinstance(kind, (mojom.Union)):
|
| return 128
|
| @@ -186,6 +198,40 @@ 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 ''
|
| +
|
| + nullable = 'true' if mojom.IsNullableKind(kind) else 'false'
|
| + if kind == mojom.BOOL or kind == mojom.FLOAT or kind == mojom.DOUBLE or \
|
| + mojom.IsIntegralKind(kind):
|
| +
|
| + kind_name = UpperCamelCase(_kind_infos[kind].decode_suffix.upper())
|
| + if kind == mojom.FLOAT:
|
| + kind_name = "Float"
|
| + elif kind == mojom.DOUBLE:
|
| + kind_name = "Double"
|
| + return '%sTypeSimpleType{%sSimpleType_%s}' % (typepkg, typepkg, kind_name)
|
| + elif mojom.IsAnyHandleKind(kind):
|
| + kind_name = 'Unspecified'
|
| + if kind == mojom.DCPIPE:
|
| + kind_name = 'DataPipeConsumer'
|
| + elif kind == mojom.DPPIPE:
|
| + kind_name = 'DataPipeProducer'
|
| + elif kind == mojom.MSGPIPE:
|
| + kind_name = 'MessagePipe'
|
| + elif kind == mojom.SHAREDBUFFER:
|
| + kind_name = 'SharedBuffer'
|
| + return '%sTypeHandleType{%sHandleType{' \
|
| + 'Nullable: %s, Kind: %sHandleType_Kind_%s}}' % \
|
| + (typepkg, typepkg, nullable, typepkg, kind_name)
|
| + elif mojom.IsStringKind(kind):
|
| + return '%sTypeStringType{%sStringType{%s}}' % (typepkg, typepkg, nullable)
|
| + else:
|
| + raise Exception('Missing case for kind: %s' % kind)
|
| +
|
| def GetPackageName(module):
|
| return module.name.split('.')[0]
|
|
|
| @@ -220,6 +266,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 +291,46 @@ 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):
|
| + # 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 ''
|
| +
|
| + # 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.
|
| + 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] = {}
|
| + 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.
|
| +def GetMojomTypeIdentifier(kind):
|
| + # Since this should be unique, it is based on the type's identifier.
|
| + return "%s__" % GetIdentifier(kind)
|
|
|
| class Generator(generator.Generator):
|
| go_filters = {
|
| @@ -258,6 +341,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,20 +357,32 @@ class Generator(generator.Generator):
|
| 'is_struct': mojom.IsStructKind,
|
| 'is_union': mojom.IsUnionKind,
|
| 'qualified': GetQualifiedName,
|
| + 'mojom_type': GetMojomTypeValue,
|
| + 'mojom_type_identifier': GetMojomTypeIdentifier,
|
| 'name': GetNameForElement,
|
| 'unqualified_name': GetUnqualifiedNameForElement,
|
| 'package': GetPackageNameForElement,
|
| 'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines())
|
| }
|
|
|
| + # TODO: This value should be settable via arguments. If False, then mojom type
|
| + # information will not be generated.
|
| + should_gen_mojom_types = True
|
| +
|
| def GetParameters(self):
|
| + package = GetPackageName(self.module)
|
| return {
|
| 'enums': GetAllEnums(self.module),
|
| - 'imports': self.GetImports(),
|
| + 'imports': self.GetImports()[0],
|
| '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)
|
| @@ -305,11 +403,15 @@ class Generator(generator.Generator):
|
| return {
|
| 'namespace': self.module.namespace,
|
| 'module': self.module,
|
| + 'should_gen_mojom_types': self.should_gen_mojom_types,
|
| }
|
|
|
| # Scans |self.module| for elements that require imports and adds all found
|
| - # imports to '_imports' dict. Returns a list of imports that should include
|
| - # the generated go file.
|
| + # imports to '_imports' dict. Mojom imports are stored in the '_mojom_imports'
|
| + # dict. This operation is idempotent.
|
| + # Returns a tuple:
|
| + # - list of imports that should include the generated go file
|
| + # - the dictionary of _mojom_imports
|
| def GetImports(self):
|
| # Imports can only be used in structs, constants, enums, interfaces.
|
| all_structs = list(self.module.structs)
|
| @@ -344,6 +446,24 @@ class Generator(generator.Generator):
|
| if field.value:
|
| AddImport(self.module, field.value)
|
|
|
| + # Mojom Type generation requires additional imports.
|
| + defInterface = len(self.module.interfaces) > 0
|
| + defOtherType = len(self.module.unions) + len(all_structs) + \
|
| + len(GetAllEnums(self.module)) > 0
|
| +
|
| + if GetPackageName(self.module) != _mojom_types_pkg_short:
|
| + if defInterface:
|
| + # Each Interface has a service description that uses this.
|
| + _imports[_mojom_types_pkg] = _mojom_types_pkg_short
|
| + if defOtherType and self.should_gen_mojom_types:
|
| + # This import is needed only if generating mojom type definitions.
|
| + _imports[_mojom_types_pkg] = _mojom_types_pkg_short
|
| +
|
| + if GetPackageName(self.module) != _service_describer_pkg_short and \
|
| + defInterface:
|
| + # Each Interface has a service description that uses this.
|
| + _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)
|
| @@ -354,7 +474,11 @@ class Generator(generator.Generator):
|
| imports_list.append('"%s"' % i)
|
| else:
|
| imports_list.append('%s "%s"' % (_imports[i], i))
|
| - return sorted(imports_list)
|
| + return sorted(imports_list), _mojom_imports
|
| +
|
| + def GetMojomImports(self):
|
| + # GetImports (idempotent) prepares the _imports and _mojom_imports maps.
|
| + return self.GetImports()[1]
|
|
|
| # Overrides the implementation from the base class in order to customize the
|
| # struct and field names.
|
|
|