def Generate(self): """Generates a Code object with the .cc for a single namespace. """ cpp_namespace = cpp_util.GetCppNamespace( self._namespace.environment.namespace_pattern, self._namespace.unix_name) 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/stl_util.h"'). Append('#include "base/strings/string_number_conversions.h"'). Append('#include "base/strings/utf_string_conversions.h"').Append( '#include "%s/%s.h"' % (self._namespace.source_file_dir, self._namespace.short_filename)).Append('#include <set>').Cblock( self._type_helper.GenerateIncludes(include_soft=True) ).Append().Append('using base::UTF8ToUTF16;').Append().Concat( cpp_util.OpenNamespace(cpp_namespace))) if self._namespace.properties: (c.Append('//').Append('// Properties').Append('//').Append()) for prop in self._namespace.properties.values(): property_code = self._type_helper.GeneratePropertyValues( prop, '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.Cblock(cpp_util.CloseNamespace(cpp_namespace)) c.Append() 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(): prop_var = 'this->%s' % prop.unix_name 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_var, 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( 'value->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('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)) (c.Sblock( 'for (const auto& it : additional_properties) {').Cblock( self._CreateValueFromType( 'value->SetWithoutPathExpansion(it.first, %s);', type_.additional_properties.name, type_.additional_properties, '%sit.second' % ('*' if needs_unwrap else ''))).Eblock('}')) return (c.Append().Append('return value.Pass();').Eblock('}'))
def _GenerateFunction(self, function): """Generates the namespaces and structs for a function. """ c = Code() # TODO(kalman): Use function.unix_name not Classname here. function_namespace = cpp_util.Classname(function.name) (c.Append('namespace %s {' % function_namespace).Append().Cblock( self._GenerateFunctionParams(function))) if function.callback: c.Cblock(self._GenerateFunctionResults(function.callback)) c.Append('} // namespace %s' % function_namespace) 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()) c.Cblock(self._GenerateInterfaceObject()) c.Sblock('%s.prototype = {' % self._interface) for function in self._namespace.functions.values(): c.Cblock(self._GenerateFunction(function)) for event in self._namespace.events.values(): c.Cblock(self._GenerateEvent(event)) c.TrimTrailingNewlines() c.Eblock('};') return c
def Generate(self): """Generates a Code object with the .dart for the entire namespace. """ c = Code() (c.Append(LICENSE) .Append() .Append('// Generated from namespace: %s' % self._namespace.name) .Append() .Append('part of chrome;')) if self._types: (c.Append() .Append('/**') .Append(' * Types') .Append(' */') .Append() ) for type_ in self._types.values(): # Check for custom dart for this whole type. override = self._GetOverride([type_.name], document_with=type_) c.Cblock(override if override is not None else self._GenerateType(type_)) if self._namespace.events: (c.Append('/**') .Append(' * Events') .Append(' */') .Append() ) for event_name in self._namespace.events: c.Cblock(self._GenerateEvent(self._namespace.events[event_name])) (c.Append('/**') .Append(' * Functions') .Append(' */') .Append() ) c.Cblock(self._GenerateMainClass()) return c
def Generate(self): """Generates a Code object with the schema for the entire namespace. """ c = Code() (c.Append(LICENSE) .Append() .Append('/** @fileoverview Externs generated from namespace: %s */' % self._namespace.name) .Append()) c.Cblock(self._GenerateNamespaceObject()) for js_type in self._namespace.types.values(): c.Cblock(self._GenerateType(js_type)) for function in self._namespace.functions.values(): c.Cblock(self._GenerateFunction(function)) for event in self._namespace.events.values(): c.Cblock(self._GenerateEvent(event)) return c
def _GenerateType(self, cpp_namespace, type_): """Generates the function definitions for a type. """ 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: c.Cblock(self._GenerateType(cpp_namespace, type_.item_type)) elif type_.property_type in (PropertyType.CHOICES, PropertyType.OBJECT): if cpp_namespace is None: classname_in_namespace = classname else: classname_in_namespace = '%s::%s' % (cpp_namespace, classname) if type_.property_type == PropertyType.OBJECT: c.Cblock( self._GeneratePropertyFunctions(classname_in_namespace, type_.properties.values())) else: c.Cblock( self._GenerateTypes(classname_in_namespace, type_.choices)) (c.Append('%s::%s()' % (classname_in_namespace, classname)).Cblock( self._GenerateInitializersAndBody(type_)).Append( '%s::~%s() {}' % (classname_in_namespace, classname)).Append()) if type_.origin.from_json: c.Cblock( self._GenerateTypePopulate(classname_in_namespace, type_)) if cpp_namespace is None: # only generate for top-level types c.Cblock( self._GenerateTypeFromValue(classname_in_namespace, type_)) if type_.origin.from_client: c.Cblock( self._GenerateTypeToValue(classname_in_namespace, type_)) elif type_.property_type == PropertyType.ENUM: (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)).Cblock( self._GenerateEnumFromString(cpp_namespace, type_))) 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 _GenerateTypes(self, types, is_toplevel=False, generate_typedefs=False): """Generate the structures required by a property such as OBJECT classes and enums. """ c = Code() for type_ in types: c.Cblock( self._GenerateType(type_, is_toplevel=is_toplevel, generate_typedefs=generate_typedefs)) return c
def _GenerateCreateCallbackArguments(self, function): """Generates functions for passing parameters to a callback. """ c = Code() params = function.params c.Cblock(self._GenerateTypes((p.type_ for p in params), is_toplevel=True)) declaration_list = [] for param in params: if param.description: c.Comment(param.description) declaration_list.append(cpp_util.GetParameterDeclaration( param, self._type_helper.GetCppType(param.type_))) c.Append('scoped_ptr<base::ListValue> Create(%s);' % ', '.join(declaration_list)) return c
def _GenerateFunction(self, function): """Generates the namespaces and structs for a function. """ c = Code() # TODO(kalman): Use function.unix_name not Classname here. function_namespace = cpp_util.Classname(function.name) # Windows has a #define for SendMessage, so to avoid any issues, we need # to not use the name. if function_namespace == 'SendMessage': function_namespace = 'PassMessage' (c.Append('namespace %s {' % function_namespace).Append().Cblock( self._GenerateFunctionParams(function))) if function.returns_async: c.Cblock(self._GenerateFunctionResults(function.returns_async)) c.Append('} // namespace %s' % function_namespace) return c
def _GenerateAsyncResponseArguments(self, params): """Generates a function to create the arguments to pass as results to a function callback, promise or event details. """ c = Code() c.Cblock( self._GenerateTypes((p.type_ for p in params), is_toplevel=True)) declaration_list = [] for param in params: if param.description: c.Comment(param.description) declaration_list.append( cpp_util.GetParameterDeclaration( param, self._type_helper.GetCppType(param.type_))) c.Append('std::unique_ptr<base::ListValue> Create(%s);' % ', '.join(declaration_list)) return c
def _GenerateCreateCallbackArguments(self, cpp_namespace, 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.Cblock( self._CreateValueFromType('create_results->Append(%s);', param.name, 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 _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
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()) # Hack: for the purpose of gyp the header file will always be the source # file with its file extension replaced by '.h'. Assume so. output_file = os.path.splitext(self._namespace.source_file)[0] + '.h' ifndef_name = cpp_util.GenerateIfndefName(output_file) # Hack: tabs and windows have circular references, so only generate hard # references for them (i.e. anything that can't be forward declared). In # other cases, generate soft dependencies so that they can include # non-optional types from other namespaces. include_soft = self._namespace.name not in ('tabs', 'windows') (c.Append('#ifndef %s' % ifndef_name).Append( '#define %s' % ifndef_name).Append().Append('#include <stdint.h>'). Append().Append('#include <map>').Append('#include <memory>').Append( '#include <string>').Append('#include <vector>').Append().Append( '#include "base/values.h"').Cblock( self._type_helper.GenerateIncludes( include_soft=include_soft)).Append()) # Hack: we're not generating soft includes for tabs and windows, so we need # to generate forward declarations for them. if not include_soft: c.Cblock(self._type_helper.GenerateForwardDeclarations()) cpp_namespace = cpp_util.GetCppNamespace( self._namespace.environment.namespace_pattern, self._namespace.unix_name) c.Concat(cpp_util.OpenNamespace(cpp_namespace)) c.Append() if self._namespace.properties: (c.Append('//').Append('// Properties').Append('//').Append()) for prop in self._namespace.properties.values(): property_code = self._type_helper.GeneratePropertyValues( prop, 'extern const %(type)s %(name)s;') if property_code: c.Cblock(property_code) if self._namespace.types: (c.Append('//').Append('// Types').Append('//').Append().Cblock( self._GenerateTypes(self._FieldDependencyOrder(), is_toplevel=True, generate_typedefs=True))) if self._namespace.manifest_keys: c.Append('//') c.Append('// Manifest Keys') c.Append('//') c.Append() c.Cblock(self._GenerateManifestKeys()) 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(cpp_util.CloseNamespace(cpp_namespace)).Append().Append( '#endif // %s' % ifndef_name).Append()) return c
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})
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() ) # Hack: for the purpose of gyp the header file will always be the source # file with its file extension replaced by '.h'. Assume so. output_file = os.path.splitext(self._namespace.source_file)[0] + '.h' ifndef_name = cpp_util.GenerateIfndefName(output_file) (c.Append('#ifndef %s' % ifndef_name) .Append('#define %s' % ifndef_name) .Append() .Append('#include <map>') .Append('#include <string>') .Append('#include <vector>') .Append() .Append('#include "base/basictypes.h"') .Append('#include "base/logging.h"') .Append('#include "base/memory/linked_ptr.h"') .Append('#include "base/memory/scoped_ptr.h"') .Append('#include "base/values.h"') .Cblock(self._type_helper.GenerateIncludes()) .Append() ) # 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. c.Cblock(self._type_helper.GenerateForwardDeclarations( self._cpp_namespace_pattern)) cpp_namespace = cpp_util.GetCppNamespace(self._cpp_namespace_pattern, self._namespace.unix_name) c.Concat(cpp_util.OpenNamespace(cpp_namespace)) c.Append() if self._namespace.properties: (c.Append('//') .Append('// Properties') .Append('//') .Append() ) for property in self._namespace.properties.values(): property_code = self._type_helper.GeneratePropertyValues( property, 'extern const %(type)s %(name)s;') if property_code: c.Cblock(property_code) if self._namespace.types: (c.Append('//') .Append('// Types') .Append('//') .Append() .Cblock(self._GenerateTypes(self._FieldDependencyOrder(), is_toplevel=True, generate_typedefs=True)) ) 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(cpp_util.CloseNamespace(cpp_namespace)) .Append('#endif // %s' % ifndef_name) .Append() ) 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 <map>') .Append('#include <string>') .Append('#include <vector>') .Append() .Append('#include "base/basictypes.h"') .Append('#include "base/logging.h"') .Append('#include "base/memory/linked_ptr.h"') .Append('#include "base/memory/scoped_ptr.h"') .Append('#include "base/values.h"') .Cblock(self._type_helper.GenerateIncludes()) .Append() ) c.Concat(cpp_util.OpenNamespace(self._cpp_namespace)) # 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._type_helper.GenerateForwardDeclarations()) if not forward_declarations.IsEmpty(): (c.Append() .Cblock(forward_declarations) ) c.Concat(self._type_helper.GetNamespaceStart()) c.Append() if self._namespace.properties: (c.Append('//') .Append('// Properties') .Append('//') .Append() ) for property in self._namespace.properties.values(): property_code = self._type_helper.GeneratePropertyValues( property, 'extern const %(type)s %(name)s;') if property_code: c.Cblock(property_code) if self._namespace.types: (c.Append('//') .Append('// Types') .Append('//') .Append() .Cblock(self._GenerateTypes(self._FieldDependencyOrder(), is_toplevel=True, generate_typedefs=True)) ) 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()) .Concat(cpp_util.CloseNamespace(self._cpp_namespace)) .Append('#endif // %s' % ifndef_name) .Append() ) return c
def _GenerateType(self, type_): """Given a Type object, returns the Code with the .dart for this type's definition. Assumes this type is a Parameter Type (creatable by user), and creates an object that extends ChromeObject. All parameters are specifiable as named arguments in the constructor, and all methods are wrapped with getters and setters that hide the JS() implementation. """ c = Code() # Since enums are just treated as strings for now, don't generate their # type. # TODO(sashab): Find a nice way to wrap enum objects. if type_.property_type is PropertyType.ENUM: return c (c.Concat(self._GenerateDocumentation(type_)).Sblock( 'class %(type_name)s extends ChromeObject {')) # Check whether this type has function members. If it does, don't allow # public construction. add_public_constructor = all(not self._IsFunction(p.type_) for p in type_.properties.values()) constructor_fields = [ self._GeneratePropertySignature(p) for p in type_.properties.values() ] if add_public_constructor: (c.Append('/*').Append(' * Public constructor').Append( ' */').Sblock('%(type_name)s({%(constructor_fields)s}) {')) for prop_name in type_.properties: (c.Sblock('if (?%s)' % prop_name).Append( 'this.%s = %s;' % (prop_name, prop_name)).Eblock()) (c.Eblock('}').Append()) (c.Append('/*').Append(' * Private constructor').Append(' */').Append( '%(type_name)s._proxy(_jsObject) : super._proxy(_jsObject);')) # Add an accessor (getter & setter) for each property. properties = [ p for p in type_.properties.values() if not self._IsFunction(p.type_) ] if properties: (c.Append().Append('/*').Append(' * Public accessors').Append( ' */')) for prop in properties: override = self._GetOverride([type_.name, prop.name], document_with=prop) c.Concat(override if override is not None else self. _GenerateGetterAndSetter(type_, prop)) # Now add all the methods. methods = [ t for t in type_.properties.values() if self._IsFunction(t.type_) ] if methods: (c.Append().Append('/*').Append(' * Methods').Append(' */')) for prop in methods: # Check if there's an override for this method. override = self._GetOverride([type_.name, prop.name], document_with=prop) c.Cblock(override if override is not None else self. _GenerateFunction(prop.type_.function)) (c.Eblock('}').Substitute({ 'type_name': self._AddPrefix(type_.simple_name), 'constructor_fields': ', '.join(constructor_fields) })) return c