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
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 _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 _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 _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 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: cpp_type = self.GetCppType(prop.type_) cpp_value = prop.value cpp_name = prop.name if cpp_type == 'std::string': cpp_value = '"%s"' % cpp_value cpp_type = 'char' cpp_name = '%s[]' % cpp_name c.Append(line % { "type": cpp_type, "name": cpp_name, "value": cpp_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 _FunctionToJsFunction(self, function): """Converts a model.Function to a JS type (i.e., function([params])...)""" c = Code() c.Append('function(') for i, param in enumerate(function.params): c.Concat(self._TypeToJsType(param.type_), new_line=False) if i is not len(function.params) - 1: c.Append(', ', new_line=False, strip_right=False) c.Append('):', new_line=False) if function.returns: c.Concat(self._TypeToJsType(function.returns), new_line=False) else: c.Append('void', new_line=False) return c
def _TypeToJsType(self, js_type): """Converts a model.Type to a JS type (number, Array, etc.)""" if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE): return Code().Append('number') if js_type.property_type is PropertyType.OBJECT: if js_type.properties: return self._GenerateObjectDefinition(js_type.properties) return Code().Append('Object') if js_type.property_type is PropertyType.ARRAY: return (Code().Append('!Array<'). Concat(self._TypeToJsType(js_type.item_type), new_line=False). Append('>', new_line=False)) if js_type.property_type is PropertyType.REF: ref_type = js_type.ref_type # Enums are defined as chrome.fooAPI.MyEnum, but types are defined simply # as MyType. if self._namespace.types[ref_type].property_type is PropertyType.ENUM: ref_type = '!chrome.%s.%s' % (self._namespace.name, ref_type) return Code().Append(ref_type) if js_type.property_type is PropertyType.CHOICES: c = Code() c.Append('(') for i, choice in enumerate(js_type.choices): c.Concat(self._TypeToJsType(choice), new_line=False) if i is not len(js_type.choices) - 1: c.Append('|', new_line=False) c.Append(')', new_line=False) return c if js_type.property_type is PropertyType.FUNCTION: return self._FunctionToJsFunction(js_type.function) if js_type.property_type is PropertyType.ANY: return Code().Append('*') if js_type.property_type.is_fundamental: return Code().Append(js_type.property_type.name) return Code().Append('?') # TODO(tbreisacher): Make this more specific.
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.Sblock('if (%(var)s.GetSize() != %(total)d) {') elif not num_required: c.Sblock('if (%(var)s.GetSize() > %(total)d) {') else: c.Sblock('if (%(var)s.GetSize() < %(required)d' ' || %(var)s.GetSize() > %(total)d) {') (c.Concat(self._GenerateError( '"expected %%(total)d arguments, got " ' '+ base::IntToString(%%(var)s.GetSize())')) .Append('return scoped_ptr<Params>();') .Eblock('}') .Substitute({ 'var': var, 'required': num_required, 'total': len(function.params), })) return c
def GeneratePropertyValues(self, property, line, nodoc=False): """Generates the Code to display all value-containing properties. """ c = Code() if not nodoc: c.Comment(property.description) if property.value is not None: c.Append( line % { "type": self.GetCppType(property.type_), "name": property.name, "value": property.value }) else: has_child_code = False c.Sblock('namespace %s {' % property.name) for child_property in property.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' % property.name) if not has_child_code: c = None return c
def _FunctionToJsFunction(self, namespace_name, function): """Converts a model.Function to a JS type (i.e., function([params])...)""" c = Code() c.Append('function(') c.Concat(self._FunctionParamsToJsParams(namespace_name, function.params), new_line=False) c.Append('): ', new_line=False, strip_right=False) if function.returns: c.Concat(self._TypeToJsType(namespace_name, function.returns), new_line=False) else: c.Append('void', new_line=False) return c
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
def GetCode(self, feature_type): """Returns the Code object for generating this feature.""" c = Code() cpp_feature_class = SIMPLE_FEATURE_CPP_CLASSES[feature_type] c.Append('%s* feature = new %s();' % (cpp_feature_class, cpp_feature_class)) c.Append('feature->set_name("%s");' % self.name) c.Concat(GetCodeForFeatureValues(self.GetAllFeatureValues())) return c
def testSameLineAppendAndConcat(self): c = Code() c.Append('This is a line.') c.Append('This too.', new_line=False) d = Code() d.Append('And this.') c.Concat(d, new_line=False) self.assertEquals('This is a line.This too.And this.', c.Render())
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 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 "base/logging.h"') .Append('#include "base/strings/string_number_conversions.h"') .Append('#include "%s/%s.h"' % (self._namespace.source_file_dir, self._namespace.unix_name)) .Cblock(self._type_helper.GenerateIncludes(include_soft=True)) .Append() .Concat(cpp_util.OpenNamespace(self._cpp_namespace)) .Cblock(self._type_helper.GetNamespaceStart()) ) if self._namespace.properties: (c.Append('//') .Append('// Properties') .Append('//') .Append() ) for property in self._namespace.properties.values(): property_code = self._type_helper.GeneratePropertyValues( property, 'const %(type)s %(name)s = %(value)s;', nodoc=True) if property_code: c.Cblock(property_code) if self._namespace.types: (c.Append('//') .Append('// Types') .Append('//') .Append() .Cblock(self._GenerateTypes(None, self._namespace.types.values())) ) if self._namespace.functions: (c.Append('//') .Append('// Functions') .Append('//') .Append() ) for function in self._namespace.functions.values(): c.Cblock(self._GenerateFunction(function)) if self._namespace.events: (c.Append('//') .Append('// Events') .Append('//') .Append() ) for event in self._namespace.events.values(): c.Cblock(self._GenerateEvent(event)) (c.Concat(self._type_helper.GetNamespaceEnd()) .Cblock(cpp_util.CloseNamespace(self._cpp_namespace)) ) return c
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())
def _GeneratePropertyFunctions(self, param_namespace, params): """Generate the functions for structures generated by a property such as CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. """ c = Code() for param in params: if param.type_ == PropertyType.OBJECT: c.Concat(self._GenerateType( param_namespace + '::' + cpp_util.Classname(param.name), param)) c.Append() elif param.type_ == PropertyType.CHOICES: c.Concat(self._GeneratePropertyFunctions( param_namespace, param.choices.values())) elif param.type_ == PropertyType.ENUM: c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) c.Append() 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 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())
def _GenerateTypedef(self, properties): """Given an OrderedDict of properties, returns a Code containing a @typedef. """ if not properties: return Code() c = Code() c.Append('@typedef {') c.Concat(self._GenerateObjectDefinition(properties), new_line=False) c.Append('}', new_line=False) return c
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: c.Append('struct %s;' % type_) c.Append('}') c.Concat(self.GetNamespaceStart()) for (name, type_) in self._namespace.types.items(): if not type_.functions: c.Append('struct %s;' % name) c.Concat(self.GetNamespaceEnd()) 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 _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( 'scoped_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('scoped_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 = 'scoped_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->IsType(base::Value::TYPE_NULL)) {'). 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.Pass();').Eblock('}').Append()) return c
def GenerateForwardDeclarations(self): """Returns the forward declarations for self._default_namespace. """ c = Code() for namespace, deps in self._NamespaceTypeDependencies().iteritems(): filtered_deps = [ dep for dep in deps # Add more ways to forward declare things as necessary. if (not dep.hard and dep.type_.property_type in ( PropertyType.CHOICES, PropertyType.OBJECT)) ] if not filtered_deps: continue cpp_namespace = cpp_util.GetCppNamespace( namespace.environment.namespace_pattern, namespace.unix_name) c.Concat(cpp_util.OpenNamespace(cpp_namespace)) for dep in filtered_deps: c.Append('struct %s;' % dep.type_.name) c.Concat(cpp_util.CloseNamespace(cpp_namespace)) return c
def Generate(self): """Generates a Code object with the .h for a single namespace. """ c = Code() (c.Append(cpp_util.CHROMIUM_LICENSE).Append().Append( cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file).Append()) ifndef_name = cpp_util.GenerateIfndefName( self._namespace.source_file_dir, self._target_namespace) (c.Append('#ifndef %s' % ifndef_name).Append( '#define %s' % ifndef_name).Append().Append('#include <string>').Append( '#include <vector>').Append().Append( '#include "base/basictypes.h"'). Append('#include "base/memory/linked_ptr.h"').Append( '#include "base/memory/scoped_ptr.h"').Append( '#include "base/values.h"').Append( '#include "tools/json_schema_compiler/any.h"').Append()) c.Concat(self._cpp_type_generator.GetRootNamespaceStart()) # TODO(calamity): These forward declarations should be #includes to allow # $ref types from other files to be used as required params. This requires # some detangling of windows and tabs which will currently lead to circular # #includes. forward_declarations = ( self._cpp_type_generator.GenerateForwardDeclarations()) if not forward_declarations.IsEmpty(): (c.Append().Concat(forward_declarations).Append()) c.Concat(self._cpp_type_generator.GetNamespaceStart()) c.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, 'extern const %(type)s %(name)s;') if property_code: c.Concat(property_code).Append() if self._namespace.types: (c.Append('//').Append('// Types').Append('//').Append()) for type_ in self._FieldDependencyOrder(): (c.Concat(self._GenerateType(type_)).Append()) if self._namespace.functions: (c.Append('//').Append('// Functions').Append('//').Append()) for function in self._namespace.functions.values(): (c.Concat(self._GenerateFunction(function)).Append()) if self._namespace.events: (c.Append('//').Append('// Events').Append('//').Append()) for event in self._namespace.events.values(): (c.Concat(self._GenerateEvent(event)).Append()) (c.Concat(self._cpp_type_generator.GetNamespaceEnd()).Concat( self._cpp_type_generator.GetRootNamespaceEnd()).Append().Append( '#endif // %s' % ifndef_name).Append()) return c
def _GeneratePropertyStructures(self, props): """Generate the structures required by a property such as OBJECT classes and enums. """ c = Code() for prop in props: if prop.type_ == PropertyType.OBJECT: c.Concat(self._GenerateType(prop)) c.Append() elif prop.type_ == PropertyType.ARRAY: c.Concat(self._GeneratePropertyStructures([prop.item_type])) c.Append() elif prop.type_ == PropertyType.CHOICES: c.Concat(self._GenerateEnumDeclaration( self._cpp_type_generator.GetChoicesEnumType(prop), prop, [choice.type_.name for choice in prop.choices.values()])) c.Concat(self._GeneratePropertyStructures(prop.choices.values())) elif prop.type_ == PropertyType.ENUM: enum_name = self._cpp_type_generator.GetCompiledType(prop) c.Concat(self._GenerateEnumDeclaration( enum_name, prop, prop.enum_values)) create_enum_value = ('scoped_ptr<base::Value> CreateEnumValue(%s %s);' % (enum_name, prop.unix_name)) enum_to_string = 'std::string ToString(%s enum_param);' % enum_name enum_from_string = ('%s From%sString(const std::string& enum_string);' % (enum_name, enum_name)) # If the property is from the UI then we're in a struct so this function # should be static. If it's from the client, then we're just in a # namespace so we can't have the static keyword. if prop.from_json: create_enum_value = 'static %s' % create_enum_value enum_to_string = 'static %s' % enum_to_string enum_from_string = 'static %s' % enum_from_string (c.Append(create_enum_value) .Append(enum_to_string) .Append(enum_from_string)) 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 testConcat(self): b = Code() (b.Sblock('2').Append('2').Eblock('2')) c = Code() (c.Sblock('1').Concat(b).Append('1').Eblock('1')) self.assertEquals('1\n' ' 2\n' ' 2\n' ' 2\n' ' 1\n' '1', c.Render()) d = Code() a = Code() a.Concat(d) self.assertEquals('', a.Render()) a.Concat(c) self.assertEquals('1\n' ' 2\n' ' 2\n' ' 2\n' ' 1\n' '1', a.Render())