Beispiel #1
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=lambda ns: ns.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)})
        else:
          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 #2
0
    def _GenerateEnumFromString(self,
                                cpp_namespace,
                                prop,
                                use_namespace=False):
        """Generates FromClassNameString() which gets an enum from its string
    representation.
    """
        c = Code()
        classname = cpp_util.Classname(
            schema_util.StripSchemaNamespace(prop.name))
        if use_namespace:
            namespace = '%s::' % cpp_namespace
        else:
            namespace = ''

        (c.Append('// static').Sblock('%(namespace)s%(class)s'
                                      ' %(namespace)sFrom%(class)sString('
                                      'const std::string& enum_string) {'))
        enum_prop = self._cpp_type_generator.GetReferencedProperty(prop)
        for i, enum_value in enumerate(
                self._cpp_type_generator.GetReferencedProperty(
                    prop).enum_values):
            # This is broken up into all ifs with no else ifs because we get
            # "fatal error C1061: compiler limit : blocks nested too deeply"
            # on Windows.
            (c.Append('if (enum_string == "%s")' % enum_value).Append(
                '  return %s;' %
                self._cpp_type_generator.GetEnumValue(prop, enum_value)))
        (c.Append('return %s;' %
                  self._cpp_type_generator.GetEnumNoneValue(prop)).Eblock(
                      '}').Substitute({
                          'namespace': namespace,
                          'class': classname
                      }))
        return c
Beispiel #3
0
    def _GenerateEnumToString(self, cpp_namespace, prop, use_namespace=False):
        """Generates ToString() which gets the string representation of an enum.
    """
        c = Code()
        classname = cpp_util.Classname(
            schema_util.StripSchemaNamespace(prop.name))
        if use_namespace:
            namespace = '%s::' % cpp_namespace
        else:
            namespace = ''

        (c.Append('// static').Sblock(
            'std::string %(namespace)sToString(%(class)s enum_param) {'))
        enum_prop = self._cpp_type_generator.GetReferencedProperty(prop)
        c.Sblock('switch (enum_param) {')
        for enum_value in enum_prop.enum_values:
            c.Concat(
                self._GenerateReturnCase(
                    self._cpp_type_generator.GetEnumValue(prop, enum_value),
                    '"%s"' % enum_value))
        (c.Append('case %s:' %
                  self._cpp_type_generator.GetEnumNoneValue(prop)).Append(
                      '  return "";').Eblock('}').Append('return "";').Eblock(
                          '}').Substitute({
                              'namespace': namespace,
                              'class': classname
                          }))
        return c
Beispiel #4
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 #5
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 #6
0
    def Generate(self):
        """Generates a Code object with the .cc for a single namespace.
    """
        c = Code()
        (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append(
            cpp_util.GENERATED_FILE_MESSAGE %
            self._namespace.source_file).Append().Append(
                self._util_cc_helper.GetIncludePath()).Append(
                    '#include "%s/%s.h"' % (self._namespace.source_file_dir,
                                            self._namespace.unix_name)))
        includes = self._cpp_type_generator.GenerateIncludes()
        if not includes.IsEmpty():
            (c.Concat(includes).Append())

        (c.Append().Concat(
            self._cpp_type_generator.GetRootNamespaceStart()).Concat(
                self._cpp_type_generator.GetNamespaceStart()).Append())
        if self._namespace.properties:
            (c.Append('//').Append('// Properties').Append('//').Append())
            for property in self._namespace.properties.values():
                property_code = self._cpp_type_generator.GeneratePropertyValues(
                    property,
                    'const %(type)s %(name)s = %(value)s;',
                    nodoc=True)
                if property_code:
                    c.Concat(property_code).Append()
        if self._namespace.types:
            (c.Append('//').Append('// Types').Append('//').Append())
        for type_ in self._namespace.types.values():
            (c.Concat(
                self._GenerateType(
                    schema_util.StripSchemaNamespace(type_.name),
                    type_)).Append())
        if self._namespace.functions:
            (c.Append('//').Append('// Functions').Append('//').Append())
        for function in self._namespace.functions.values():
            (c.Concat(
                self._GenerateFunction(cpp_util.Classname(function.name),
                                       function)).Append())
        if self._namespace.events:
            (c.Append('//').Append('// Events').Append('//').Append())
        for event in self._namespace.events.values():
            (c.Concat(
                self._GenerateCreateCallbackArguments(
                    cpp_util.Classname(event.name),
                    event,
                    generate_to_json=True)).Append())
        (c.Concat(self._cpp_type_generator.GetNamespaceEnd()).Concat(
            self._cpp_type_generator.GetRootNamespaceEnd()).Append())
        return c
