示例#1
0
 def _GenerateFields(self, props):
   """Generates the field declarations when declaring a type.
   """
   c = Code()
   # Generate the enums needed for any fields with "choices"
   for prop in props:
     if prop.type_ == PropertyType.CHOICES:
       enum_name = self._cpp_type_generator.GetChoicesEnumType(prop)
       c.Append('%s %s_type;' % (enum_name, prop.unix_name))
       c.Append()
   for prop in self._cpp_type_generator.GetExpandedChoicesInParams(props):
     if prop.description:
       c.Comment(prop.description)
     c.Append('%s %s;' % (
         self._cpp_type_generator.GetType(prop, wrap_optional=True),
         prop.unix_name))
     c.Append()
   return c
示例#2
0
    def _GenerateCreateCallbackArguments(self, function):
        """Generates functions for passing parameters to a callback.
    """
        c = Code()
        params = function.params
        c.Cblock(
            self._GenerateTypes((p.type_ for p in params), is_toplevel=True))

        declaration_list = []
        for param in params:
            if param.description:
                c.Comment(param.description)
            declaration_list.append(
                cpp_util.GetParameterDeclaration(
                    param, self._type_helper.GetCppType(param.type_)))
        c.Append('std::unique_ptr<base::ListValue> Create(%s);' %
                 ', '.join(declaration_list))
        return c
    def _GenerateFunctionJsDoc(self, function):
        """Generates the documentation for a function as a Code.

    Returns an empty code object if the object has no documentation.
    """
        c = Code()
        c.Sblock(line='/**', line_prefix=' * ')

        if function.description:
            c.Comment(function.description, comment_prefix='')

        def append_field(c, tag, js_type, name, optional, description):
            c.Append('@%s {' % tag)
            c.Concat(js_type, new_line=False)
            if optional:
                c.Append('=', new_line=False)
            c.Append('} %s' % name, new_line=False)
            if description:
                c.Comment(' %s' % description,
                          comment_prefix='',
                          wrap_indent=4,
                          new_line=False)

        for param in function.params:
            append_field(c, 'param', self._TypeToJsType(param.type_),
                         param.name, param.optional, param.description)

        if function.callback:
            append_field(c, 'param',
                         self._FunctionToJsFunction(function.callback),
                         function.callback.name, function.callback.optional,
                         function.callback.description)

        if function.returns:
            append_field(c, 'return', self._TypeToJsType(function.returns), '',
                         False, function.returns.description)

        if function.deprecated:
            c.Append('@deprecated %s' % function.deprecated)

        c.Append(self._GenerateSeeLink('method', function.name))

        c.Eblock(' */')
        return c
示例#4
0
 def _GenerateFields(self, props):
   """Generates the field declarations when declaring a type.
   """
   c = Code()
   needs_blank_line = False
   for prop in props:
     if needs_blank_line:
       c.Append()
     needs_blank_line = True
     if prop.description:
       c.Comment(prop.description)
     # ANY is a base::Value which is abstract and cannot be a direct member, so
     # we always need to wrap it in a scoped_ptr.
     is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
     (c.Append('%s %s;' % (
          self._type_helper.GetCppType(prop.type_, is_ptr=is_ptr),
          prop.unix_name))
     )
   return c
示例#5
0
  def _GenerateCreateCallbackArguments(self, function, generate_to_json=False):
    """Generates functions for passing paramaters to a callback.
    """
    c = Code()
    params = function.params
    c.Concat(self._GeneratePropertyStructures(params))

    param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params)
    for param_list in param_lists:
      declaration_list = []
      for param in param_list:
        if param.description:
          c.Comment(param.description)
        declaration_list.append('const %s' % cpp_util.GetParameterDeclaration(
            param, self._cpp_type_generator.GetCompiledType(param)))
      c.Append('scoped_ptr<base::ListValue> Create(%s);' %
               ', '.join(declaration_list))
      if generate_to_json:
        c.Append('std::string ToJson(%s);' % ', '.join(declaration_list))
    return c
