def Write(self):
    """Writes the output."""
    header_file = self._out_base_filename + '.h'
    cc_file = self._out_base_filename + '.cc'

    include_file_root = self._out_root[len(self._gen_dir_relpath)+1:]
    header_file_path = '%s/%s' % (include_file_root, header_file)
    cc_file_path = '%s/%s' % (include_file_root, cc_file)
    substitutions = ({
        'header_file_path': header_file_path,
        'header_guard': (header_file_path.replace('/', '_').
                             replace('.', '_').upper()),
        'method_name': self._method_name,
        'source_files': str([ToPosixPath(f) for f in self._source_files]),
        'year': str(datetime.now().year)
    })
    if not os.path.exists(self._out_root):
      os.makedirs(self._out_root)
    # Write the .h file.
    with open(os.path.join(self._out_root, header_file), 'w') as f:
      header_file = Code()
      header_file.Append(HEADER_FILE_TEMPLATE)
      header_file.Substitute(substitutions)
      f.write(header_file.Render().strip())
    # Write the .cc file.
    with open(os.path.join(self._out_root, cc_file), 'w') as f:
      cc_file = Code()
      cc_file.Append(CC_FILE_BEGIN)
      cc_file.Substitute(substitutions)
      cc_file.Concat(self.Render())
      cc_end = Code()
      cc_end.Append(CC_FILE_END)
      cc_end.Substitute(substitutions)
      cc_file.Concat(cc_end)
      f.write(cc_file.Render().strip())
Beispiel #2
0
 def Write(self):
     """Writes the output."""
     header_file_path = self._out_base_filename + '.h'
     cc_file_path = self._out_base_filename + '.cc'
     substitutions = ({
         'header_file_path':
         header_file_path,
         'header_guard':
         (header_file_path.replace('/', '_').replace('.', '_').upper()),
         'provider_class':
         self._provider_class,
         'source_files':
         str(self._source_files),
         'year':
         str(datetime.now().year)
     })
     if not os.path.exists(self._out_root):
         os.makedirs(self._out_root)
     # Write the .h file.
     with open(os.path.join(self._out_root, header_file_path), 'w') as f:
         header_file = Code()
         header_file.Append(HEADER_FILE_TEMPLATE)
         header_file.Substitute(substitutions)
         f.write(header_file.Render().strip())
     # Write the .cc file.
     with open(os.path.join(self._out_root, cc_file_path), 'w') as f:
         cc_file = Code()
         cc_file.Append(CC_FILE_BEGIN)
         cc_file.Substitute(substitutions)
         cc_file.Concat(self.Render())
         cc_end = Code()
         cc_end.Append(CC_FILE_END)
         cc_end.Substitute(substitutions)
         cc_file.Concat(cc_end)
         f.write(cc_file.Render().strip())
Beispiel #3
0
  def _GenerateType(self, type_):
    """Generates a struct for a type.
    """
    classname = cpp_util.Classname(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)})
    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
Beispiel #4
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.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
Beispiel #5
0
 def testSubstitute(self):
     c = Code()
     c.Append('%(var1)s %(var2)s %(var1)s')
     c.Substitute({'var1': 'one', 'var2': 'two'})
     self.assertEquals('one two one', c.Render())
     c.Append('%(var1)s %(var2)s %(var3)s')
     c.Append('%(var2)s %(var1)s %(var3)s')
     c.Substitute({'var1': 'one', 'var2': 'two', 'var3': 'three'})
     self.assertEquals('one two one\n'
                       'one two three\n'
                       'two one three', c.Render())
Beispiel #6
0
    def Write(self):
        """Writes the output."""
        header_file = self._out_base_filename + '.h'
        cc_file = self._out_base_filename + '.cc'

        include_file_root = self._out_root
        GEN_DIR_PREFIX = 'gen/'
        if include_file_root.startswith(GEN_DIR_PREFIX) and len(
                include_file_root) >= len(GEN_DIR_PREFIX):
            include_file_root = include_file_root[len(GEN_DIR_PREFIX):]
        else:
            include_file_root = ''
        if include_file_root:
            header_file_path = '%s/%s' % (include_file_root, header_file)
        else:
            header_file_path = header_file
        cc_file_path = '%s/%s' % (include_file_root, cc_file)

        substitutions = ({
            'header_file_path':
            header_file_path,
            'header_guard':
            (header_file_path.replace('/', '_').replace('.', '_').upper()),
            'method_name':
            self._method_name,
            'source_files':
            str(self._source_files),
            'year':
            str(datetime.now().year)
        })
        if not os.path.exists(self._out_root):
            os.makedirs(self._out_root)
        # Write the .h file.
        with open(os.path.join(self._out_root, header_file), 'w') as f:
            header_file = Code()
            header_file.Append(HEADER_FILE_TEMPLATE)
            header_file.Substitute(substitutions)
            f.write(header_file.Render().strip())
        # Write the .cc file.
        with open(os.path.join(self._out_root, cc_file), 'w') as f:
            cc_file = Code()
            cc_file.Append(CC_FILE_BEGIN)
            cc_file.Substitute(substitutions)
            cc_file.Concat(self.Render())
            cc_end = Code()
            cc_end.Append(CC_FILE_END)
            cc_end.Substitute(substitutions)
            cc_file.Concat(cc_end)
            f.write(cc_file.Render().strip())