Beispiel #7
0
 def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop):
     """Generates CreateEnumValue() that returns the base::StringValue
 representation of an enum type.
 """
     c = Code()
     classname = cpp_util.Classname(
         schema_util.StripSchemaNamespace(prop.name))
     (c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' %
               (classname, classname.lower())).Append(
                   'std::string enum_temp = ToString(%s);' %
                   classname.lower()).Append('if (enum_temp.empty())').
      Append('  return scoped_ptr<base::Value>();').Append(
          'return scoped_ptr<base::Value>('
          'base::Value::CreateStringValue(enum_temp));').Eblock('}'))
     return c
Beispiel #8
0
    def Generate(self):
        """Generates a Code object with the .cc for a single namespace.
    """
        c = Code()
        (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append(
            cpp_util.GENERATED_FILE_MESSAGE %
            self._namespace.source_file).Append().Append(
                self._util_cc_helper.GetIncludePath()).Append(
                    '#include "%s/%s.h"' % (self._namespace.source_file_dir,
                                            self._namespace.unix_name)))
        includes = self._cpp_type_generator.GenerateIncludes()
        if not includes.IsEmpty():
            (c.Concat(includes).Append())

        (c.Append().Append('using base::Value;').Append(
            'using base::DictionaryValue;').Append('using base::ListValue;').
         Append('using base::BinaryValue;').Append(
             'using %s;' % any_helper.ANY_CLASS).Append().Concat(
                 self._cpp_type_generator.GetRootNamespaceStart()).Concat(
                     self._cpp_type_generator.GetNamespaceStart()).Append())
        if self._namespace.properties:
            (c.Append('//').Append('// Properties').Append('//').Append())
            for property in self._namespace.properties.values():
                property_code = self._cpp_type_generator.GeneratePropertyValues(
                    property,
                    'const %(type)s %(name)s = %(value)s;',
                    nodoc=True)
                if property_code:
                    c.Concat(property_code).Append()
        if self._namespace.types:
            (c.Append('//').Append('// Types').Append('//').Append())
        for type_ in self._namespace.types.values():
            (c.Concat(
                self._GenerateType(
                    schema_util.StripSchemaNamespace(type_.name),
                    type_)).Append())
        if self._namespace.functions:
            (c.Append('//').Append('// Functions').Append('//').Append())
        for function in self._namespace.functions.values():
            (c.Concat(
                self._GenerateFunction(cpp_util.Classname(function.name),
                                       function)).Append())
        (c.Concat(self._cpp_type_generator.GetNamespaceEnd()).Concat(
            self._cpp_type_generator.GetRootNamespaceEnd()).Append())
        # TODO(calamity): Events
        return c
