def _GetContainerValidateParamsCtorArgs(self, kind): if mojom.IsStringKind(kind): expected_num_elements = 0 element_is_nullable = False key_validate_params = "nullptr" element_validate_params = "nullptr" enum_validate_func = "nullptr" elif mojom.IsMapKind(kind): expected_num_elements = 0 element_is_nullable = False key_validate_params = self._GetNewContainerValidateParams( mojom.Array(kind=kind.key_kind)) element_validate_params = self._GetNewContainerValidateParams( mojom.Array(kind=kind.value_kind)) enum_validate_func = "nullptr" else: # mojom.IsArrayKind(kind) expected_num_elements = generator.ExpectedArraySize(kind) or 0 element_is_nullable = mojom.IsNullableKind(kind.kind) key_validate_params = "nullptr" element_validate_params = self._GetNewContainerValidateParams( kind.kind) if mojom.IsEnumKind(kind.kind): enum_validate_func = ( "%s::Validate" % self._GetQualifiedNameForKind( kind.kind, internal=True, flatten_nested_kind=True)) else: enum_validate_func = "nullptr" if enum_validate_func == "nullptr": if key_validate_params == "nullptr": return "%d, %s, %s" % (expected_num_elements, "true" if element_is_nullable else "false", element_validate_params) else: return "%s, %s" % (key_validate_params, element_validate_params) else: return "%d, %s" % (expected_num_elements, enum_validate_func)
class Generator(generator.Generator): go_filters = { 'array': lambda kind: mojom.Array(kind), 'bit_size': GetBitSize, 'decode_suffix': DecodeSuffix, 'encode_suffix': EncodeSuffix, 'go_type': GetGoType, 'expression_to_text': ExpressionToText, 'is_array': mojom.IsArrayKind, 'is_enum': mojom.IsEnumKind, 'is_handle': mojom.IsAnyHandleKind, 'is_map': mojom.IsMapKind, 'is_none_or_empty': lambda array: array == None or len(array) == 0, 'is_nullable': mojom.IsNullableKind, 'is_pointer': mojom.IsObjectKind, 'is_struct': mojom.IsStructKind, 'name': GetNameForElement, 'response_struct_from_method': GetResponseStructFromMethod, 'struct_from_method': GetStructFromMethod, 'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines()) } def GetParameters(self): return { 'enums': GetAllEnums(self.module), 'imports': GetImports(self.module), 'interfaces': self.module.interfaces, 'package': GetPackage(self.module.namespace), 'structs': self.GetStructs(), } @UseJinja('go_templates/source.tmpl', filters=go_filters) def GenerateSource(self): return self.GetParameters() def GenerateFiles(self, args): self.Write(self.GenerateSource(), os.path.join("go", "src", "gen", GetPackagePath(self.module.namespace), '%s.go' % self.module.name)) def GetJinjaParameters(self): return { 'lstrip_blocks': True, 'trim_blocks': True, } def GetGlobals(self): return { 'namespace': self.module.namespace, 'module': self.module, }
def testImportFromDataNoExtraneousImports(self): """Tests that arrays, maps and interface requests are not imported.""" module = mojom.Module('test_module', 'test_namespace') imported_module = mojom.Module('import_module', 'import_namespace') #TODO(azani): Init values in module.py. imported_module.values = {} imported_data = {'module' : imported_module} array = mojom.Array(mojom.INT16, length=20) imported_module.kinds[array.spec] = array map_kind = mojom.Map(mojom.INT16, mojom.INT16) imported_module.kinds[map_kind.spec] = map_kind interface_req = mojom.InterfaceRequest(mojom.INT16) imported_module.kinds[interface_req.spec] = interface_req data.ImportFromData(module, imported_data) self.assertNotIn(array.spec, module.kinds) self.assertNotIn(map_kind.spec, module.kinds) self.assertNotIn(interface_req.spec, module.kinds)
def _Kind(kinds, spec, scope): """Convert a type name into a mojom.Kind object. As a side-effect this function adds the result to 'kinds'. Args: kinds: {Dict[str, mojom.Kind]} All known kinds up to this point, indexed by their names. spec: {str} A name uniquely identifying a type. scope: {Tuple[str, str]} A tuple that looks like (namespace, struct/interface), referring to the location where the type is referenced. Returns: {mojom.Kind} The type corresponding to 'spec'. """ kind = _LookupKind(kinds, spec, scope) if kind: return kind if spec.startswith('?'): kind = _Kind(kinds, spec[1:], scope).MakeNullableKind() elif spec.startswith('a:'): kind = mojom.Array(_Kind(kinds, spec[2:], scope)) elif spec.startswith('asso:'): inner_kind = _Kind(kinds, spec[5:], scope) if isinstance(inner_kind, mojom.InterfaceRequest): kind = mojom.AssociatedInterfaceRequest(inner_kind) else: kind = mojom.AssociatedInterface(inner_kind) elif spec.startswith('a'): colon = spec.find(':') length = int(spec[1:colon]) kind = mojom.Array(_Kind(kinds, spec[colon+1:], scope), length) elif spec.startswith('r:'): kind = mojom.InterfaceRequest(_Kind(kinds, spec[2:], scope)) elif spec.startswith('rmt:'): kind = mojom.PendingRemote(_Kind(kinds, spec[4:], scope)) elif spec.startswith('rcv:'): kind = mojom.PendingReceiver(_Kind(kinds, spec[4:], scope)) elif spec.startswith('rma:'): kind = mojom.PendingAssociatedRemote(_Kind(kinds, spec[4:], scope)) elif spec.startswith('rca:'): kind = mojom.PendingAssociatedReceiver(_Kind(kinds, spec[4:], scope)) elif spec.startswith('m['): # Isolate the two types from their brackets. # It is not allowed to use map as key, so there shouldn't be nested ']'s # inside the key type spec. key_end = spec.find(']') assert key_end != -1 and key_end < len(spec) - 1 assert spec[key_end+1] == '[' and spec[-1] == ']' first_kind = spec[2:key_end] second_kind = spec[key_end+2:-1] kind = mojom.Map(_Kind(kinds, first_kind, scope), _Kind(kinds, second_kind, scope)) else: kind = mojom.Kind(spec) kinds[spec] = kind return kind
class Generator(generator.Generator): go_filters = { 'array': lambda kind: mojom.Array(kind), 'bit_size': GetBitSize, 'decode_suffix': DecodeSuffix, 'encode_suffix': EncodeSuffix, 'go_type': GetGoType, 'expression_to_text': ExpressionToText, 'has_response': lambda method: method.response_parameters is not None, 'is_array': mojom.IsArrayKind, 'is_enum': mojom.IsEnumKind, 'is_handle': mojom.IsAnyHandleKind, 'is_interface': mojom.IsInterfaceKind, 'is_interface_request': mojom.IsInterfaceRequestKind, 'is_map': mojom.IsMapKind, 'is_none_or_empty': lambda array: array is None or len(array) == 0, 'is_nullable': mojom.IsNullableKind, 'is_pointer': IsPointer, 'is_object': mojom.IsObjectKind, 'is_struct': mojom.IsStructKind, 'is_union': mojom.IsUnionKind, 'qualified': GetQualifiedName, 'fullidentifier': mojom.GetMojomTypeFullIdentifier, 'mojom_type': GetMojomTypeValue, 'mojom_type_identifier': mojom.GetMojomTypeIdentifier, 'name': GetNameForElement, 'unqualified_name': GetUnqualifiedNameForElement, 'package': GetPackageNameForElement, 'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines()) } # If set to True, then mojom type information will be generated. should_gen_mojom_types = False def GetParameters(self): package = GetPackageName(self.module) imports, mojom_imports = self.GetImports() return { 'enums': GetAllEnums(self.module), 'imports': imports, 'interfaces': self.GetInterfaces(), 'mojom_imports': mojom_imports, 'package': package, 'structs': self.GetStructs(), '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) def GenerateSource(self): return self.GetParameters() def GenerateFiles(self, args): self.should_gen_mojom_types = "--generate_type_info" in args self.Write(self.GenerateSource(), os.path.join("go", "src", GetPackagePath(self.module), "%s.go" % self.module.name)) def GetJinjaParameters(self): return { 'lstrip_blocks': True, 'trim_blocks': True, } def GetGlobals(self): return { 'namespace': self.module.namespace, 'module': self.module, 'should_gen_mojom_types': self.should_gen_mojom_types, } def GetImports(self): """Gets the current module's imports. Returns: tuple(dict<str, str>, dict<str, str>) The first element of the tuple is a dictionary mapping import paths to import names. The second element is a dictionary mapping import paths to import names only for imported mojom files. """ imports = {} mojom_imports = {} # Imports are referred to by the imported_from field of imported kinds. # Imported kinds can only be referred to in structs, constants, enums, # unions and interfaces. all_structs = list(self.module.structs) for i in self.module.interfaces: for method in i.methods: all_structs.append(self._GetStructFromMethod(method)) if method.response_parameters: all_structs.append(self._GetResponseStructFromMethod(method)) if (len(all_structs) > 0 or len(self.module.interfaces) > 0 or len(self.module.unions) > 0): imports['fmt'] = 'fmt' imports['mojo/public/go/bindings'] = 'bindings' if len(self.module.interfaces) > 0: imports['mojo/public/go/system'] = 'system' if len(all_structs) > 0: imports['sort'] = 'sort' for union in self.module.unions: for field in union.fields: AddImport(imports, mojom_imports, self.module, field.kind) for struct in all_structs: for field in struct.fields: AddImport(imports, mojom_imports, self.module, field.kind) # TODO(rogulenko): add these after generating constants and struct defaults. # if field.default: # AddImport(imports, mojom_imports, self.module, field.default) for enum in GetAllEnums(self.module): for field in enum.fields: if field.value: AddImport(imports, mojom_imports, 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(imports, mojom_imports, self.module, constant.value) return imports, mojom_imports # Overrides the implementation from the base class in order to customize the # struct and field names. def _GetStructFromMethod(self, method): params_class = "%s_%s_Params" % (GetNameForElement(method.interface), GetNameForElement(method)) struct = mojom.Struct(params_class, module=method.interface.module) for param in method.parameters: struct.AddField("in%s" % GetNameForElement(param), param.kind, param.ordinal, attributes=param.attributes) return self._AddStructComputedData(False, struct) # Overrides the implementation from the base class in order to customize the # struct and field names. def _GetResponseStructFromMethod(self, method): params_class = "%s_%s_ResponseParams" % ( GetNameForElement(method.interface), GetNameForElement(method)) struct = mojom.Struct(params_class, module=method.interface.module) for param in method.response_parameters: struct.AddField("out%s" % GetNameForElement(param), param.kind, param.ordinal, attributes=param.attributes) return self._AddStructComputedData(False, struct)
class Generator(generator.Generator): go_filters = { 'array': lambda kind: mojom.Array(kind), 'bit_size': GetBitSize, 'decode_suffix': DecodeSuffix, 'encode_suffix': EncodeSuffix, 'go_type': GetGoType, 'expression_to_text': ExpressionToText, 'has_response': lambda method: method.response_parameters is not None, 'is_array': mojom.IsArrayKind, 'is_enum': mojom.IsEnumKind, 'is_handle': mojom.IsAnyHandleKind, 'is_interface': mojom.IsInterfaceKind, 'is_interface_request': mojom.IsInterfaceRequestKind, 'is_map': mojom.IsMapKind, 'is_none_or_empty': lambda array: array is None or len(array) == 0, 'is_nullable': mojom.IsNullableKind, 'is_pointer': IsPointer, 'is_object': mojom.IsObjectKind, 'is_struct': mojom.IsStructKind, 'is_union': mojom.IsUnionKind, 'qualified': GetQualifiedName, 'name': GetNameForElement, 'unqualified_name': GetUnqualifiedNameForElement, 'package': GetPackageNameForElement, 'tab_indent': lambda s, size=1: ('\n' + '\t' * size).join(s.splitlines()) } def GetParameters(self): return { 'enums': GetAllEnums(self.module), 'imports': self.GetImports(), 'interfaces': self.GetInterfaces(), 'package': GetPackageName(self.module), 'structs': self.GetStructs(), 'unions': self.GetUnions(), } @UseJinja('go_templates/source.tmpl', filters=go_filters) def GenerateSource(self): return self.GetParameters() def GenerateFiles(self, args): self.Write( self.GenerateSource(), os.path.join("go", "src", GetPackagePath(self.module), "%s.go" % self.module.name)) def GetJinjaParameters(self): return { 'lstrip_blocks': True, 'trim_blocks': True, } def GetGlobals(self): return { 'namespace': self.module.namespace, 'module': self.module, } # 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. def GetImports(self): # Imports can only be used in structs, constants, enums, interfaces. all_structs = list(self.module.structs) for i in self.module.interfaces: for method in i.methods: all_structs.append(self._GetStructFromMethod(method)) if method.response_parameters: all_structs.append( self._GetResponseStructFromMethod(method)) if (len(all_structs) > 0 or len(self.module.interfaces) > 0 or len(self.module.unions) > 0): _imports['fmt'] = 'fmt' _imports['mojo/public/go/bindings'] = 'bindings' if len(self.module.interfaces) > 0: _imports['mojo/public/go/system'] = 'system' if len(all_structs) > 0: _imports['sort'] = 'sort' for union in self.module.unions: for field in union.fields: AddImport(self.module, field.kind) for struct in all_structs: for field in struct.fields: AddImport(self.module, field.kind) # TODO(rogulenko): add these after generating constants and struct defaults. # if field.default: # AddImport(self.module, field.default) for enum in GetAllEnums(self.module): for field in enum.fields: if field.value: AddImport(self.module, field.value) # TODO(rogulenko): add these after generating constants and struct defaults. # for constant in GetAllConstants(self.module): # AddImport(self.module, constant.value) imports_list = [] for i in _imports: if i.split('/')[-1] == _imports[i]: imports_list.append('"%s"' % i) else: imports_list.append('%s "%s"' % (_imports[i], i)) return sorted(imports_list) # Overrides the implementation from the base class in order to customize the # struct and field names. def _GetStructFromMethod(self, method): params_class = "%s_%s_Params" % (GetNameForElement( method.interface), GetNameForElement(method)) struct = mojom.Struct(params_class, module=method.interface.module) for param in method.parameters: struct.AddField("in%s" % GetNameForElement(param), param.kind, param.ordinal, attributes=param.attributes) return self._AddStructComputedData(False, struct) # Overrides the implementation from the base class in order to customize the # struct and field names. def _GetResponseStructFromMethod(self, method): params_class = "%s_%s_ResponseParams" % (GetNameForElement( method.interface), GetNameForElement(method)) struct = mojom.Struct(params_class, module=method.interface.module) for param in method.response_parameters: struct.AddField("out%s" % GetNameForElement(param), param.kind, param.ordinal, attributes=param.attributes) return self._AddStructComputedData(False, struct)