Beispiel #7
0
    def GenerateForwardDeclarations(self):
        """Returns the forward declarations for self._namespace.

    Use after GetRootNamespaceStart. Assumes all namespaces are relative to
    self._root_namespace.
    """
        c = Code()
        for namespace, types in sorted(
                self._NamespaceTypeDependencies().items()):
            c.Append('namespace %s {' % namespace.name)
            for type_ in types:
                if namespace.types[type_].type_ == PropertyType.STRING:
                    c.Append('typedef std::string %s;' % type_)
                elif namespace.types[type_].type_ == PropertyType.ARRAY:
                    c.Append('typedef std::vector<%(item_type)s> %(name)s;')
                    c.Substitute({
                        'name':
                        type_,
                        'item_type':
                        self.GetType(namespace.types[type_].item_type,
                                     wrap_optional=True)
                    })
                else:
                    c.Append('struct %s;' % type_)
            c.Append('}')
        c.Concat(self.GetNamespaceStart())
        for (name, type_) in self._namespace.types.items():
            if not type_.functions and type_.type_ == PropertyType.OBJECT:
                c.Append('struct %s;' % name)
        c.Concat(self.GetNamespaceEnd())
        return c
Beispiel #8
0
  def _GenerateTypePopulateProperty(self, prop, src, dst):
    """Generate the code to populate a single property in a type.

    src: DictionaryValue*
    dst: Type*
    """
    c = Code()
    value_var = prop.unix_name + '_value'
    c.Append('Value* %(value_var)s = NULL;')
    if prop.optional:
      (c.Sblock(
          'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {'
        )
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, value_var, dst, 'false'))
        .Eblock('}')
      )
    else:
      (c.Append(
          'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))')
        .Append('  return false;')
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, value_var, dst, 'false'))
      )
    c.Append()
    c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src})
    return c
Beispiel #9
0
  def _GenerateType(self, cpp_namespace, type_):
    """Generates the function definitions for a type.
    """
    classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
    c = Code()

    if type_.functions:
      for function in type_.functions.values():
        (c.Concat(
            self._GenerateFunction(
                cpp_namespace + '::' + cpp_util.Classname(function.name),
                function))
          .Append()
        )
    elif type_.type_ == PropertyType.OBJECT:
      (c.Concat(self._GeneratePropertyFunctions(
          cpp_namespace, type_.properties.values()))
        .Sblock('%(namespace)s::%(classname)s()')
        .Concat(self._GenerateInitializersAndBody(type_))
        .Eblock('%(namespace)s::~%(classname)s() {}')
        .Append()
      )
      if type_.from_json:
        (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
          .Append()
        )
      if type_.from_client:
        (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
          .Append()
        )
    c.Substitute({'classname': classname, 'namespace': cpp_namespace})

    return c
Beispiel #10
0
  def _GenerateCreateCallbackArguments(self, function_scope, callback):
    """Generate all functions to create Value parameters for a callback.

    E.g for function "Bar", generate Bar::Results::Create
    E.g for event "Baz", generate Baz::Create

    function_scope: the function scope path, e.g. Foo::Bar for the function
                    Foo::Bar::Baz(). May be None if there is no function scope.
    callback: the Function object we are creating callback arguments for.
    """
    c = Code()
    params = callback.params
    c.Concat(self._GeneratePropertyFunctions(function_scope, params))

    (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
                  'Create(%(declaration_list)s) {')
      .Append('scoped_ptr<base::ListValue> create_results('
              'new base::ListValue());')
    )
    declaration_list = []
    for param in params:
      declaration_list.append(cpp_util.GetParameterDeclaration(
          param, self._type_helper.GetCppType(param.type_)))
      c.Append('create_results->Append(%s);' %
          self._CreateValueFromType(param.type_, param.unix_name))
    c.Append('return create_results.Pass();')
    c.Eblock('}')
    c.Substitute({
        'function_scope': ('%s::' % function_scope) if function_scope else '',
        'declaration_list': ', '.join(declaration_list),
        'param_names': ', '.join(param.unix_name for param in params)
    })
    return c
Beispiel #11
0
    def _GenerateTypePopulateProperty(self, prop, src, dst):
        """Generate the code to populate a single property in a type.

    src: base::DictionaryValue*
    dst: Type*
    """
        c = Code()
        value_var = prop.unix_name + '_value'
        c.Append('const base::Value* %(value_var)s = NULL;')
        if prop.optional:
            (c.Sblock(
                'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {'
            ).Concat(
                self._GeneratePopulatePropertyFromValue(
                    prop, value_var, dst, 'false')))
            if self._cpp_type_generator.IsEnumOrEnumRef(prop):
                (c.Append('} else {').Append(
                    '%%(dst)s->%%(name)s = %s;' %
                    self._cpp_type_generator.GetEnumNoneValue(prop)))
            c.Eblock('}')
        else:
            (c.Append(
                'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))'
            ).Append('  return false;').Concat(
                self._GeneratePopulatePropertyFromValue(
                    prop, value_var, dst, 'false')))
        c.Append()
        c.Substitute({
            'value_var': value_var,
            'key': prop.name,
            'src': src,
            'dst': dst,
            'name': prop.unix_name
        })
        return c