Beispiel #9
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(
            schema_util.StripSchemaNamespace(type_.name))
        c = Code()
        (c.Append('// static').Sblock(
            'bool %(namespace)s::Populate'
            '(const base::Value& value, %(name)s* out) {').Append(
                'if (!value.IsType(base::Value::TYPE_DICTIONARY))').Append(
                    '  return false;'))
        if type_.properties:
            (c.Append(
                'const base::DictionaryValue* dict = '
                'static_cast<const base::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 #10
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:
            # 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 #11
0
  def GetType(self, prop, pad_for_generics=False, wrap_optional=False):
    """Translates a model.Property into its C++ type.

    If REF types from different namespaces are referenced, will resolve
    using self._type_namespaces.

    Use pad_for_generics when using as a generic to avoid operator ambiguity.

    Use wrap_optional to wrap the type in a scoped_ptr<T> if the Property is
    optional.
    """
    cpp_type = None
    force_wrapping = False
    if prop.type_ == PropertyType.REF:
      dependency_namespace = self._ResolveTypeNamespace(prop.ref_type)
      if not dependency_namespace:
        raise KeyError('Cannot find referenced type: %s' % prop.ref_type)
      if self._namespace != dependency_namespace:
        cpp_type = '%s::%s' % (self._cpp_namespaces[dependency_namespace],
            schema_util.StripSchemaNamespace(prop.ref_type))
      else:
        cpp_type = schema_util.StripSchemaNamespace(prop.ref_type)
    elif prop.type_ == PropertyType.BOOLEAN:
      cpp_type = 'bool'
    elif prop.type_ == PropertyType.INTEGER:
      cpp_type = 'int'
    elif prop.type_ == PropertyType.DOUBLE:
      cpp_type = 'double'
    elif prop.type_ == PropertyType.STRING:
      cpp_type = 'std::string'
    elif prop.type_ == PropertyType.ENUM:
      cpp_type = cpp_util.Classname(prop.name)
    elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
      cpp_type = 'base::DictionaryValue'
    elif prop.type_ == PropertyType.ANY:
      cpp_type = any_helper.ANY_CLASS
    elif prop.type_ == PropertyType.OBJECT:
      cpp_type = cpp_util.Classname(prop.name)
    elif prop.type_ == PropertyType.ARRAY:
      item_type = prop.item_type
      if item_type.type_ == PropertyType.REF:
        item_type = self.GetReferencedProperty(item_type)
      if item_type.type_ in (
          PropertyType.REF, PropertyType.ANY, PropertyType.OBJECT):
        cpp_type = 'std::vector<linked_ptr<%s> > '
      else:
        cpp_type = 'std::vector<%s> '
      cpp_type = cpp_type % self.GetType(
          prop.item_type, pad_for_generics=True)
    elif prop.type_ == PropertyType.BINARY:
      # Since base::BinaryValue's are immutable, we wrap them in a scoped_ptr to
      # allow them to be modified after the fact.
      force_wrapping = True
      cpp_type = 'base::BinaryValue'
    else:
      raise NotImplementedError(prop.type_)

    # Enums aren't wrapped because C++ won't allow it. Optional enums have a
    # NONE value generated instead.
    if force_wrapping or (wrap_optional and prop.optional and prop.type_ !=
                          PropertyType.ENUM):
      cpp_type = 'scoped_ptr<%s> ' % cpp_type
    if pad_for_generics:
      return cpp_type
    return cpp_type.strip()
Beispiel #12
0
 def testStripSchemaNamespace(self):
     self.assertEquals('Bar', schema_util.StripSchemaNamespace('foo.Bar'))
     self.assertEquals('Baz', schema_util.StripSchemaNamespace('Baz'))
Beispiel #13
0
    def _GetTypeHelper(self,
                       prop,
                       pad_for_generics=False,
                       wrap_optional=False,
                       use_compiled_type=False):
        """Translates a model.Property into its C++ type.

    If REF types from different namespaces are referenced, will resolve
    using self._type_namespaces.

    Use pad_for_generics when using as a generic to avoid operator ambiguity.

    Use wrap_optional to wrap the type in a scoped_ptr<T> if the Property is
    optional.

    Use use_compiled_type when converting from prop.type_ to prop.compiled_type.
    """
        cpp_type = None
        type_ = prop.type_ if not use_compiled_type else prop.compiled_type

        if type_ == PropertyType.REF:
            dependency_namespace = self._ResolveTypeNamespace(prop.ref_type)
            if not dependency_namespace:
                raise KeyError('Cannot find referenced type: %s' %
                               prop.ref_type)
            if self._namespace != dependency_namespace:
                cpp_type = '%s::%s' % (
                    self._cpp_namespaces[dependency_namespace],
                    schema_util.StripSchemaNamespace(prop.ref_type))
            else:
                cpp_type = schema_util.StripSchemaNamespace(prop.ref_type)
        elif type_ == PropertyType.BOOLEAN:
            cpp_type = 'bool'
        elif type_ == PropertyType.INTEGER:
            cpp_type = 'int'
        elif type_ == PropertyType.INT64:
            cpp_type = 'int64'
        elif type_ == PropertyType.DOUBLE:
            cpp_type = 'double'
        elif type_ == PropertyType.STRING:
            cpp_type = 'std::string'
        elif type_ == PropertyType.ENUM:
            cpp_type = cpp_util.Classname(prop.name)
        elif type_ == PropertyType.ADDITIONAL_PROPERTIES:
            cpp_type = 'base::DictionaryValue'
        elif type_ == PropertyType.ANY:
            cpp_type = any_helper.ANY_CLASS
        elif type_ == PropertyType.OBJECT:
            cpp_type = cpp_util.Classname(prop.name)
        elif type_ == PropertyType.FUNCTION:
            # Functions come into the json schema compiler as empty objects. We can
            # record these as empty DictionaryValue's so that we know if the function
            # was passed in or not.
            cpp_type = 'base::DictionaryValue'
        elif type_ == PropertyType.ARRAY:
            item_type = prop.item_type
            if item_type.type_ == PropertyType.REF:
                item_type = self.GetReferencedProperty(item_type)
            if item_type.type_ in (PropertyType.REF, PropertyType.ANY,
                                   PropertyType.OBJECT):
                cpp_type = 'std::vector<linked_ptr<%s> > '
            else:
                cpp_type = 'std::vector<%s> '
            cpp_type = cpp_type % self.GetType(prop.item_type,
                                               pad_for_generics=True)
        elif type_ == PropertyType.BINARY:
            cpp_type = 'std::string'
        else:
            raise NotImplementedError(type_)

        # Enums aren't wrapped because C++ won't allow it. Optional enums have a
        # NONE value generated instead.
        if wrap_optional and prop.optional and not self.IsEnumOrEnumRef(prop):
            cpp_type = 'scoped_ptr<%s> ' % cpp_type
        if pad_for_generics:
            return cpp_type
        return cpp_type.strip()