示例#6
0
 def testComment(self):
     long_comment = ('This comment is ninety one characters in longness, '
                     'that is, using a different word, length.')
     c = Code()
     c.Comment(long_comment)
     self.assertEqual(
         '// This comment is ninety one characters '
         'in longness, that is, using a different\n'
         '// word, length.', c.Render())
     c = Code()
     c.Sblock('sblock')
     c.Comment(long_comment)
     c.Eblock('eblock')
     c.Comment(long_comment)
     self.assertEqual(
         'sblock\n'
         '  // This comment is ninety one characters '
         'in longness, that is, using a\n'
         '  // different word, length.\n'
         'eblock\n'
         '// This comment is ninety one characters in '
         'longness, that is, using a different\n'
         '// word, length.', c.Render())
     # Words that cannot be broken up are left as too long.
     long_word = 'x' * 100
     c = Code()
     c.Comment('xxx')
     c.Comment(long_word)
     c.Comment('xxx')
     self.assertEqual('// xxx\n'
                      '// ' + 'x' * 100 + '\n'
                      '// xxx', c.Render())
     c = Code(indent_size=2, comment_length=40)
     c.Comment(
         'Pretend this is a Closure Compiler style comment, which should '
         'both wrap and indent',
         comment_prefix=' * ',
         wrap_indent=4)
     self.assertEqual(
         ' * Pretend this is a Closure Compiler\n'
         ' *     style comment, which should both\n'
         ' *     wrap and indent', c.Render())
示例#7
0
    def _GenerateType(self, type_, is_toplevel=False, generate_typedefs=False):
        """Generates a struct for |type_|.

    |is_toplevel|       implies that the type was declared in the "types" field
                        of an API schema. This determines the correct function
                        modifier(s).
    |generate_typedefs| controls whether primitive types should be generated as
                        a typedef. This may not always be desired. If false,
                        primitive types are ignored.
    """
        classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
        c = Code()

        if type_.functions:
            # Wrap functions within types in the type's namespace.
            (c.Append('namespace %s {' % classname).Append())
            for function in type_.functions.values():
                c.Cblock(self._GenerateFunction(function))
            c.Append('}  // namespace %s' % classname)
        elif type_.property_type == PropertyType.ARRAY:
            if generate_typedefs and type_.description:
                c.Comment(type_.description)
            c.Cblock(
                self._GenerateType(type_.item_type, is_toplevel=is_toplevel))
            if generate_typedefs:
                (c.Append('typedef std::vector<%s > %s;' %
                          (self._type_helper.GetCppType(
                              type_.item_type), classname)))
        elif type_.property_type == PropertyType.STRING:
            if generate_typedefs:
                if type_.description:
                    c.Comment(type_.description)
                c.Append('typedef std::string %(classname)s;')
        elif type_.property_type == PropertyType.ENUM:
            if type_.description:
                c.Comment(type_.description)
            c.Cblock(self._GenerateEnumDeclaration(classname, type_))
            # Top level enums are in a namespace scope so the methods shouldn't be
            # static. On the other hand, those declared inline (e.g. in an object) do.
            maybe_static = '' if is_toplevel else 'static '
            (c.Append().Append(
                '%sconst char* ToString(%s as_enum);' %
                (maybe_static, classname)).Append(
                    '%s%s Parse%s(const std::string& as_string);' %
                    (maybe_static, classname, classname)))
        elif type_.property_type in (PropertyType.CHOICES,
                                     PropertyType.OBJECT):
            if type_.description:
                c.Comment(type_.description)

            (c.Sblock('struct %(classname)s {').Append(
                '%(classname)s();').Append('~%(classname)s();').Append(
                    '%(classname)s(const %(classname)s&) = delete;').
             Append('%(classname)s& operator=(const %(classname)s&) = delete;'
                    ).Append('%(classname)s(%(classname)s&& rhs);').Append(
                        '%(classname)s& operator=(%(classname)s&& rhs);'))

            if type_.origin.from_manifest_keys:
                c.Append()
                c.Comment('Manifest key constants.')
                c.Concat(
                    self._GenerateManifestKeyConstants(
                        type_.properties.values()))

            if type_.origin.from_json:
                (c.Append().Comment(
                    'Populates a %s object from a base::Value. Returns'
                    ' whether |out| was successfully populated.' %
                    classname).Append('static bool Populate(%s);' %
                                      self._GenerateParams(
                                          ('const base::Value& value',
                                           '%s* out' % classname))))
                if is_toplevel:
                    (c.Append().Comment(
                        'Creates a %s object from a base::Value, or NULL on '
                        'failure.' % classname).Append(
                            'static std::unique_ptr<%s> FromValue(%s);' %
                            (classname,
                             self._GenerateParams(
                                 ('const base::Value& value', )))))
            if type_.origin.from_client:
                value_type = ('base::Value'
                              if type_.property_type is PropertyType.CHOICES
                              else 'base::DictionaryValue')
                (c.Append().Comment(
                    'Returns a new %s representing the serialized form of this '
                    '%s object.' % (value_type, classname)).Append(
                        'std::unique_ptr<%s> ToValue() const;' % value_type))

            if type_.origin.from_manifest_keys:
                c.Cblock(self._GenerateParseFromDictionary(type_, classname))

            if type_.property_type == PropertyType.CHOICES:
                # Choices are modelled with optional fields for each choice. Exactly one
                # field of the choice is guaranteed to be set by the compiler.
                c.Cblock(self._GenerateTypes(type_.choices))
                c.Append('// Choices:')
                for choice_type in type_.choices:
                    c.Append('%s as_%s;' % (self._type_helper.GetCppType(
                        choice_type, is_ptr=True), choice_type.unix_name))
            else:
                properties = type_.properties.values()
                (c.Append().Cblock(
                    self._GenerateTypes(p.type_ for p in properties)).Cblock(
                        self._GenerateFields(properties)))
                if type_.additional_properties is not None:
                    # Most additionalProperties actually have type "any", which is better
                    # modelled as a DictionaryValue rather than a map of string -> Value.
                    if type_.additional_properties.property_type == PropertyType.ANY:
                        c.Append(
                            'base::DictionaryValue additional_properties;')
                    else:
                        (c.Cblock(
                            self._GenerateType(type_.additional_properties)).
                         Append(
                             'std::map<std::string, %s> additional_properties;'
                             % self._type_helper.GetCppType(
                                 type_.additional_properties,
                                 is_in_container=True)))
            (c.Eblock('};'))
        return c.Substitute({'classname': classname})
