Chromium Code Reviews| Index: tools/json_schema_compiler/cpp_type_generator.py |
| diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py |
| index a60b6e5cb381491d845fedbc392d0171e81eff60..a2682dedd1ec647f8909388e37fda2d39fad1cb5 100644 |
| --- a/tools/json_schema_compiler/cpp_type_generator.py |
| +++ b/tools/json_schema_compiler/cpp_type_generator.py |
| @@ -4,6 +4,7 @@ |
| from code import Code |
| from model import PropertyType |
| +import copy |
| import cpp_util |
| class CppTypeGenerator(object): |
| @@ -29,38 +30,85 @@ class CppTypeGenerator(object): |
| self._type_namespaces[type_] = namespace |
| self._cpp_namespaces[namespace] = cpp_namespace |
| + def ExpandedChoicesInParams(self, params): |
|
not at google - send to devlin
2012/02/08 05:02:08
nice
though try to make method names verbs, like
calamity
2012/02/08 07:01:18
Done.
|
| + """Returns the given parameters with PropertyType.CHOICES parameters |
| + expanded so that each choice is a separate parameter and sets a unix_name |
| + for each choice. |
| + """ |
| + expanded = [] |
| + for param in params: |
| + if param.type_ == PropertyType.CHOICES: |
| + for choice in param.choices.values(): |
| + choice_copy = copy.copy(choice) |
| + choice_copy.unix_name = (param.unix_name + '_' + |
| + repr(choice.type_).lower()) |
| + expanded.append(choice_copy) |
| + else: |
| + expanded.append(param) |
| + return expanded |
| + |
| def GetCppNamespaceName(self, namespace): |
| """Gets the mapped C++ namespace name for the given namespace relative to |
| the root namespace. |
| """ |
| return self._cpp_namespaces[namespace] |
| - def GetCppNamespaceStart(self): |
| - """Get opening namespace declarations. |
| + def GetRootNamespaceStart(self): |
| + """Get opening root namespace declarations. |
| """ |
| c = Code() |
| - for n in self._root_namespace: |
| - c.Append('namespace %s {' % n) |
| - c.Append('namespace %s {' % self.GetCppNamespaceName(self._namespace)) |
| + for namespace in self._root_namespace: |
| + c.Append('namespace %s {' % namespace) |
| return c |
| - def GetCppNamespaceEnd(self): |
| - """Get closing namespace declarations. |
| + def GetRootNamespaceEnd(self): |
| + """Get closing root namespace declarations. |
| """ |
| c = Code() |
| - c.Append('} // %s' % self.GetCppNamespaceName(self._namespace)) |
| - for n in reversed(self._root_namespace): |
| - c.Append('} // %s' % n) |
| + for namespace in reversed(self._root_namespace): |
| + c.Append('} // %s' % namespace) |
| return c |
| - # TODO(calamity): Handle ANY |
| - def GetType(self, prop, pad_for_generics=False): |
| + def GetNamespaceStart(self): |
| + """Get opening self._namespace namespace declaration. |
| + """ |
| + return Code().Append('namespace %s {' % |
| + self.GetCppNamespaceName(self._namespace)) |
| + |
| + def GetNamespaceEnd(self): |
| + """Get closing self._namespace namespace declaration. |
| + """ |
| + return Code().Append('} // %s' % |
| + self.GetCppNamespaceName(self._namespace)) |
| + |
| + def GetChoiceEnum(self, prop, type_): |
| + """Gets the enum of the choices in the given model.Property of the given |
| + type. |
| + |
| + e.g VAR_STRING |
| + """ |
| + if type_ is not None: |
| + assert prop.choices[type_] |
|
not at google - send to devlin
2012/02/08 05:02:08
won't prop.choices[type_] raise a TypeError if typ
calamity
2012/02/08 07:01:18
We don't actually use prop.choice[type_] otherwise
|
| + return '%s_%s' % (prop.unix_name.upper(), |
| + 'NONE' if type_ is None else repr(type_)) |
|
not at google - send to devlin
2012/02/08 05:02:08
Make this two separate methods rather than overloa
calamity
2012/02/08 07:01:18
Hah, wups. Yeah.
|
| + |
| + def GetChoicesEnumName(self, prop): |
|
not at google - send to devlin
2012/02/08 05:02:08
This function name is confusing me. It generates t
calamity
2012/02/08 07:01:18
Okay. Didn't know if enums were classified as type
|
| + """Gets the name of the enum for the given model.Property. |
| + |
| + e.g VarType |
| + """ |
| + return cpp_util.Classname(prop.name) + 'Type' |
| + |
| + 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 |
| if prop.type_ == PropertyType.REF: |
| @@ -71,7 +119,7 @@ class CppTypeGenerator(object): |
| cpp_type = '%s::%s' % (self._cpp_namespaces[dependency_namespace], |
| prop.ref_type) |
| else: |
| - cpp_type = '%s' % prop.ref_type |
| + cpp_type = prop.ref_type |
| elif prop.type_ == PropertyType.BOOLEAN: |
| cpp_type = 'bool' |
| elif prop.type_ == PropertyType.INTEGER: |
| @@ -80,47 +128,75 @@ class CppTypeGenerator(object): |
| cpp_type = 'double' |
| elif prop.type_ == PropertyType.STRING: |
| cpp_type = 'std::string' |
| + elif prop.type_ == PropertyType.ANY: |
| + cpp_type = 'DictionaryValue' |
| elif prop.type_ == PropertyType.ARRAY: |
| - cpp_type = 'std::vector<%s>' % self.GetType( |
| + if prop.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.OBJECT: |
| - cpp_type = cpp_util.CppName(prop.name) |
| - # TODO(calamity): choices |
| + cpp_type = cpp_util.Classname(prop.name) |
| else: |
| - raise NotImplementedError |
| + raise NotImplementedError(prop.type_) |
| + |
| + if wrap_optional and prop.optional: |
| + cpp_type = 'scoped_ptr<%s> ' % cpp_type |
| + if pad_for_generics: |
| + return cpp_type |
| + return cpp_type.strip() |
| + |
| + 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('}') |
| + return c |
| - # Add a space to prevent operator ambiguity |
| - if pad_for_generics and cpp_type[-1] == '>': |
| - return '%s ' % cpp_type |
| - return '%s' % cpp_type |
| + def GenerateIncludes(self): |
| + """Returns the #include lines for self._namespace. |
| + """ |
| + c = Code() |
| + for dependency in sorted(self._NamespaceTypeDependencies().keys()): |
| + c.Append('#include "%s/%s.h"' % ( |
| + dependency.source_file_dir, |
| + self._cpp_namespaces[dependency])) |
| + return c |
| - def GenerateCppIncludes(self): |
| - """Returns the #include lines for self._namespace using the other |
| - namespaces in self._model. |
| + def _NamespaceTypeDependencies(self): |
| + """Returns a dict containing a mapping of model.Namespace to the C++ type |
| + of type dependencies for self._namespace. |
| """ |
| dependencies = set() |
| for function in self._namespace.functions.values(): |
| for param in function.params: |
| - dependencies |= self._TypeDependencies(param) |
| - dependencies |= self._TypeDependencies(function.callback.param) |
| + dependencies |= self._PropertyTypeDependencies(param) |
| + for param in function.callback.params: |
| + dependencies |= self._PropertyTypeDependencies(param) |
| for type_ in self._namespace.types.values(): |
| for prop in type_.properties.values(): |
| - dependencies |= self._TypeDependencies(prop) |
| + dependencies |= self._PropertyTypeDependencies(prop) |
| - dependency_namespaces = set() |
| + dependency_namespaces = dict() |
| for dependency in dependencies: |
| - dependency_namespace = self._type_namespaces[dependency] |
| - if dependency_namespace != self._namespace: |
| - dependency_namespaces.add(dependency_namespace) |
| - |
| - includes = Code() |
| - for dependency_namespace in sorted(dependency_namespaces): |
| - includes.Append('#include "%s/%s.h"' % ( |
| - dependency_namespace.source_file_dir, |
| - self._cpp_namespaces[dependency_namespace])) |
| - return includes |
| - |
| - def _TypeDependencies(self, prop): |
| + namespace = self._type_namespaces[dependency] |
| + if namespace != self._namespace: |
| + if not dependency_namespaces.get(namespace): |
| + dependency_namespaces[namespace] = [] |
| + dependency_namespaces[namespace].append(dependency) |
| + return dependency_namespaces |
| + |
| + def _PropertyTypeDependencies(self, prop): |
| """Recursively gets all the type dependencies of a property. |
| """ |
| deps = set() |
| @@ -128,8 +204,8 @@ class CppTypeGenerator(object): |
| if prop.type_ == PropertyType.REF: |
| deps.add(prop.ref_type) |
| elif prop.type_ == PropertyType.ARRAY: |
| - deps = self._TypeDependencies(prop.item_type) |
| + deps = self._PropertyTypeDependencies(prop.item_type) |
| elif prop.type_ == PropertyType.OBJECT: |
| for p in prop.properties.values(): |
| - deps |= self._TypeDependencies(p) |
| + deps |= self._PropertyTypeDependencies(p) |
| return deps |