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)
Example #2
0
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,
    }
Example #3
0
  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)
Example #4
0
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
Example #5
0
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)
Example #6
0
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)