def Render(self): """Returns the Code object for the body of the .cc file, which handles the initialization of all features.""" c = Code() c.Append('%s::%s() {' % (self._provider_class, self._provider_class)) c.Sblock() for k in sorted(self._features.keys()): c.Sblock('{') feature = self._features[k] if type(feature) is list: c.Append('std::vector<Feature*> features;') for f in feature: c.Sblock('{') c.Concat(f.GetCode(self._feature_class)) c.Append('features.push_back(feature);') c.Eblock('}') c.Append( 'ComplexFeature* feature(new ComplexFeature(&features));') c.Append('feature->set_name("%s");' % k) else: c.Concat(feature.GetCode(self._feature_class)) c.Append('AddFeature("%s", feature);' % k) c.Eblock('}') c.Eblock('}') return c
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
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
def Render(self): """Returns the Code object for the body of the .cc file, which handles the initialization of all features.""" c = Code() c.Sblock() for k in sorted(self._features.keys()): c.Sblock('{') feature = self._features[k] c.Concat(feature.GetCode(self._feature_type)) c.Append('provider->AddFeature("%s", feature);' % k) c.Eblock('}') c.Eblock() return c
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
def testComment(self): long_comment = ('This comment is eighty nine characters in longness, ' 'that is, to use another word, length') c = Code() c.Comment(long_comment) self.assertEquals( '// This comment is eighty nine characters ' 'in longness, that is, to use another\n' '// word, length', c.Render()) c = Code() c.Sblock('sblock') c.Comment(long_comment) c.Eblock('eblock') c.Comment(long_comment) self.assertEquals( 'sblock\n' ' // This comment is eighty nine characters ' 'in longness, that is, to use\n' ' // another word, length\n' 'eblock\n' '// This comment is eighty nine characters in ' 'longness, that is, to use another\n' '// word, length', c.Render()) long_word = 'x' * 100 c = Code() c.Comment(long_word) self.assertEquals('// ' + 'x' * 77 + '\n' '// ' + 'x' * 23, c.Render())
def GeneratePropertyValues(self, prop, line, nodoc=False): """Generates the Code to display all value-containing properties. """ c = Code() if not nodoc: c.Comment(prop.description) if prop.value is not None: c.Append( line % { "type": self.GetCppType(prop.type_), "name": prop.name, "value": prop.value }) else: has_child_code = False c.Sblock('namespace %s {' % prop.name) for child_property in prop.type_.properties.values(): child_code = self.GeneratePropertyValues(child_property, line, nodoc=nodoc) if child_code: has_child_code = True c.Concat(child_code) c.Eblock('} // namespace %s' % prop.name) if not has_child_code: c = None return c
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
def _GenerateObjectDefinition(self, properties): """Given an OrderedDict of properties, returns a Code containing the description of an object. """ if not properties: return Code() c = Code() c.Sblock('{') first = True for field, prop in properties.items(): # Avoid trailing comma. # TODO(devlin): This will be unneeded, if/when # https://github.com/google/closure-compiler/issues/796 is fixed. if not first: c.Append(',', new_line=False) first = False js_type = self._TypeToJsType(prop.type_) if prop.optional: js_type = (Code(). Append('('). Concat(js_type, new_line=False). Append('|undefined)', new_line=False)) c.Append('%s: ' % field, strip_right=False) c.Concat(js_type, new_line=False) c.Eblock('}') return c
def _GenerateFunctionResult(self, function): """Generates functions for passing a function's result back. """ c = Code() c.Sblock('namespace Result {') params = function.callback.params if not params: c.Append('Value* Create();') else: c.Concat(self._GeneratePropertyStructures(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 self._cpp_type_generator.GetExpandedChoicesInParams(params): if param.description: c.Comment(param.description) if param.type_ == PropertyType.ANY: c.Comment("Value* Result::Create(Value*) not generated " "because it's redundant.") continue c.Append('Value* Create(const %s);' % cpp_util.GetParameterDeclaration( param, self._cpp_type_generator.GetType(param))) c.Eblock('};') return c
def _GenerateGetChoiceValue(self, cpp_namespace, prop): """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value> representing the choice value. """ c = Code() (c.Sblock( 'scoped_ptr<base::Value> ' '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {').Sblock( 'switch (%s_type) {' % prop.unix_name).Concat( self._GenerateReturnCase( self._cpp_type_generator.GetEnumNoneValue(prop), 'scoped_ptr<base::Value>()'))) for choice in self._cpp_type_generator.ExpandParams([prop]): c.Concat( self._GenerateReturnCase( self._cpp_type_generator.GetEnumValue( prop, choice.type_.name), 'make_scoped_ptr<base::Value>(%s)' % self._CreateValueFromProperty(choice, choice.unix_name))) (c.Eblock('}').Append('return scoped_ptr<base::Value>();').Eblock( '}').Append().Substitute({ 'cpp_namespace': cpp_namespace, 'choice': cpp_util.Classname(prop.name) })) return c
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
def Generate(self): """Generates a Code object with the schema for the entire namespace. """ c = Code() (c.Append(self._GetHeader(sys.argv[0], self._namespace.name)) .Append()) self._AppendInterfaceObject(c) c.Append() c.Sblock('%s.prototype = {' % self._interface) for function in self._namespace.functions.values(): self._AppendFunction(c, function) c.TrimTrailingNewlines() c.Eblock('};') c.Append() for event in self._namespace.events.values(): self._AppendEvent(c, event) c.TrimTrailingNewlines() return c
def _GenerateTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes the type into a |DictionaryValue|. E.g. for type "Foo" generates Foo::ToValue() """ c = Code() (c.Sblock( 'scoped_ptr<DictionaryValue> %s::ToValue() const {' % cpp_namespace).Append( 'scoped_ptr<DictionaryValue> value(new DictionaryValue());'). Append()) for prop in type_.properties.values(): if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: c.Append('value->MergeDictionary(&%s);' % prop.unix_name) else: if prop.optional: if prop.type_ == PropertyType.ENUM: c.Sblock( 'if (%s != %s)' % (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) else: c.Sblock('if (%s.get())' % prop.unix_name) c.Append('value->SetWithoutPathExpansion("%s", %s);' % (prop.name, self._CreateValueFromProperty( prop, 'this->' + prop.unix_name))) if prop.optional: c.Eblock() (c.Append().Append('return value.Pass();').Eblock('}')) return c
def _GenerateTypeJsDoc(self, js_type): """Generates the documentation for a type as a Code. Returns an empty code object if the object has no documentation. """ c = Code() c.Sblock(line='/**', line_prefix=' * ') if js_type.description: for line in js_type.description.splitlines(): c.Append(line) is_constructor = self._IsTypeConstructor(js_type) if is_constructor: c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4) else: c.Concat(self._GenerateTypedef(js_type.properties)) c.Append(self._GenerateSeeLink('type', js_type.simple_name)) c.Eblock(' */') var = 'var ' + js_type.simple_name if is_constructor: var += ' = function() {}' var += ';' c.Append(var) return c
def Generate(self): """Generates a Code object for features. """ c = Code() (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append( cpp_util.GENERATED_FEATURE_MESSAGE % self._source_file).Append(). Append('#include <string>').Append().Append( '#include "%s.h"' % self._source_file_filename).Append().Append( '#include "base/notreached.h"').Append().Concat( cpp_util.OpenNamespace(self._namespace)).Append()) # Generate the constructor. (c.Append('%s::%s() {' % (self._class_name, self._class_name)).Sblock()) for feature in self._feature_defs: c.Append('features_["%s"] = %s;' % (feature.name, cpp_util.FeatureNameToConstantName(feature.name))) (c.Eblock().Append('}').Append()) # Generate the ToString function. (c.Append( 'const char* %s::ToString(' '%s::ID id) const {' % (self._class_name, self._class_name)).Sblock().Append('switch (id) {').Sblock()) for feature in self._feature_defs: c.Append('case %s: return "%s";' % (cpp_util.FeatureNameToConstantName( feature.name), feature.name)) (c.Append('case kUnknown: break;').Append('case kEnumBoundary: break;') .Eblock().Append('}').Append('NOTREACHED();').Append('return "";')) (c.Eblock().Append('}').Append()) # Generate the FromString function. (c.Append( '%s::ID %s::FromString(' 'const std::string& id) const {' % (self._class_name, self._class_name)).Sblock().Append( 'const auto& it = features_.find(id);' % self._class_name).Append( 'return (it == features_.end()) ? kUnknown : it->second;'). Eblock().Append('}').Append().Cblock( cpp_util.CloseNamespace(self._namespace))) return c
def _GenerateObjectTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes an object-representing type into a base::DictionaryValue. """ c = Code() (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % cpp_namespace) .Append('scoped_ptr<base::DictionaryValue> value(' 'new base::DictionaryValue());') .Append() ) for prop in type_.properties.values(): if prop.optional: # Optional enum values are generated with a NONE enum value. underlying_type = self._type_helper.FollowRef(prop.type_) if underlying_type.property_type == PropertyType.ENUM: c.Sblock('if (%s != %s) {' % (prop.unix_name, self._type_helper.GetEnumNoneValue(prop.type_))) else: c.Sblock('if (%s.get()) {' % prop.unix_name) # ANY is a base::Value which is abstract and cannot be a direct member, so # it will always be a pointer. is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( prop.name, self._CreateValueFromType(prop.type_, 'this->%s' % prop.unix_name, is_ptr=is_ptr))) if prop.optional: c.Eblock('}') if type_.additional_properties is not None: if type_.additional_properties.property_type == PropertyType.ANY: c.Append('value->MergeDictionary(&additional_properties);') else: # Non-copyable types will be wrapped in a linked_ptr for inclusion in # maps, so we need to unwrap them. needs_unwrap = ( not self._type_helper.IsCopyable(type_.additional_properties)) cpp_type = self._type_helper.GetCppType(type_.additional_properties, is_in_container=True) (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' % cpp_util.PadForGenerics(cpp_type)) .Append(' additional_properties.begin();') .Append(' it != additional_properties.end(); ++it) {') .Append('value->SetWithoutPathExpansion(it->first, %s);' % self._CreateValueFromType( type_.additional_properties, '%sit->second' % ('*' if needs_unwrap else ''))) .Eblock('}') ) return (c.Append() .Append('return value.Pass();') .Eblock('}'))
def _GenerateObjectTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes an object-representing type into a base::DictionaryValue. """ c = Code() (c.Sblock('std::unique_ptr<base::DictionaryValue> %s::ToValue() const {' % cpp_namespace) .Append('std::unique_ptr<base::DictionaryValue> to_value_result(' 'new base::DictionaryValue());') .Append() ) for prop in type_.properties.values(): prop_var = 'this->%s' % prop.unix_name if prop.optional: underlying_type = self._type_helper.FollowRef(prop.type_) if underlying_type.property_type == PropertyType.ENUM: # Optional enum values are generated with a NONE enum value, # potentially from another namespace. maybe_namespace = '' if underlying_type.namespace != self._namespace: maybe_namespace = '%s::' % underlying_type.namespace.unix_name c.Sblock('if (%s != %s%s) {' % (prop_var, maybe_namespace, self._type_helper.GetEnumNoneValue(prop.type_))) else: c.Sblock('if (%s.get()) {' % prop_var) # ANY is a base::Value which is abstract and cannot be a direct member, so # it will always be a pointer. is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY c.Cblock(self._CreateValueFromType( 'to_value_result->SetWithoutPathExpansion("%s", %%s);' % prop.name, prop.name, prop.type_, prop_var, is_ptr=is_ptr)) if prop.optional: c.Eblock('}') if type_.additional_properties is not None: if type_.additional_properties.property_type == PropertyType.ANY: c.Append('to_value_result->MergeDictionary(&additional_properties);') else: (c.Sblock('for (const auto& it : additional_properties) {') .Cblock(self._CreateValueFromType( 'to_value_result->SetWithoutPathExpansion(it.first, %s);', type_.additional_properties.name, type_.additional_properties, 'it.second')) .Eblock('}') ) return (c.Append() .Append('return to_value_result;') .Eblock('}'))
def _GenerateEnumDeclaration(self, enum_name, type_): """Generate the declaration of a C++ enum. """ c = Code() c.Sblock('enum %s {' % enum_name) c.Append(self._type_helper.GetEnumNoneValue(type_) + ',') for value in type_.enum_values: c.Append(self._type_helper.GetEnumValue(type_, value) + ',') return c.Eblock('};')
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
def _GenerateFunction(self, function): """Generates the structs for a function. """ c = Code() (c.Sblock('namespace %s {' % cpp_util.Classname(function.name)).Concat( self._GenerateFunctionParams(function)).Append()) if function.callback: (c.Concat(self._GenerateFunctionResult(function)).Append()) c.Eblock('};') return c
def testLinePrefixes(self): c = Code() c.Sblock(line='/**', line_prefix=' * ') c.Sblock('@typedef {{') c.Append('foo: bar,') c.Sblock('baz: {') c.Append('x: y') c.Eblock('}') c.Eblock('}}') c.Eblock(line=' */') output = c.Render() self.assertMultiLineEqual( '/**\n' ' * @typedef {{\n' ' * foo: bar,\n' ' * baz: {\n' ' * x: y\n' ' * }\n' ' * }}\n' ' */', output)
def _GenerateEnumDeclaration(self, enum_name, prop, values): """Generate the declaration of a C++ enum for the given property and values. """ c = Code() c.Sblock('enum %s {' % enum_name) if prop.optional: c.Append(self._cpp_type_generator.GetEnumNoneValue(prop) + ',') for value in values: c.Append(self._cpp_type_generator.GetEnumValue(prop, value) + ',') (c.Eblock('};').Append()) return c
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.StripNamespace(type_.name)) c = Code() (c.Append('// static').Append('bool %(namespace)s::Populate(').Sblock( ' const base::Value& value, %(name)s* out) {')) if type_.property_type == PropertyType.CHOICES: for choice in type_.choices: value_type = cpp_util.GetValueType( self._type_helper.FollowRef(choice)) (c.Sblock('if (value.IsType(%s)) {' % value_type).Concat( self._GeneratePopulateVariableFromValue( choice, '(&value)', 'out->as_%s' % choice.unix_name, 'false', is_ptr=True)).Append('return true;').Eblock('}')) c.Append('return false;') elif type_.property_type == PropertyType.OBJECT: (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))'). Append(' return false;')) if type_.properties or type_.additional_properties is not None: c.Append('const base::DictionaryValue* dict = ' 'static_cast<const base::DictionaryValue*>(&value);') for prop in type_.properties.values(): c.Concat(self._InitializePropertyToDefault(prop, 'out')) for prop in type_.properties.values(): c.Concat( self._GenerateTypePopulateProperty(prop, 'dict', 'out')) if type_.additional_properties is not None: if type_.additional_properties.property_type == PropertyType.ANY: c.Append( 'out->additional_properties.MergeDictionary(dict);') else: cpp_type = self._type_helper.GetCppType( type_.additional_properties, is_in_container=True) (c.Append('for (base::DictionaryValue::Iterator it(*dict);' ).Sblock(' !it.IsAtEnd(); it.Advance()) {'). Append('%s tmp;' % cpp_type).Concat( self._GeneratePopulateVariableFromValue( type_.additional_properties, '(&it.value())', 'tmp', 'false')).Append( 'out->additional_properties[it.key()] = tmp;' ).Eblock('}')) c.Append('return true;') (c.Eblock('}').Substitute({ 'namespace': cpp_namespace, 'name': classname })) return c
def _GenerateTypeToValue(self, cpp_namespace, type_): """Generates a function that serializes the type into a |base::DictionaryValue|. E.g. for type "Foo" generates Foo::ToValue() """ c = Code() (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % cpp_namespace).Append( 'scoped_ptr<base::DictionaryValue> value(' 'new base::DictionaryValue());').Append()) for prop in type_.properties.values(): if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: c.Append('value->MergeDictionary(&%s);' % prop.unix_name) else: if prop.optional: if self._cpp_type_generator.IsEnumOrEnumRef(prop): c.Sblock( 'if (%s != %s) {' % (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) elif prop.type_ == PropertyType.CHOICES: c.Sblock( 'if (%s_type != %s) {' % (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) else: c.Sblock('if (%s.get()) {' % prop.unix_name) if prop.type_ == prop.compiled_type: c.Append('value->SetWithoutPathExpansion("%s", %s);' % (prop.name, self._CreateValueFromProperty( prop, 'this->' + prop.unix_name))) else: conversion_src = 'this->' + prop.unix_name if prop.optional: conversion_src = '*' + conversion_src (c.Append('%s %s;' % (self._cpp_type_generator.GetType( prop), prop.unix_name)).Append( cpp_util.GenerateCompiledTypeToTypeConversion( self._cpp_type_generator.GetReferencedProperty( prop), conversion_src, prop.unix_name) + ';').Append( 'value->SetWithoutPathExpansion("%s", %s);' % (prop.unix_name, self._CreateValueFromProperty( prop, prop.unix_name)))) if prop.optional: c.Eblock('}') (c.Append().Append('return value.Pass();').Eblock('}')) return c
def _GenerateEnumDeclaration(self, enum_name, type_): """Generate a code object with the declaration of a C++ enum. """ c = Code() c.Sblock('enum %s {' % enum_name) c.Append(self._type_helper.GetEnumNoneValue(type_) + ',') for value in type_.enum_values: current_enum_string = self._type_helper.GetEnumValue(type_, value) c.Append(current_enum_string + ',') c.Append('%s = %s,' % ( self._type_helper.GetEnumLastValue(type_), current_enum_string)) c.Eblock('};') return c
def _GenerateEvent(self, event): """Generates the interface for an event. """ c = Code() c.Sblock(line='/**', line_prefix=' * ') if (event.description): c.Comment(event.description, comment_prefix='') c.Append('@type {!ChromeEvent}') c.Append( self._js_util.GenerateSeeLink(self._namespace.name, 'event', event.name)) c.Eblock(' */') c.Append('%s: new ChromeEvent(),' % (event.name)) return c
def _GenerateMainClass(self): """Generates the main class for this file, which links to all functions and events. Returns a code object. """ c = Code() (c.Sblock('class API_%s {' % self._namespace.unix_name) .Append('/*') .Append(' * API connection') .Append(' */') .Append('Object _jsObject;') ) # Add events. if self._namespace.events: (c.Append() .Append('/*') .Append(' * Events') .Append(' */') ) for event_name in self._namespace.events: c.Append('Event_%s_%s %s;' % (self._namespace.unix_name, event_name, event_name)) # Add functions. if self._namespace.functions: (c.Append() .Append('/*') .Append(' * Functions') .Append(' */') ) for function in self._namespace.functions.values(): # Check for custom dart for this whole property. override = self._GetOverride([function.name], document_with=function) c.Cblock(override if override is not None else self._GenerateFunction(function)) # Add the constructor. c.Sblock('API_%s(this._jsObject) {' % self._namespace.unix_name) # Add events to constructor. for event_name in self._namespace.events: c.Append("%s = new Event_%s_%s(JS('', '#.%s', this._jsObject));" % (event_name, self._namespace.unix_name, event_name, event_name)) (c.Eblock('}') .Eblock('}') ) return c
def GetCode(self, feature_type): c = Code() c.Append('std::vector<Feature*> features;') for f in self.feature_list: # Sanity check that components of complex features have no shared values # set. assert not f.shared_values c.Sblock('{') c.Concat(f.GetCode(feature_type)) c.Append('features.push_back(feature);') c.Eblock('}') c.Append('ComplexFeature* feature(new ComplexFeature(&features));') c.Append('feature->set_name("%s");' % self.name) c.Concat(GetCodeForFeatureValues(self.shared_values)) return c
def _GenerateEvent(self, event): """Generates the code representing an event. For example: /** @type {!ChromeEvent} */ chrome.bookmarks.onChildrenReordered; """ c = Code() c.Sblock(line='/**', line_prefix=' * ') if (event.description): c.Comment(event.description, comment_prefix='') c.Append('@type {!ChromeEvent}') c.Append(self._GenerateSeeLink('event', event.name)) c.Eblock(' */') c.Append('chrome.%s.%s;' % (self._namespace.name, event.name)) return c