cpp_type_generator.py revision cedac228d2dd51db4b79ea1e72c7f249408ee061
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from code import Code 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from model import PropertyType 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import cpp_util 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from json_parse import OrderedDict 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import schema_util 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _TypeDependency(object): 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Contains information about a dependency a namespace has on a type: the 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) type's model, and whether that dependency is "hard" meaning that it cannot be 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) forward declared. 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, type_, hard=False): 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.type_ = type_ 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.hard = hard 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetSortKey(self): 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '%s.%s' % (self.type_.namespace.name, self.type_.name) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CppTypeGenerator(object): 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Manages the types of properties and provides utilities for getting the 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C++ type out of a model.Property 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, model, schema_loader, default_namespace=None): 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Creates a cpp_type_generator. The given root_namespace should be of the 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format extensions::api::sub. The generator will generate code suitable for 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use in the given model's namespace. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._default_namespace = default_namespace 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self._default_namespace is None: 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._default_namespace = model.namespaces.values()[0] 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._schema_loader = schema_loader 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetCppNamespaceName(self, namespace): 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Gets the mapped C++ namespace name for the given namespace relative to 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the root namespace. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return namespace.unix_name 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetNamespaceStart(self): 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Get opening self._default_namespace namespace declaration. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Code().Append('namespace %s {' % 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.GetCppNamespaceName(self._default_namespace)) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetNamespaceEnd(self): 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Get closing self._default_namespace namespace declaration. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Code().Append('} // %s' % 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.GetCppNamespaceName(self._default_namespace)) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetEnumNoneValue(self, type_): 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Gets the enum value in the given model.Property indicating no value has 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) been set. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return '%s_NONE' % self.FollowRef(type_).unix_name.upper() 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) def GetEnumLastValue(self, type_): 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) """Gets the enum value in the given model.Property indicating the last value 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for the type. 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) """ 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return '%s_LAST' % self.FollowRef(type_).unix_name.upper() 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetEnumValue(self, type_, enum_value): 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Gets the enum value of the given model.Property of the given type. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.g VAR_STRING 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) value = cpp_util.Classname(enum_value.name.upper()) 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) prefix = (type_.cpp_enum_prefix_override or 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.FollowRef(type_).unix_name) 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value = '%s_%s' % (prefix.upper(), value) 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # To avoid collisions with built-in OS_* preprocessor definitions, we add a 78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # trailing slash to enum names that start with OS_. 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if value.startswith("OS_"): 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) value += "_" 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return value 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GetCppType(self, type_, is_ptr=False, is_in_container=False): 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Translates a model.Property or model.Type into its C++ type. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) If REF types from different namespaces are referenced, will resolve 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) using self._schema_loader. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Use |is_ptr| if the type is optional. This will wrap the type in a 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr if possible (it is not possible to wrap an enum). 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Use |is_in_container| if the type is appearing in a collection, e.g. a 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector or std::map. This will wrap it in the correct type with spacing. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = None 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if type_.property_type == PropertyType.REF: 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ref_type = self._FindType(type_.ref_type) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ref_type is None: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise KeyError('Cannot find referenced type: %s' % type_.ref_type) 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cpp_type = self.GetCppType(ref_type) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.BOOLEAN: 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'bool' 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.INTEGER: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'int' 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.INT64: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'int64' 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.DOUBLE: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'double' 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.STRING: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'std::string' 111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch elif type_.property_type in (PropertyType.ENUM, 112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PropertyType.OBJECT, 113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PropertyType.CHOICES): 114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if self._default_namespace is type_.namespace: 115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cpp_type = cpp_util.Classname(type_.name) 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch else: 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cpp_type = '%s::%s' % (type_.namespace.unix_name, 118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cpp_util.Classname(type_.name)) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.ANY: 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cpp_type = 'base::Value' 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.FUNCTION: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Functions come into the json schema compiler as empty objects. We can 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # record these as empty DictionaryValues so that we know if the function 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # was passed in or not. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'base::DictionaryValue' 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.ARRAY: 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_cpp_type = self.GetCppType(type_.item_type, is_in_container=True) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cpp_type = 'std::vector<%s>' % cpp_util.PadForGenerics(item_cpp_type) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.BINARY: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cpp_type = 'std::string' 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise NotImplementedError('Cannot get type of %s' % type_.property_type) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # HACK: optional ENUM is represented elsewhere with a _NONE value, so it 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # never needs to be wrapped in pointer shenanigans. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # TODO(kalman): change this - but it's an exceedingly far-reaching change. 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not self.FollowRef(type_).property_type == PropertyType.ENUM: 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if is_in_container and (is_ptr or not self.IsCopyable(type_)): 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif is_ptr: 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cpp_type = 'scoped_ptr<%s>' % cpp_util.PadForGenerics(cpp_type) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cpp_type 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def IsCopyable(self, type_): 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return not (self.FollowRef(type_).property_type in (PropertyType.ANY, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PropertyType.ARRAY, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PropertyType.OBJECT, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PropertyType.CHOICES)) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GenerateForwardDeclarations(self): 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Returns the forward declarations for self._default_namespace. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = Code() 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for namespace, dependencies in self._NamespaceTypeDependencies().items(): 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c.Append('namespace %s {' % namespace.unix_name) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for dependency in dependencies: 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # No point forward-declaring hard dependencies. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if dependency.hard: 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Add more ways to forward declare things as necessary. 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if dependency.type_.property_type in (PropertyType.CHOICES, 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PropertyType.OBJECT): 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c.Append('struct %s;' % dependency.type_.name) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Append('}') 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def GenerateIncludes(self, include_soft=False): 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Returns the #include lines for self._default_namespace. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = Code() 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for namespace, dependencies in self._NamespaceTypeDependencies().items(): 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for dependency in dependencies: 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if dependency.hard or include_soft: 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c.Append('#include "%s/%s.h"' % (namespace.source_file_dir, 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) namespace.unix_name)) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _FindType(self, full_name): 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Finds the model.Type with name |qualified_name|. If it's not from 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) |self._default_namespace| then it needs to be qualified. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) namespace = self._schema_loader.ResolveType(full_name, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._default_namespace) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if namespace is None: 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise KeyError('Cannot resolve type %s. Maybe it needs a prefix ' 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'if it comes from another namespace?' % full_name) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return namespace.types[schema_util.StripNamespace(full_name)] 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def FollowRef(self, type_): 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Follows $ref link of types to resolve the concrete type a ref refers to. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) If the property passed in is not of type PropertyType.REF, it will be 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) returned unchanged. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if type_.property_type != PropertyType.REF: 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return type_ 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self.FollowRef(self._FindType(type_.ref_type)) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def _NamespaceTypeDependencies(self): 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Returns a dict ordered by namespace name containing a mapping of 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model.Namespace to every _TypeDependency for |self._default_namespace|, 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sorted by the type's name. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dependencies = set() 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for function in self._default_namespace.functions.values(): 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for param in function.params: 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependencies |= self._TypeDependencies(param.type_, 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hard=not param.optional) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if function.callback: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for param in function.callback.params: 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependencies |= self._TypeDependencies(param.type_, 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hard=not param.optional) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for type_ in self._default_namespace.types.values(): 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for prop in type_.properties.values(): 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependencies |= self._TypeDependencies(prop.type_, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hard=not prop.optional) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for event in self._default_namespace.events.values(): 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for param in event.params: 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependencies |= self._TypeDependencies(param.type_, 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hard=not param.optional) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Make sure that the dependencies are returned in alphabetical order. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependency_namespaces = OrderedDict() 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for dependency in sorted(dependencies, key=_TypeDependency.GetSortKey): 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) namespace = dependency.type_.namespace 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if namespace is self._default_namespace: 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if namespace not in dependency_namespaces: 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependency_namespaces[namespace] = [] 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dependency_namespaces[namespace].append(dependency) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dependency_namespaces 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _TypeDependencies(self, type_, hard=False): 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Gets all the type dependencies of a property. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deps = set() 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if type_.property_type == PropertyType.REF: 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deps.add(_TypeDependency(self._FindType(type_.ref_type), hard=hard)) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.ARRAY: 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Non-copyable types are not hard because they are wrapped in linked_ptrs 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # when generated. Otherwise they're typedefs, so they're hard (though we 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # could generate those typedefs in every dependent namespace, but that 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # seems weird). 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deps = self._TypeDependencies(type_.item_type, 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hard=self.IsCopyable(type_.item_type)) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.CHOICES: 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for type_ in type_.choices: 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deps |= self._TypeDependencies(type_, hard=self.IsCopyable(type_)) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) elif type_.property_type == PropertyType.OBJECT: 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for p in type_.properties.values(): 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deps |= self._TypeDependencies(p.type_, hard=not p.optional) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return deps 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GeneratePropertyValues(self, property, line, nodoc=False): 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Generates the Code to display all value-containing properties. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = Code() 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not nodoc: 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Comment(property.description) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if property.value is not None: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Append(line % { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "type": self.GetCppType(property.type_), 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name": property.name, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "value": property.value 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_child_code = False 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Sblock('namespace %s {' % property.name) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for child_property in property.type_.properties.values(): 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) child_code = self.GeneratePropertyValues(child_property, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) line, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nodoc=nodoc) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if child_code: 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_child_code = True 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Concat(child_code) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Eblock('} // namespace %s' % property.name) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not has_child_code: 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = None 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c 285