Beispiel #12
0
 def _GenerateCreateEnumValue(self, cpp_namespace, prop):
     """Generates CreateEnumValue() that returns the |StringValue|
 representation of an enum.
 """
     c = Code()
     c.Append('// static')
     c.Sblock(
         'scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {')
     c.Sblock('switch (%s) {' % prop.unix_name)
     if prop.optional:
         (c.Append('case %s: {' %
                   self._cpp_type_generator.GetEnumNoneValue(prop)).Append(
                       '  return scoped_ptr<Value>();').Append('}'))
     for enum_value in prop.enum_values:
         (c.Append(
             'case %s: {' %
             self._cpp_type_generator.GetEnumValue(prop, enum_value)
         ).Append(
             '  return scoped_ptr<Value>(Value::CreateStringValue("%s"));' %
             enum_value).Append('}'))
     (c.Append('default: {').Append('  return scoped_ptr<Value>();').Append(
         '}'))
     c.Eblock('}')
     c.Eblock('}')
     c.Substitute({
         'cpp_namespace':
         cpp_namespace,
         'arg':
         cpp_util.GetParameterDeclaration(
             prop, self._cpp_type_generator.GetType(prop))
     })
     return c
Beispiel #13
0
    def _GenerateTypePopulate(self, cpp_namespace, type_):
        """Generates the function for populating a type given a pointer to it.

    E.g for type "Foo", generates Foo::Populate()
    """
        classname = cpp_util.Classname(type_.name)
        c = Code()
        (c.Append('// static').Sblock('bool %(namespace)s::Populate'
                                      '(const Value& value, %(name)s* out) {').
         Append('if (!value.IsType(Value::TYPE_DICTIONARY))').Append(
             '  return false;').Append(
                 'const DictionaryValue* dict = '
                 'static_cast<const DictionaryValue*>(&value);').Append())
        for prop in type_.properties.values():
            c.Concat(self._InitializePropertyToDefault(prop, 'out'))
        for prop in type_.properties.values():
            if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
                c.Append('out->additional_properties.MergeDictionary(dict);')
                # remove all keys that are actual properties
                for cur_prop in type_.properties.values():
                    if prop != cur_prop:
                        c.Append('out->additional_properties'
                                 '.RemoveWithoutPathExpansion("%s", NULL);' %
                                 cur_prop.name)
                c.Append()
            else:
                c.Concat(
                    self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
        (c.Append('return true;').Eblock('}'))
        c.Substitute({'namespace': cpp_namespace, 'name': classname})
        return c
Beispiel #14
0
    def GenerateForwardDeclarations(self):
        """Returns the forward declarations for self._namespace.

    Use after GetRootNamespaceStart. Assumes all namespaces are relative to
    self._root_namespace.
    """
        c = Code()
        namespace_type_dependencies = self._NamespaceTypeDependencies()
        for namespace in sorted(namespace_type_dependencies.keys(),
                                key=operator.attrgetter('name')):
            c.Append('namespace %s {' % namespace.name)
            for type_ in sorted(namespace_type_dependencies[namespace],
                                key=schema_util.StripSchemaNamespace):
                type_name = schema_util.StripSchemaNamespace(type_)
                if namespace.types[type_].type_ == PropertyType.STRING:
                    c.Append('typedef std::string %s;' % type_name)
                elif namespace.types[type_].type_ == PropertyType.ARRAY:
                    c.Append('typedef std::vector<%(item_type)s> %(name)s;')
                    c.Substitute({
                        'name':
                        type_name,
                        'item_type':
                        self.GetType(namespace.types[type_].item_type,
                                     wrap_optional=True)
                    })
                # Enums cannot be forward declared.
                elif namespace.types[type_].type_ != PropertyType.ENUM:
                    c.Append('struct %s;' % type_name)
            c.Append('}')
        c.Concat(self.GetNamespaceStart())
        for (name, type_) in self._namespace.types.items():
            if not type_.functions and type_.type_ == PropertyType.OBJECT:
                c.Append('struct %s;' % schema_util.StripSchemaNamespace(name))
        c.Concat(self.GetNamespaceEnd())
        return c
Beispiel #15
0
  def _GenerateFunctionParamsCreate(self, cpp_namespace, function):
    """Generate function to create an instance of Params. The generated
    function takes a ListValue of arguments.

    E.g for function "Bar", generate Bar::Params::Create()
    """
    c = Code()
    (c.Append('// static')
      .Sblock('scoped_ptr<%(cpp_namespace)s::Params> '
        '%(cpp_namespace)s::Params::Create(const ListValue& args) {')
      .Concat(self._GenerateParamsCheck(function, 'args'))
      .Append('scoped_ptr<Params> params(new Params());')
    )
    c.Substitute({'cpp_namespace': cpp_namespace})

    for param in function.params:
      c.Concat(self._InitializePropertyToDefault(param, 'params'))

    for i, param in enumerate(function.params):
      # Any failure will cause this function to return. If any argument is
      # incorrect or missing, those following it are not processed. Note that
      # for optional arguments, we allow missing arguments and proceed because
      # there may be other arguments following it.
      failure_value = 'scoped_ptr<Params>()'
      c.Append()
      value_var = param.unix_name + '_value'
      (c.Append('Value* %(value_var)s = NULL;')
        .Append('if (args.Get(%(i)s, &%(value_var)s) && '
            '!%(value_var)s->IsType(Value::TYPE_NULL))')
        .Sblock('{')
        .Concat(self._GeneratePopulatePropertyFromValue(
            param, value_var, 'params', failure_value))
        .Eblock('}')
      )
      if not param.optional:
        (c.Sblock('else {')
          .Append('return %s;' % failure_value)
          .Eblock('}')
        )
      c.Substitute({'value_var': value_var, 'i': i})
    (c.Append()
      .Append('return params.Pass();')
      .Eblock('}')
      .Append()
    )

    return c
Beispiel #16
0
 def testCommentWithSpecialCharacters(self):
     c = Code()
     c.Comment('20% of 80%s')
     c.Substitute({})
     self.assertEquals('// 20% of 80%s', c.Render())
     d = Code()
     d.Append('90')
     d.Concat(c)
     self.assertEquals('90\n' '// 20% of 80%s', d.Render())
Beispiel #17
0
    def _GeneratePopulatePropertyFromValue(self,
                                           prop,
                                           value_var,
                                           dst,
                                           failure_value,
                                           check_type=True):
        """Generates code to populate a model.Property given a base::Value*. The
    existence of data inside the base::Value* is assumed so checks for existence
    should be performed before the code this generates.

    prop: the property the code is populating.
    value_var: a base::Value* that should represent |prop|.
    dst: the object with |prop| as a member.
    failure_value: the value to return if |prop| cannot be extracted from
    |value_var|
    check_type: if true, will check if |value_var| is the correct
    base::Value::Type
    """
        c = Code()
        c.Sblock('{')

        if self._IsFundamentalOrFundamentalRef(prop):
            self._GenerateFundamentalOrFundamentalRefPopulate(
                c, prop, value_var, dst)
        elif self._IsObjectOrObjectRef(prop):
            self._GenerateObjectOrObjectRefPopulate(c, prop)
        elif prop.type_ == PropertyType.FUNCTION:
            self._GenerateFunctionPopulate(c, prop)
        elif prop.type_ == PropertyType.ANY:
            self._GenerateAnyPopulate(c, prop, value_var, dst)
        elif self._IsArrayOrArrayRef(prop):
            self._GenerateArrayOrArrayRefPopulate(c, prop, dst)
        elif prop.type_ == PropertyType.CHOICES:
            self._GenerateChoicePopulate(c, prop, value_var, dst,
                                         failure_value)
        elif self._cpp_type_generator.IsEnumOrEnumRef(prop):
            self._GenerateEnumPopulate(c, prop, value_var)
        elif prop.type_ == PropertyType.BINARY:
            self._GenerateBinaryPopulate(c, prop)
        else:
            raise NotImplementedError(prop.type_)
        c.Eblock('}')
        sub = {
            'value_var': value_var,
            'name': prop.unix_name,
            'dst': dst,
            'failure_value': failure_value,
        }
        if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
            sub['ctype'] = self._cpp_type_generator.GetType(prop)
            sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(
                prop)
            sub['value_type'] = cpp_util.GetValueType(
                self._cpp_type_generator.GetReferencedProperty(prop).type_)
        c.Substitute(sub)
        return c
Beispiel #18
0
  def _GenerateFunctionParamsCreate(self, function):
    """Generate function to create an instance of Params. The generated
    function takes a base::ListValue of arguments.

    E.g for function "Bar", generate Bar::Params::Create()
    """
    c = Code()
    (c.Append('// static')
      .Sblock('std::unique_ptr<Params> Params::Create(%s) {' %
                  self._GenerateParams(['const base::ListValue& args']))
    )
    if self._generate_error_messages:
      c.Append('DCHECK(error);')
    (c.Concat(self._GenerateParamsCheck(function, 'args'))
      .Append('std::unique_ptr<Params> params(new Params());')
    )

    for param in function.params:
      c.Concat(self._InitializePropertyToDefault(param, 'params'))

    for i, param in enumerate(function.params):
      # Any failure will cause this function to return. If any argument is
      # incorrect or missing, those following it are not processed. Note that
      # for optional arguments, we allow missing arguments and proceed because
      # there may be other arguments following it.
      failure_value = 'std::unique_ptr<Params>()'
      c.Append()
      value_var = param.unix_name + '_value'
      (c.Append('const base::Value* %(value_var)s = NULL;')
        .Append('if (args.Get(%(i)s, &%(value_var)s) &&')
        .Sblock('    !%(value_var)s->is_none()) {')
        .Concat(self._GeneratePopulatePropertyFromValue(
            param, value_var, 'params', failure_value))
        .Eblock('}')
      )
      if not param.optional:
        (c.Sblock('else {')
          .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
          .Append('return %s;' % failure_value)
          .Eblock('}'))
      c.Substitute({'value_var': value_var, 'i': i, 'key': param.name})
    (c.Append()
      .Append('return params;')
      .Eblock('}')
      .Append()
    )

    return c
Beispiel #19
0
    def _GenerateFunctionResultCreate(self, cpp_namespace, function):
        """Generate function to create a Result given the return value.

    E.g for function "Bar", generate Bar::Result::Create
    """
        c = Code()
        params = function.callback.params

        if not params:
            (c.Append('Value* %s::Result::Create() {' % cpp_namespace).Append(
                '  return Value::CreateNullValue();').Append('}'))
        else:
            expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams(
                params)
            c.Concat(
                self._GeneratePropertyFunctions(cpp_namespace + '::Result',
                                                expanded_params))

            # If there is a single parameter, this is straightforward. However, if
            # the callback parameter is of 'choices', this generates a Create method
            # for each choice. This works because only 1 choice can be returned at a
            # time.
            for param in expanded_params:
                if param.type_ == PropertyType.ANY:
                    # Generation of Value* Create(Value*) is redundant.
                    continue
                # We treat this argument as 'required' to avoid wrapping it in a
                # scoped_ptr if it's optional.
                param_copy = param.Copy()
                param_copy.optional = False
                c.Sblock(
                    'Value* %(cpp_namespace)s::Result::Create(const %(arg)s) {'
                )
                c.Append('return %s;' % self._CreateValueFromProperty(
                    param_copy, param_copy.unix_name))
                c.Eblock('}')
                c.Substitute({
                    'cpp_namespace':
                    cpp_namespace,
                    'arg':
                    cpp_util.GetParameterDeclaration(
                        param_copy,
                        self._cpp_type_generator.GetType(param_copy))
                })

        return c
Beispiel #20
0
  def _GenerateTypePopulateProperty(self, prop, src, dst):
    """Generate the code to populate a single property in a type.

    src: base::DictionaryValue*
    dst: Type*
    """
    c = Code()
    value_var = prop.unix_name + '_value'
    c.Append('const base::Value* %(value_var)s = NULL;')
    if prop.optional:
      (c.Sblock(
          'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, value_var, dst, 'false')))
      underlying_type = self._type_helper.FollowRef(prop.type_)
      if underlying_type.property_type == PropertyType.ENUM:
        namespace_prefix = ('%s::' % underlying_type.namespace.unix_name
                            if underlying_type.namespace != self._namespace
                            else '')
        (c.Append('} else {')
          .Append('%%(dst)s->%%(name)s = %s%s;' %
             (namespace_prefix,
              self._type_helper.GetEnumNoneValue(prop.type_))))
      c.Eblock('}')
    else:
      (c.Sblock(
          'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
        .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
        .Append('return false;')
        .Eblock('}')
        .Concat(self._GeneratePopulatePropertyFromValue(
            prop, value_var, dst, 'false'))
      )
    c.Append()
    c.Substitute({
      'value_var': value_var,
      'key': prop.name,
      'src': src,
      'dst': dst,
      'name': prop.unix_name
    })
    return c
Beispiel #21
0
  def _GenerateCreateCallbackArguments(self, function_scope, callback):
    """Generate all functions to create Value parameters for a callback.

    E.g for function "Bar", generate Bar::Results::Create
    E.g for event "Baz", generate Baz::Create

    function_scope: the function scope path, e.g. Foo::Bar for the function
    Foo::Bar::Baz().
    callback: the Function object we are creating callback arguments for.
    """
    c = Code()
    params = callback.params
    expanded_params = self._cpp_type_generator.ExpandParams(params)
    c.Concat(self._GeneratePropertyFunctions(function_scope, expanded_params))

    param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params)
    for param_list in param_lists:
      (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::'
                'Create(%(declaration_list)s) {')
        .Append('scoped_ptr<base::ListValue> create_results('
                'new base::ListValue());')
      )
      declaration_list = []
      for param in param_list:
        # We treat this argument as 'required' to avoid wrapping it in a
        # scoped_ptr if it's optional.
        param_copy = param.Copy()
        param_copy.optional = False
        c.Append('create_results->Append(%s);' %
            self._CreateValueFromProperty(param_copy, param_copy.unix_name))
        declaration_list.append("const %s" % cpp_util.GetParameterDeclaration(
            param_copy, self._cpp_type_generator.GetType(param_copy)))

      c.Append('return create_results.Pass();')
      c.Eblock('}')
      c.Substitute({
          'function_scope': function_scope,
          'declaration_list': ', '.join(declaration_list)
      })

    return c
Beispiel #22
0
  def _GenerateType(self, cpp_namespace, type_):
    """Generates the function definitions for a type.
    """
    classname = cpp_util.Classname(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')
      for function in type_.functions.values():
        (c.Concat(
            self._GenerateFunction(
                cpp_namespace + '::' + cpp_util.Classname(function.name),
                function))
          .Append()
        )
    elif type_.type_ == PropertyType.OBJECT:
      (c.Concat(self._GeneratePropertyFunctions(
          cpp_namespace, type_.properties.values()))
        .Sblock('%(namespace)s::%(classname)s()')
        .Concat(self._GenerateInitializersAndBody(type_))
        .Eblock('%(namespace)s::~%(classname)s() {}')
        .Append()
      )
      if type_.from_json:
        (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
          .Append()
        )
      if type_.from_client:
        (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
          .Append()
        )
    c.Substitute({'classname': classname, 'namespace': cpp_namespace})

    return c
Beispiel #23
0
 def _GenerateParamsCheck(self, function, var):
     """Generates a check for the correct number of arguments when creating
 Params.
 """
     c = Code()
     num_required = 0
     for param in function.params:
         if not param.optional:
             num_required += 1
     if num_required == len(function.params):
         c.Append('if (%(var)s.GetSize() != %(total)d)')
     elif not num_required:
         c.Append('if (%(var)s.GetSize() > %(total)d)')
     else:
         c.Append('if (%(var)s.GetSize() < %(required)d'
                  ' || %(var)s.GetSize() > %(total)d)')
     c.Append('  return scoped_ptr<Params>();')
     c.Substitute({
         'var': var,
         'required': num_required,
         'total': len(function.params),
     })
     return c
Beispiel #24
0
    def _GenerateFunction(self, cpp_namespace, function):
        """Generates the definitions for function structs.
    """
        c = Code()

        # Params::Populate function
        if function.params:
            c.Concat(
                self._GeneratePropertyFunctions(cpp_namespace + '::Params',
                                                function.params))
            (c.Append('%(cpp_namespace)s::Params::Params() {}').Append(
                '%(cpp_namespace)s::Params::~Params() {}').Append().Concat(
                    self._GenerateFunctionParamsCreate(cpp_namespace,
                                                       function)).Append())

        # Result::Create function
        if function.callback:
            c.Concat(
                self._GenerateFunctionResultCreate(cpp_namespace, function))

        c.Substitute({'cpp_namespace': cpp_namespace})

        return c
Beispiel #25
0
    def _GenerateCreateCallbackArguments(self,
                                         function_scope,
                                         callback,
                                         generate_to_json=False):
        """Generate all functions to create Value parameters for a callback.

    E.g for function "Bar", generate Bar::Results::Create
    E.g for event "Baz", generate Baz::Create

    function_scope: the function scope path, e.g. Foo::Bar for the function
    Foo::Bar::Baz().
    callback: the Function object we are creating callback arguments for.
    generate_to_json: Generate a ToJson method.
    """
        c = Code()
        params = callback.params
        expanded_params = self._cpp_type_generator.ExpandParams(params)
        c.Concat(
            self._GeneratePropertyFunctions(function_scope, expanded_params))

        param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(
            params)
        for param_list in param_lists:
            (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::'
                      'Create(%(declaration_list)s) {').Append(
                          'scoped_ptr<base::ListValue> create_results('
                          'new base::ListValue());'))
            declaration_list = []
            for param in param_list:
                # We treat this argument as 'required' to avoid wrapping it in a
                # scoped_ptr if it's optional.
                param_copy = param.Copy()
                param_copy.optional = False
                declaration_list.append(
                    "const %s" % cpp_util.GetParameterDeclaration(
                        param_copy,
                        self._cpp_type_generator.GetCompiledType(param_copy)))
                param_name = param_copy.unix_name
                if param_copy.type_ != param_copy.compiled_type:
                    param_name = 'temp_' + param_name
                    (c.Append('%s %s;' % (self._cpp_type_generator.GetType(
                        param_copy), param_name)).Append(
                            cpp_util.GenerateCompiledTypeToTypeConversion(
                                param_copy, param_copy.unix_name, param_name) +
                            ';'))
                c.Append('create_results->Append(%s);' %
                         self._CreateValueFromProperty(param_copy, param_name))

            c.Append('return create_results.Pass();')
            c.Eblock('}')
            if generate_to_json:
                c.Append()
                (c.Sblock('std::string %(function_scope)s::'
                          'ToJson(%(declaration_list)s) {').Append(
                              'scoped_ptr<base::ListValue> create_results = '
                              '%(function_scope)s::Create(%(param_list)s);').
                 Append('std::string json;').Append(
                     'base::JSONWriter::Write(create_results.get(), &json);').
                 Append('return json;'))
                c.Eblock('}')

            c.Substitute({
                'function_scope':
                function_scope,
                'declaration_list':
                ', '.join(declaration_list),
                'param_list':
                ', '.join(param.unix_name for param in param_list)
            })

        return c
Beispiel #26
0
  def _GeneratePopulateVariableFromValue(self,
                                         type_,
                                         src_var,
                                         dst_var,
                                         failure_value,
                                         is_ptr=False):
    """Generates code to populate a variable |dst_var| of type |type_| from a
    Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated
    code, if |dst_var| fails to be populated then Populate will return
    |failure_value|.
    """
    c = Code()

    underlying_type = self._type_helper.FollowRef(type_)

    if underlying_type.property_type.is_fundamental:
      if is_ptr:
        (c.Append('%(cpp_type)s temp;')
          .Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
                      self._type_helper.FollowRef(type_), src_var, '&temp'))
          .Concat(self._GenerateError(
            '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
                type_.name,
                self._util_cc_helper.GetValueTypeString(
                    '%%(src_var)s', True)))))
        c.Append('%(dst_var)s.reset();')
        if not self._generate_error_messages:
          c.Append('return %(failure_value)s;')
        (c.Eblock('}')
          .Append('else')
          .Append('  %(dst_var)s.reset(new %(cpp_type)s(temp));')
        )
      else:
        (c.Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
                      self._type_helper.FollowRef(type_),
                      src_var,
                      '&%s' % dst_var))
          .Concat(self._GenerateError(
            '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
                type_.name,
                self._util_cc_helper.GetValueTypeString(
                    '%%(src_var)s', True))))
          .Append('return %(failure_value)s;')
          .Eblock('}')
        )
    elif underlying_type.property_type == PropertyType.OBJECT:
      if is_ptr:
        (c.Append('const base::DictionaryValue* dictionary = NULL;')
          .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
          .Concat(self._GenerateError(
            '"\'%%(key)s\': expected dictionary, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))))
        # If an optional property fails to populate, the population can still
        # succeed with a warning. If no error messages are generated, this
        # warning is not set and we fail out instead.
        if not self._generate_error_messages:
          c.Append('return %(failure_value)s;')
        (c.Eblock('}')
          .Sblock('else {')
          .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
          .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
            ('*dictionary', 'temp.get()')))
          .Append('  return %(failure_value)s;')
        )
        (c.Append('}')
          .Append('else')
          .Append('  %(dst_var)s = temp.Pass();')
          .Eblock('}')
        )
      else:
        (c.Append('const base::DictionaryValue* dictionary = NULL;')
          .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
          .Concat(self._GenerateError(
            '"\'%%(key)s\': expected dictionary, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
          .Append('return %(failure_value)s;')
          .Eblock('}')
          .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
            ('*dictionary', '&%(dst_var)s')))
          .Append('  return %(failure_value)s;')
          .Append('}')
        )
    elif underlying_type.property_type == PropertyType.FUNCTION:
      if is_ptr:
        c.Append('%(dst_var)s.reset(new base::DictionaryValue());')
    elif underlying_type.property_type == PropertyType.ANY:
      c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
    elif underlying_type.property_type == PropertyType.ARRAY:
      # util_cc_helper deals with optional and required arrays
      (c.Append('const base::ListValue* list = NULL;')
        .Sblock('if (!%(src_var)s->GetAsList(&list)) {')
          .Concat(self._GenerateError(
            '"\'%%(key)s\': expected list, got " + ' +
            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
      )
      if is_ptr and self._generate_error_messages:
        c.Append('%(dst_var)s.reset();')
      else:
        c.Append('return %(failure_value)s;')
      c.Eblock('}')
      c.Sblock('else {')
      item_type = self._type_helper.FollowRef(underlying_type.item_type)
      if item_type.property_type == PropertyType.ENUM:
        c.Concat(self._GenerateListValueToEnumArrayConversion(
                     item_type,
                     'list',
                     dst_var,
                     failure_value,
                     is_ptr=is_ptr))
      else:
        c.Sblock('if (!%s(%s)) {' % (
            self._util_cc_helper.PopulateArrayFromListFunction(is_ptr),
            self._GenerateArgs(('*list', '&%(dst_var)s'))))
        c.Concat(self._GenerateError(
            '"unable to populate array \'%%(parent_key)s\'"'))
        if is_ptr and self._generate_error_messages:
          c.Append('%(dst_var)s.reset();')
        else:
          c.Append('return %(failure_value)s;')
        c.Eblock('}')
      c.Eblock('}')
    elif underlying_type.property_type == PropertyType.CHOICES:
      if is_ptr:
        (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
          .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
            ('*%(src_var)s', 'temp.get()')))
          .Append('  return %(failure_value)s;')
          .Append('%(dst_var)s = temp.Pass();')
        )
      else:
        (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
            ('*%(src_var)s', '&%(dst_var)s')))
          .Append('  return %(failure_value)s;'))
    elif underlying_type.property_type == PropertyType.ENUM:
      c.Concat(self._GenerateStringToEnumConversion(underlying_type,
                                                    src_var,
                                                    dst_var,
                                                    failure_value))
    elif underlying_type.property_type == PropertyType.BINARY:
      (c.Append('const base::BinaryValue* binary_value = NULL;')
        .Sblock('if (!%(src_var)s->IsType(base::Value::TYPE_BINARY)) {')
        .Concat(self._GenerateError(
          '"\'%%(key)s\': expected binary, got " + ' +
          self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
      )
      if not self._generate_error_messages:
        c.Append('return %(failure_value)s;')
      (c.Eblock('}')
        .Sblock('else {')
        .Append(' binary_value =')
        .Append('   static_cast<const base::BinaryValue*>(%(src_var)s);')
      )
      if is_ptr:
        (c.Append('%(dst_var)s.reset(new std::vector<char>(')
          .Append('    binary_value->GetBuffer(),')
          .Append('    binary_value->GetBuffer() + binary_value->GetSize()));')
        )
      else:
        (c.Append('%(dst_var)s.assign(')
          .Append('    binary_value->GetBuffer(),')
          .Append('    binary_value->GetBuffer() + binary_value->GetSize());')
        )
      c.Eblock('}')
    else:
      raise NotImplementedError(type_)
    if c.IsEmpty():
      return c
    return Code().Sblock('{').Concat(c.Substitute({
      'cpp_type': self._type_helper.GetCppType(type_),
      'src_var': src_var,
      'dst_var': dst_var,
      'failure_value': failure_value,
      'key': type_.name,
      'parent_key': type_.parent.name,
    })).Eblock('}')
Beispiel #27
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})
Beispiel #28
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
Beispiel #29
0
    def _GeneratePopulatePropertyFromValue(self,
                                           prop,
                                           value_var,
                                           dst,
                                           failure_value,
                                           check_type=True):
        """Generates code to populate a model.Property given a Value*. The
    existence of data inside the Value* is assumed so checks for existence
    should be performed before the code this generates.

    prop: the property the code is populating.
    value_var: a Value* that should represent |prop|.
    dst: the object with |prop| as a member.
    failure_value: the value to return if |prop| cannot be extracted from
    |value_var|
    check_type: if true, will check if |value_var| is the correct Value::Type
    """
        c = Code()
        c.Sblock('{')

        if self._IsFundamentalOrFundamentalRef(prop):
            if prop.optional:
                (c.Append('%(ctype)s temp;').Append(
                    'if (!%s)' % cpp_util.GetAsFundamentalValue(
                        self._cpp_type_generator.GetReferencedProperty(prop),
                        value_var,
                        '&temp')).Append('  return %(failure_value)s;').Append(
                            '%(dst)s->%(name)s.reset(new %(ctype)s(temp));'))
            else:
                (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue(
                    self._cpp_type_generator.GetReferencedProperty(prop),
                    value_var, '&%s->%s' % (dst, prop.unix_name))).Append(
                        '  return %(failure_value)s;'))
        elif self._IsObjectOrObjectRef(prop):
            if prop.optional:
                (c.Append('DictionaryValue* dictionary = NULL;').Append(
                    'if (!%(value_var)s->GetAsDictionary(&dictionary))').
                 Append('  return %(failure_value)s;').Append(
                     'scoped_ptr<%(ctype)s> temp(new %(ctype)s());').Append(
                         'if (!%(ctype)s::Populate(*dictionary, temp.get()))').
                 Append('  return %(failure_value)s;').Append(
                     '%(dst)s->%(name)s = temp.Pass();'))
            else:
                (c.Append('DictionaryValue* dictionary = NULL;').Append(
                    'if (!%(value_var)s->GetAsDictionary(&dictionary))'
                ).Append('  return %(failure_value)s;').Append(
                    'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))'
                ).Append('  return %(failure_value)s;'))
        elif prop.type_ == PropertyType.ANY:
            if prop.optional:
                c.Append('%(dst)s->%(name)s.reset(new Any());')
            c.Append(self._any_helper.Init(prop, value_var, dst) + ';')
        elif self._IsArrayOrArrayRef(prop):
            # util_cc_helper deals with optional and required arrays
            (c.Append('ListValue* list = NULL;').
             Append('if (!%(value_var)s->GetAsList(&list))').Append(
                 '  return %(failure_value)s;').Append(
                     'if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
                         self._cpp_type_generator.GetReferencedProperty(prop),
                         'list', dst + '->' + prop.unix_name,
                         prop.optional)).Append('  return %(failure_value)s;'))
        elif prop.type_ == PropertyType.CHOICES:
            type_var = '%(dst)s->%(name)s_type'
            c.Sblock('switch (%(value_var)s->GetType()) {')
            for choice in self._cpp_type_generator.GetExpandedChoicesInParams(
                [prop]):
                (c.Sblock('case %s: {' % cpp_util.GetValueType(
                    self._cpp_type_generator.GetReferencedProperty(
                        choice).type_)).Concat(
                            self._GeneratePopulatePropertyFromValue(
                                choice,
                                value_var,
                                dst,
                                failure_value,
                                check_type=False)).Append(
                                    '%s = %s;' %
                                    (type_var,
                                     self._cpp_type_generator.GetEnumValue(
                                         prop, choice.type_.name))).Append(
                                             'break;').Eblock('}'))
            (c.Append('default:').Append('  return %(failure_value)s;'))
            c.Eblock('}')
        elif prop.type_ == PropertyType.ENUM:
            (c.Append('std::string enum_temp;').Append(
                'if (!%(value_var)s->GetAsString(&enum_temp))').Append(
                    '  return %(failure_value)s;'))
            for i, enum_value in enumerate(prop.enum_values):
                (c.Append(('if' if i == 0 else 'else if') +
                          '(enum_temp == "%s")' % enum_value).Append(
                              '  %s->%s = %s;' %
                              (dst, prop.unix_name,
                               self._cpp_type_generator.GetEnumValue(
                                   prop, enum_value))))
            (c.Append('else').Append('  return %(failure_value)s;'))
        elif prop.type_ == PropertyType.BINARY:
            # This is the same if the property is optional or not. We need a pointer
            # to the BinaryValue to be able to populate it, so a scoped_ptr is used
            # whether it is optional or required.
            (c.Append('if (!%(value_var)s->IsType(%(value_type)s))').Append(
                '  return %(failure_value)s;').
             Append('%(dst)s->%(name)s.reset(').Append(
                 '    static_cast<BinaryValue*>(%(value_var)s)->DeepCopy());'))
        else:
            raise NotImplementedError(prop.type_)
        c.Eblock('}')
        sub = {
            'value_var': value_var,
            'name': prop.unix_name,
            'dst': dst,
            'failure_value': failure_value,
        }
        if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
            sub['ctype'] = self._cpp_type_generator.GetType(prop)
            sub['value_type'] = cpp_util.GetValueType(
                self._cpp_type_generator.GetReferencedProperty(prop).type_)
        c.Substitute(sub)
        return c