示例#8
0
  def _GenerateType(self, type_):
    """Generates a struct for a type.
    """
    classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
    c = Code()

    if type_.functions:
      c.Sblock('namespace %(classname)s {')
      for function in type_.functions.values():
        (c.Concat(self._GenerateFunction(function))
          .Append()
        )
      c.Eblock('}')
    elif type_.type_ == PropertyType.ARRAY:
      if type_.description:
        c.Comment(type_.description)
      c.Append('typedef std::vector<%(item_type)s> %(classname)s;')
      c.Substitute({'classname': classname, 'item_type':
          self._cpp_type_generator.GetCompiledType(type_.item_type,
                                                   wrap_optional=True)})
    elif type_.type_ == PropertyType.STRING:
      if type_.description:
        c.Comment(type_.description)
      c.Append('typedef std::string %(classname)s;')
    elif type_.type_ == PropertyType.ENUM:
      if type_.description:
        c.Comment(type_.description)
      c.Sblock('enum %(classname)s {')
      c.Append('%s,' % self._cpp_type_generator.GetEnumNoneValue(type_))
      for value in type_.enum_values:
        c.Append('%s,' % self._cpp_type_generator.GetEnumValue(type_, value))
      (c.Eblock('};')
        .Append()
        .Append('scoped_ptr<base::Value> CreateEnumValue(%s %s);' %
                (classname, classname.lower()))
        .Append('std::string ToString(%s enum_param);' % classname)
        .Append('%s From%sString(const std::string& enum_string);' %
            (classname, classname))
      )
    else:
      if type_.description:
        c.Comment(type_.description)
      (c.Sblock('struct %(classname)s {')
          .Append('~%(classname)s();')
          .Append('%(classname)s();')
          .Append()
          .Concat(self._GeneratePropertyStructures(type_.properties.values()))
          .Concat(self._GenerateFields(type_.properties.values()))
      )
      if type_.from_json:
        (c.Comment('Populates a %s object from a base::Value. Returns'
                   ' whether |out| was successfully populated.' % classname)
          .Append('static bool Populate(const base::Value& value, '
                  '%(classname)s* out);')
          .Append()
        )

      if type_.from_client:
        (c.Comment('Returns a new base::DictionaryValue representing the'
                   ' serialized form of this %s object. Passes '
                   'ownership to caller.' % classname)
          .Append('scoped_ptr<base::DictionaryValue> ToValue() const;')
        )

      (c.Eblock()
        .Sblock(' private:')
          .Concat(self._GeneratePrivatePropertyStructures(
              type_.properties.values()))
          .Append()
          .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
        .Eblock('};')
      )
    c.Substitute({'classname': classname})
    return c
