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 |