| 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..7b4424b4e731cb19891e8a666cc8a3dfc957c78d 100644
|
| --- a/tools/json_schema_compiler/cpp_type_generator.py
|
| +++ b/tools/json_schema_compiler/cpp_type_generator.py
|
| @@ -29,38 +29,88 @@ class CppTypeGenerator(object):
|
| self._type_namespaces[type_] = namespace
|
| self._cpp_namespaces[namespace] = cpp_namespace
|
|
|
| + def GetExpandedChoicesInParams(self, params):
|
| + """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.unix_name = (
|
| + param.unix_name + '_' + choice.type_.name.lower())
|
| + expanded.append(choice)
|
| + 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 GetChoiceEnumNoneValue(self, prop):
|
| + """Gets the enum of the choices in the given model.Property indicating no
|
| + choice has been set.
|
| + """
|
| + return '%s_NONE' % prop.unix_name.upper()
|
| +
|
| + def GetChoiceEnumValue(self, prop, type_):
|
| + """Gets the enum of the choices in the given model.Property of the given
|
| + type.
|
| +
|
| + e.g VAR_STRING
|
| + """
|
| + assert prop.choices[type_]
|
| + return '%s_%s' % (prop.unix_name.upper(), type_.name)
|
| +
|
| + def GetChoicesEnumType(self, prop):
|
| + """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 +121,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 +130,74 @@ 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()
|
|
|
| - # Add a space to prevent operator ambiguity
|
| - if pad_for_generics and cpp_type[-1] == '>':
|
| - return '%s ' % cpp_type
|
| - return '%s' % cpp_type
|
| + def GenerateForwardDeclarations(self):
|
| + """Returns the forward declarations for self._namespace.
|
|
|
| - def GenerateCppIncludes(self):
|
| - """Returns the #include lines for self._namespace using the other
|
| - namespaces in self._model.
|
| + 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
|
| +
|
| + 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 _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:
|
| + dependency_namespaces.setdefault(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 +205,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
|
|
|