示例#9
0
  def _GenerateType(self, type_, is_toplevel=False, generate_typedefs=False):
    """Generates a struct for |type_|.

    |is_toplevel|       implies that the type was declared in the "types" field
                        of an API schema. This determines the correct function
                        modifier(s).
    |generate_typedefs| controls whether primitive types should be generated as
                        a typedef. This may not always be desired. If false,
                        primitive types are ignored.
    """
    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
    c = Code()

    if type_.functions:
      # Wrap functions within types in the type's namespace.
      (c.Append('namespace %s {' % classname)
        .Append()
      )
      for function in type_.functions.values():
        c.Cblock(self._GenerateFunction(function))
      c.Append('}  // namespace %s' % classname)
    elif type_.property_type == PropertyType.ARRAY:
      if generate_typedefs and type_.description:
        c.Comment(type_.description)
      c.Cblock(self._GenerateType(type_.item_type))
      if generate_typedefs:
        (c.Append('typedef std::vector<%s > %s;' % (
                       self._type_helper.GetCppType(type_.item_type),
                       classname))
        )
    elif type_.property_type == PropertyType.STRING:
      if generate_typedefs:
        if type_.description:
          c.Comment(type_.description)
        c.Append('typedef std::string %(classname)s;')
    elif type_.property_type == PropertyType.ENUM:
      if type_.description:
        c.Comment(type_.description)
      c.Sblock('enum %(classname)s {')
      c.Append('%s,' % self._type_helper.GetEnumNoneValue(type_))
      for value in type_.enum_values:
        c.Append('%s,' % self._type_helper.GetEnumValue(type_, value))
      # Top level enums are in a namespace scope so the methods shouldn't be
      # static. On the other hand, those declared inline (e.g. in an object) do.
      maybe_static = '' if is_toplevel else 'static '
      (c.Eblock('};')
        .Append()
        .Append('%sstd::string ToString(%s as_enum);' %
                    (maybe_static, classname))
        .Append('%s%s Parse%s(const std::string& as_string);' %
                    (maybe_static, classname, classname))
      )
    elif type_.property_type == PropertyType.OBJECT:
      if type_.description:
        c.Comment(type_.description)
      (c.Sblock('struct %(classname)s {')
          .Append('%(classname)s();')
          .Append('~%(classname)s();')
      )
      if type_.origin.from_json:
        (c.Append()
          .Comment('Populates a %s object from a base::Value. Returns'
                   ' whether |out| was successfully populated.' % classname)
          .Append('static bool Populate(const base::Value& value, '
                  '%(classname)s* out);')
        )
      if type_.origin.from_client:
        (c.Append()
          .Comment('Returns a new base::DictionaryValue representing the'
                   ' serialized form of this %s object.' % classname)
          .Append('scoped_ptr<base::DictionaryValue> ToValue() const;')
        )
      properties = type_.properties.values()
      (c.Append()
        .Cblock(self._GenerateTypes(p.type_ for p in properties))
        .Cblock(self._GenerateFields(properties)))
      if type_.additional_properties is not None:
        # Most additionalProperties actually have type "any", which is better
        # modelled as a DictionaryValue rather than a map of string -> Value.
        if type_.additional_properties.property_type == PropertyType.ANY:
          c.Append('base::DictionaryValue additional_properties;')
        else:
          (c.Cblock(self._GenerateType(type_.additional_properties))
            .Append('std::map<std::string, %s> additional_properties;' %
                cpp_util.PadForGenerics(
                    self._type_helper.GetCppType(type_.additional_properties,
                                                 is_in_container=True)))
          )
      (c.Eblock()
        .Append()
        .Sblock(' private:')
          .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
        .Eblock('};')
      )
    elif type_.property_type == PropertyType.CHOICES:
      if type_.description:
        c.Comment(type_.description)
      # Choices are modelled with optional fields for each choice. Exactly one
      # field of the choice is guaranteed to be set by the compiler.
      (c.Sblock('struct %(classname)s {')
          .Append('%(classname)s();')
          .Append('~%(classname)s();')
          .Append())
      c.Cblock(self._GenerateTypes(type_.choices))
      if type_.origin.from_json:
        (c.Comment('Populates a %s object from a base::Value. Returns'
                   ' whether |out| was successfully populated.' % classname)
          .Append('static bool Populate(const base::Value& value, '
                  '%(classname)s* out);')
          .Append()
        )
      if type_.origin.from_client:
        (c.Comment('Returns a new base::Value representing the'
                   ' serialized form of this %s object.' % classname)
          .Append('scoped_ptr<base::Value> ToValue() const;')
          .Append()
        )
      c.Append('// Choices:')
      for choice_type in type_.choices:
        c.Append('%s as_%s;' % (
            self._type_helper.GetCppType(choice_type, is_ptr=True),
            choice_type.unix_name))
      c.Eblock('};')
    c.Substitute({'classname': classname})
    return c
示例#10
0
  def _GenerateType(self, type_):
    """Generates a struct for a type.
    """
    classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
    c = Code()

    if type_.functions:
      # Types with functions are not instantiable in C++ because they are
      # handled in pure Javascript and hence have no properties or
      # additionalProperties.
      if type_.properties:
        raise NotImplementedError('\n'.join(model.GetModelHierarchy(type_)) +
            '\nCannot generate both functions and properties on a type')
      c.Sblock('namespace %(classname)s {')
      for function in type_.functions.values():
        (c.Concat(self._GenerateFunction(function))
          .Append()
        )
      c.Eblock('}')
    elif type_.type_ == PropertyType.ARRAY:
      if type_.description:
        c.Comment(type_.description)
      c.Append('typedef std::vector<%(item_type)s> %(classname)s;')
      c.Substitute({'classname': classname, 'item_type':
          self._cpp_type_generator.GetType(type_.item_type,
                                           wrap_optional=True)})
    elif type_.type_ == PropertyType.STRING:
      if type_.description:
        c.Comment(type_.description)
      c.Append('typedef std::string %(classname)s;')
      c.Substitute({'classname': classname})
    else:
      if type_.description:
        c.Comment(type_.description)
      (c.Sblock('struct %(classname)s {')
          .Append('~%(classname)s();')
          .Append('%(classname)s();')
          .Append()
          .Concat(self._GeneratePropertyStructures(type_.properties.values()))
          .Concat(self._GenerateFields(type_.properties.values()))
      )
      if type_.from_json:
        (c.Comment('Populates a %s object from a Value. Returns'
                   ' whether |out| was successfully populated.' % classname)
          .Append(
              'static bool Populate(const Value& value, %(classname)s* out);')
          .Append()
        )

      if type_.from_client:
        (c.Comment('Returns a new DictionaryValue representing the'
                   ' serialized form of this %s object. Passes '
                   'ownership to caller.' % classname)
          .Append('scoped_ptr<DictionaryValue> ToValue() const;')
        )

      (c.Eblock()
        .Sblock(' private:')
          .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
        .Eblock('};')
      )
    c.Substitute({'classname': classname})
    return c