OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from code import Code | 5 from code import Code |
6 from model import PropertyType | 6 from model import PropertyType, Type |
7 import any_helper | |
8 import cpp_util | 7 import cpp_util |
9 import model | 8 import model |
10 import schema_util | 9 import schema_util |
11 import sys | 10 import sys |
12 import util_cc_helper | 11 import util_cc_helper |
13 | 12 |
14 class CCGenerator(object): | 13 class CCGenerator(object): |
15 """A .cc generator for a namespace. | 14 """A .cc generator for a namespace. |
16 """ | 15 """ |
17 def __init__(self, namespace, cpp_type_generator): | 16 def __init__(self, namespace, cpp_type_generator): |
18 self._cpp_type_generator = cpp_type_generator | 17 self._type_helper = cpp_type_generator |
19 self._namespace = namespace | 18 self._namespace = namespace |
20 self._target_namespace = ( | 19 self._target_namespace = ( |
21 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 20 self._type_helper.GetCppNamespaceName(self._namespace)) |
22 self._util_cc_helper = ( | 21 self._util_cc_helper = ( |
23 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | 22 util_cc_helper.UtilCCHelper(self._type_helper)) |
24 self._any_helper = any_helper.AnyHelper() | |
25 | 23 |
26 def Generate(self): | 24 def Generate(self): |
27 """Generates a Code object with the .cc for a single namespace. | 25 """Generates a Code object with the .cc for a single namespace. |
28 """ | 26 """ |
29 c = Code() | 27 c = Code() |
30 (c.Append(cpp_util.CHROMIUM_LICENSE) | 28 (c.Append(cpp_util.CHROMIUM_LICENSE) |
31 .Append() | 29 .Append() |
32 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 30 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
33 .Append() | 31 .Append() |
34 .Append(self._util_cc_helper.GetIncludePath()) | 32 .Append(self._util_cc_helper.GetIncludePath()) |
35 .Append('#include "%s/%s.h"' % | 33 .Append('#include "%s/%s.h"' % |
36 (self._namespace.source_file_dir, self._namespace.unix_name)) | 34 (self._namespace.source_file_dir, self._namespace.unix_name)) |
37 ) | 35 .Append('#include "base/logging.h"') |
38 includes = self._cpp_type_generator.GenerateIncludes() | 36 .Cblock(self._type_helper.GenerateIncludes()) |
39 if not includes.IsEmpty(): | 37 .Concat(self._type_helper.GetRootNamespaceStart()) |
40 (c.Concat(includes) | 38 .Cblock(self._type_helper.GetNamespaceStart()) |
41 .Append() | |
42 ) | |
43 | |
44 (c.Append() | |
45 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) | |
46 .Concat(self._cpp_type_generator.GetNamespaceStart()) | |
47 .Append() | |
48 ) | 39 ) |
49 if self._namespace.properties: | 40 if self._namespace.properties: |
50 (c.Append('//') | 41 (c.Append('//') |
51 .Append('// Properties') | 42 .Append('// Properties') |
52 .Append('//') | 43 .Append('//') |
53 .Append() | 44 .Append() |
54 ) | 45 ) |
55 for property in self._namespace.properties.values(): | 46 for property in self._namespace.properties.values(): |
56 property_code = self._cpp_type_generator.GeneratePropertyValues( | 47 property_code = self._type_helper.GeneratePropertyValues( |
57 property, | 48 property, |
58 'const %(type)s %(name)s = %(value)s;', | 49 'const %(type)s %(name)s = %(value)s;', |
59 nodoc=True) | 50 nodoc=True) |
60 if property_code: | 51 if property_code: |
61 c.Concat(property_code).Append() | 52 c.Cblock(property_code) |
62 if self._namespace.types: | 53 if self._namespace.types: |
63 (c.Append('//') | 54 (c.Append('//') |
64 .Append('// Types') | 55 .Append('// Types') |
65 .Append('//') | 56 .Append('//') |
66 .Append() | 57 .Append() |
67 ) | 58 .Cblock(self._GenerateTypes(None, self._namespace.types.values())) |
68 for type_ in self._namespace.types.values(): | |
69 (c.Concat(self._GenerateType( | |
70 schema_util.StripSchemaNamespace(type_.name), type_)).Append() | |
71 ) | 59 ) |
72 if self._namespace.functions: | 60 if self._namespace.functions: |
73 (c.Append('//') | 61 (c.Append('//') |
74 .Append('// Functions') | 62 .Append('// Functions') |
75 .Append('//') | 63 .Append('//') |
76 .Append() | 64 .Append() |
77 ) | 65 ) |
78 for function in self._namespace.functions.values(): | 66 for function in self._namespace.functions.values(): |
79 (c.Concat(self._GenerateFunction( | 67 c.Cblock(self._GenerateFunction(function)) |
80 cpp_util.Classname(function.name), function)) | |
81 .Append() | |
82 ) | |
83 if self._namespace.events: | 68 if self._namespace.events: |
84 (c.Append('//') | 69 (c.Append('//') |
85 .Append('// Events') | 70 .Append('// Events') |
86 .Append('//') | 71 .Append('//') |
87 .Append() | 72 .Append() |
88 ) | 73 ) |
89 for event in self._namespace.events.values(): | 74 for event in self._namespace.events.values(): |
90 (c.Concat(self._GenerateCreateCallbackArguments( | 75 c.Cblock(self._GenerateEvent(event)) |
91 cpp_util.Classname(event.name), event, generate_to_json=True)) | 76 (c.Concat(self._type_helper.GetNamespaceEnd()) |
92 .Append() | 77 .Cblock(self._type_helper.GetRootNamespaceEnd()) |
93 ) | |
94 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) | |
95 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | |
96 .Append() | |
97 ) | 78 ) |
98 return c | 79 return c |
99 | 80 |
100 def _GenerateType(self, cpp_namespace, type_): | 81 def _GenerateType(self, cpp_namespace, type_): |
101 """Generates the function definitions for a type. | 82 """Generates the function definitions for a type. |
102 """ | 83 """ |
103 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 84 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
104 c = Code() | 85 c = Code() |
105 | 86 |
106 if type_.functions: | 87 if type_.functions: |
| 88 # Wrap functions within types in the type's namespace. |
| 89 (c.Append('namespace %s {' % classname) |
| 90 .Append()) |
107 for function in type_.functions.values(): | 91 for function in type_.functions.values(): |
108 (c.Concat( | 92 c.Cblock(self._GenerateFunction(function)) |
109 self._GenerateFunction( | 93 c.Append('} // namespace %s' % classname) |
110 cpp_namespace + '::' + cpp_util.Classname(function.name), | 94 elif type_.property_type == PropertyType.ARRAY: |
111 function)) | 95 c.Cblock(self._GenerateType(cpp_namespace, type_.item_type)) |
112 .Append()) | 96 elif (type_.property_type == PropertyType.OBJECT or |
113 elif type_.type_ == PropertyType.OBJECT: | 97 type_.property_type == PropertyType.CHOICES): |
114 (c.Concat(self._GeneratePropertyFunctions( | 98 if cpp_namespace is None: |
115 cpp_namespace, type_.properties.values())) | 99 classname_in_namespace = classname |
116 .Sblock('%(namespace)s::%(classname)s()') | 100 else: |
117 .Concat(self._GenerateInitializersAndBody(type_)) | 101 classname_in_namespace = '%s::%s' % (cpp_namespace, classname) |
118 .Eblock('%(namespace)s::~%(classname)s() {}') | 102 |
119 .Append()) | 103 if type_.property_type == PropertyType.OBJECT: |
120 if type_.from_json: | 104 c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace, |
121 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | 105 type_.properties.values())) |
122 .Append()) | 106 else: |
123 if type_.from_client: | 107 c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices)) |
124 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | 108 |
125 .Append()) | 109 (c.Append('%s::%s()' % (classname_in_namespace, classname)) |
126 elif self._cpp_type_generator.IsEnumOrEnumRef(type_): | 110 .Cblock(self._GenerateInitializersAndBody(type_)) |
127 (c.Concat(self._GenerateCreateEnumTypeValue(cpp_namespace, type_)) | 111 .Append('%s::~%s() {}' % (classname_in_namespace, classname)) |
128 .Append() | 112 .Append() |
129 .Concat(self._GenerateEnumFromString(cpp_namespace, type_)) | 113 ) |
130 .Append() | 114 if type_.origin.from_json: |
131 .Concat(self._GenerateEnumToString(cpp_namespace, type_)) | 115 c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_)) |
132 .Append()) | 116 if type_.origin.from_client: |
133 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) | 117 c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_)) |
| 118 elif type_.property_type == PropertyType.ENUM: |
| 119 (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) |
| 120 .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) |
| 121 ) |
134 | 122 |
135 return c | 123 return c |
136 | 124 |
137 def _GenerateInitializersAndBody(self, type_): | 125 def _GenerateInitializersAndBody(self, type_): |
138 items = [] | 126 items = [] |
139 for prop in type_.properties.values(): | 127 for prop in type_.properties.values(): |
140 if prop.optional: | 128 if prop.optional: |
141 continue | 129 continue |
142 | 130 |
143 t = prop.type_ | 131 t = prop.type_ |
144 if t == PropertyType.INTEGER: | 132 if t.property_type == PropertyType.INTEGER: |
145 items.append('%s(0)' % prop.unix_name) | 133 items.append('%s(0)' % prop.unix_name) |
146 elif t == PropertyType.DOUBLE: | 134 elif t.property_type == PropertyType.DOUBLE: |
147 items.append('%s(0.0)' % prop.unix_name) | 135 items.append('%s(0.0)' % prop.unix_name) |
148 elif t == PropertyType.BOOLEAN: | 136 elif t.property_type == PropertyType.BOOLEAN: |
149 items.append('%s(false)' % prop.unix_name) | 137 items.append('%s(false)' % prop.unix_name) |
150 elif t == PropertyType.BINARY: | 138 elif t.property_type == PropertyType.BINARY: |
151 items.append('%s(NULL)' % prop.unix_name) | 139 items.append('%s(NULL)' % prop.unix_name) |
152 elif (t == PropertyType.ADDITIONAL_PROPERTIES or | 140 elif (t.property_type == PropertyType.ANY or |
153 t == PropertyType.ANY or | 141 t.property_type == PropertyType.ARRAY or |
154 t == PropertyType.ARRAY or | 142 t.property_type == PropertyType.CHOICES or |
155 t == PropertyType.CHOICES or | 143 t.property_type == PropertyType.ENUM or |
156 t == PropertyType.ENUM or | 144 t.property_type == PropertyType.OBJECT or |
157 t == PropertyType.OBJECT or | 145 t.property_type == PropertyType.FUNCTION or |
158 t == PropertyType.FUNCTION or | 146 t.property_type == PropertyType.REF or |
159 t == PropertyType.REF or | 147 t.property_type == PropertyType.STRING): |
160 t == PropertyType.STRING): | |
161 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we | 148 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we |
162 # don't presently have the semantics to indicate which one of a set | 149 # don't presently have the semantics to indicate which one of a set |
163 # should be the default. | 150 # should be the default. |
164 continue | 151 continue |
165 else: | 152 else: |
166 sys.exit("Unhandled PropertyType: %s" % t) | 153 raise TypeError(t) |
167 | 154 |
168 if items: | 155 if items: |
169 s = ': %s' % (', '.join(items)) | 156 s = ': %s' % (', '.join(items)) |
170 else: | 157 else: |
171 s = '' | 158 s = '' |
172 s = s + ' {}' | 159 s = s + ' {}' |
173 return Code().Append(s) | 160 return Code().Append(s) |
174 | 161 |
175 def _GenerateTypePopulate(self, cpp_namespace, type_): | 162 def _GenerateTypePopulate(self, cpp_namespace, type_): |
176 """Generates the function for populating a type given a pointer to it. | 163 """Generates the function for populating a type given a pointer to it. |
177 | 164 |
178 E.g for type "Foo", generates Foo::Populate() | 165 E.g for type "Foo", generates Foo::Populate() |
179 """ | 166 """ |
180 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 167 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
181 c = Code() | 168 c = Code() |
182 (c.Append('// static') | 169 (c.Append('// static') |
183 .Sblock('bool %(namespace)s::Populate' | 170 .Append('bool %(namespace)s::Populate(') |
184 '(const base::Value& value, %(name)s* out) {') | 171 .Sblock(' const base::Value& value, %(name)s* out) {') |
185 .Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') | 172 ) |
| 173 if type_.property_type == PropertyType.CHOICES: |
| 174 for choice in type_.choices: |
| 175 value_type = cpp_util.GetValueType(self._type_helper.FollowRef(choice)) |
| 176 (c.Sblock('if (value.IsType(%s)) {' % value_type) |
| 177 .Concat(self._GeneratePopulateVariableFromValue( |
| 178 choice, |
| 179 '(&value)', |
| 180 'out->as_%s' % choice.unix_name, |
| 181 'false', |
| 182 is_ptr=True)) |
| 183 .Append('return true;') |
| 184 .Eblock('}') |
| 185 ) |
| 186 c.Append('return false;') |
| 187 elif type_.property_type == PropertyType.OBJECT: |
| 188 (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') |
186 .Append(' return false;') | 189 .Append(' return false;') |
187 ) | |
188 if type_.properties: | |
189 (c.Append('const base::DictionaryValue* dict = ' | |
190 'static_cast<const base::DictionaryValue*>(&value);') | |
191 .Append() | |
192 ) | 190 ) |
| 191 if type_.properties or type_.additional_properties is not None: |
| 192 c.Append('const base::DictionaryValue* dict = ' |
| 193 'static_cast<const base::DictionaryValue*>(&value);') |
193 for prop in type_.properties.values(): | 194 for prop in type_.properties.values(): |
194 c.Concat(self._InitializePropertyToDefault(prop, 'out')) | 195 c.Concat(self._InitializePropertyToDefault(prop, 'out')) |
195 for prop in type_.properties.values(): | 196 for prop in type_.properties.values(): |
196 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 197 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
| 198 if type_.additional_properties is not None: |
| 199 if type_.additional_properties.property_type == PropertyType.ANY: |
197 c.Append('out->additional_properties.MergeDictionary(dict);') | 200 c.Append('out->additional_properties.MergeDictionary(dict);') |
198 # remove all keys that are actual properties | |
199 for cur_prop in type_.properties.values(): | |
200 if prop != cur_prop: | |
201 c.Append('out->additional_properties' | |
202 '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name) | |
203 c.Append() | |
204 else: | 201 else: |
205 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | 202 cpp_type = self._type_helper.GetCppType(type_.additional_properties, |
206 (c.Append('return true;') | 203 is_in_container=True) |
207 .Eblock('}') | 204 (c.Append('for (base::DictionaryValue::Iterator it(*dict);') |
208 ) | 205 .Sblock(' it.HasNext(); it.Advance()) {') |
209 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | 206 .Append('%s tmp;' % cpp_type) |
| 207 .Concat(self._GeneratePopulateVariableFromValue( |
| 208 type_.additional_properties, |
| 209 '(&it.value())', |
| 210 'tmp', |
| 211 'false')) |
| 212 .Append('out->additional_properties[it.key()] = tmp;') |
| 213 .Eblock('}') |
| 214 ) |
| 215 c.Append('return true;') |
| 216 (c.Eblock('}') |
| 217 .Substitute({'namespace': cpp_namespace, 'name': classname})) |
210 return c | 218 return c |
211 | 219 |
212 def _GenerateTypePopulateProperty(self, prop, src, dst): | 220 def _GenerateTypePopulateProperty(self, prop, src, dst): |
213 """Generate the code to populate a single property in a type. | 221 """Generate the code to populate a single property in a type. |
214 | 222 |
215 src: base::DictionaryValue* | 223 src: base::DictionaryValue* |
216 dst: Type* | 224 dst: Type* |
217 """ | 225 """ |
218 c = Code() | 226 c = Code() |
219 value_var = prop.unix_name + '_value' | 227 value_var = prop.unix_name + '_value' |
220 c.Append('const base::Value* %(value_var)s = NULL;') | 228 c.Append('const base::Value* %(value_var)s = NULL;') |
221 if prop.optional: | 229 if prop.optional: |
222 (c.Sblock( | 230 (c.Sblock( |
223 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') | 231 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') |
224 .Concat(self._GeneratePopulatePropertyFromValue( | 232 .Concat(self._GeneratePopulatePropertyFromValue( |
225 prop, value_var, dst, 'false'))) | 233 prop, value_var, dst, 'false'))) |
226 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 234 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 235 if underlying_type.property_type == PropertyType.ENUM: |
227 (c.Append('} else {') | 236 (c.Append('} else {') |
228 .Append('%%(dst)s->%%(name)s = %s;' % | 237 .Append('%%(dst)s->%%(name)s = %s;' % |
229 self._cpp_type_generator.GetEnumNoneValue(prop))) | 238 self._type_helper.GetEnumNoneValue(prop.type_))) |
230 c.Eblock('}') | 239 c.Eblock('}') |
231 else: | 240 else: |
232 (c.Append( | 241 (c.Append( |
233 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') | 242 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') |
234 .Append(' return false;') | 243 .Append(' return false;') |
235 .Concat(self._GeneratePopulatePropertyFromValue( | 244 .Concat(self._GeneratePopulatePropertyFromValue( |
236 prop, value_var, dst, 'false')) | 245 prop, value_var, dst, 'false')) |
237 ) | 246 ) |
238 c.Append() | 247 c.Append() |
239 c.Substitute({ | 248 c.Substitute({ |
240 'value_var': value_var, | 249 'value_var': value_var, |
241 'key': prop.name, | 250 'key': prop.name, |
242 'src': src, | 251 'src': src, |
243 'dst': dst, | 252 'dst': dst, |
244 'name': prop.unix_name | 253 'name': prop.unix_name |
245 }) | 254 }) |
246 return c | 255 return c |
247 | 256 |
248 def _GenerateTypeToValue(self, cpp_namespace, type_): | 257 def _GenerateTypeToValue(self, cpp_namespace, type_): |
249 """Generates a function that serializes the type into a | 258 """Generates a function that serializes the type into a base::Value. |
250 |base::DictionaryValue|. | 259 E.g. for type "Foo" generates Foo::ToValue() |
| 260 """ |
| 261 if type_.property_type == PropertyType.OBJECT: |
| 262 return self._GenerateObjectTypeToValue(cpp_namespace, type_) |
| 263 elif type_.property_type == PropertyType.CHOICES: |
| 264 return self._GenerateChoiceTypeToValue(cpp_namespace, type_) |
| 265 else: |
| 266 raise ValueError("Unsupported property type %s" % type_.type_) |
251 | 267 |
252 E.g. for type "Foo" generates Foo::ToValue() | 268 def _GenerateObjectTypeToValue(self, cpp_namespace, type_): |
| 269 """Generates a function that serializes an object-representing type |
| 270 into a base::DictionaryValue. |
253 """ | 271 """ |
254 c = Code() | 272 c = Code() |
255 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % | 273 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % |
256 cpp_namespace) | 274 cpp_namespace) |
257 .Append('scoped_ptr<base::DictionaryValue> value(' | 275 .Append('scoped_ptr<base::DictionaryValue> value(' |
258 'new base::DictionaryValue());') | 276 'new base::DictionaryValue());') |
259 .Append() | 277 .Append() |
260 ) | 278 ) |
| 279 |
261 for prop in type_.properties.values(): | 280 for prop in type_.properties.values(): |
262 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 281 if prop.optional: |
263 c.Append('value->MergeDictionary(&%s);' % prop.unix_name) | 282 # Optional enum values are generated with a NONE enum value. |
| 283 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 284 if underlying_type.property_type == PropertyType.ENUM: |
| 285 c.Sblock('if (%s != %s) {' % |
| 286 (prop.unix_name, |
| 287 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 288 else: |
| 289 c.Sblock('if (%s.get()) {' % prop.unix_name) |
| 290 |
| 291 # ANY is a base::Value which is abstract and cannot be a direct member, so |
| 292 # it will always be a pointer. |
| 293 is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY |
| 294 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( |
| 295 prop.name, |
| 296 self._CreateValueFromType(prop.type_, |
| 297 'this->%s' % prop.unix_name, |
| 298 is_ptr=is_ptr))) |
| 299 |
| 300 if prop.optional: |
| 301 c.Eblock('}'); |
| 302 |
| 303 if type_.additional_properties is not None: |
| 304 if type_.additional_properties.property_type == PropertyType.ANY: |
| 305 c.Append('value->MergeDictionary(&additional_properties);') |
264 else: | 306 else: |
265 if prop.optional: | 307 # Non-copyable types will be wrapped in a linked_ptr for inclusion in |
266 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 308 # maps, so we need to unwrap them. |
267 c.Sblock('if (%s != %s) {' % | 309 needs_unwrap = ( |
268 (prop.unix_name, | 310 not self._type_helper.IsCopyable(type_.additional_properties)) |
269 self._cpp_type_generator.GetEnumNoneValue(prop))) | 311 cpp_type = self._type_helper.GetCppType(type_.additional_properties, |
270 elif prop.type_ == PropertyType.CHOICES: | 312 is_in_container=True) |
271 c.Sblock('if (%s_type != %s) {' % | 313 (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' % |
272 (prop.unix_name, | 314 cpp_util.PadForGenerics(cpp_type)) |
273 self._cpp_type_generator.GetEnumNoneValue(prop))) | 315 .Append(' additional_properties.begin();') |
274 else: | 316 .Append(' it != additional_properties.end(); ++it) {') |
275 c.Sblock('if (%s.get()) {' % prop.unix_name) | 317 .Append('value->SetWithoutPathExpansion(it->first, %s);' % |
| 318 self._CreateValueFromType( |
| 319 type_.additional_properties, |
| 320 '%sit->second' % ('*' if needs_unwrap else ''))) |
| 321 .Eblock('}') |
| 322 ) |
276 | 323 |
277 if prop.type_ == prop.compiled_type: | 324 return (c.Append() |
278 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 325 .Append('return value.Pass();') |
279 prop.name, | 326 .Eblock('}')) |
280 self._CreateValueFromProperty(prop, 'this->' + prop.unix_name))) | 327 |
281 else: | 328 def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): |
282 conversion_src = 'this->' + prop.unix_name | 329 """Generates a function that serializes a choice-representing type |
283 if prop.optional: | 330 into a base::Value. |
284 conversion_src = '*' + conversion_src | 331 """ |
285 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop), | 332 c = Code() |
286 prop.unix_name)) | 333 c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) |
287 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | 334 c.Append('scoped_ptr<base::Value> result;'); |
288 self._cpp_type_generator.GetReferencedProperty(prop), | 335 for choice in type_.choices: |
289 conversion_src, | 336 choice_var = 'as_%s' % choice.unix_name |
290 prop.unix_name) + ';') | 337 (c.Sblock('if (%s) {' % choice_var) |
291 .Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 338 .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' % |
292 prop.unix_name, | 339 type_.unix_name) |
293 self._CreateValueFromProperty(prop, prop.unix_name))) | 340 .Append('result.reset(%s);' % |
294 ) | 341 self._CreateValueFromType(choice, '*%s' % choice_var)) |
295 if prop.optional: | 342 .Eblock('}') |
296 c.Eblock('}'); | 343 ) |
297 (c.Append() | 344 (c.Append('DCHECK(result) << "Must set at least one choice for %s";' % |
298 .Append('return value.Pass();') | 345 type_.unix_name) |
| 346 .Append('return result.Pass();') |
299 .Eblock('}') | 347 .Eblock('}') |
300 ) | 348 ) |
301 return c | 349 return c |
302 | 350 |
303 def _GenerateFunction(self, cpp_namespace, function): | 351 def _GenerateFunction(self, function): |
304 """Generates the definitions for function structs. | 352 """Generates the definitions for function structs. |
305 """ | 353 """ |
306 c = Code() | 354 c = Code() |
307 | 355 |
| 356 # TODO(kalman): use function.unix_name not Classname. |
| 357 function_namespace = cpp_util.Classname(function.name) |
| 358 (c.Append('namespace %s {' % function_namespace) |
| 359 .Append() |
| 360 ) |
| 361 |
308 # Params::Populate function | 362 # Params::Populate function |
309 if function.params: | 363 if function.params: |
310 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params', | 364 c.Concat(self._GeneratePropertyFunctions('Params', function.params)) |
311 function.params)) | 365 (c.Append('Params::Params() {}') |
312 (c.Append('%(cpp_namespace)s::Params::Params() {}') | 366 .Append('Params::~Params() {}') |
313 .Append('%(cpp_namespace)s::Params::~Params() {}') | |
314 .Append() | 367 .Append() |
315 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function)) | 368 .Cblock(self._GenerateFunctionParamsCreate(function)) |
316 .Append() | |
317 ) | 369 ) |
318 | 370 |
319 # Results::Create function | 371 # Results::Create function |
320 if function.callback: | 372 if function.callback: |
321 c.Concat(self._GenerateCreateCallbackArguments( | 373 c.Concat(self._GenerateCreateCallbackArguments('Results', |
322 "%s::Results" % cpp_namespace, function.callback)) | 374 function.callback)) |
323 | 375 |
324 c.Substitute({'cpp_namespace': cpp_namespace}) | 376 c.Append('} // namespace %s' % function_namespace) |
325 | |
326 return c | 377 return c |
327 | 378 |
328 def _CreateValueFromProperty(self, prop, var): | 379 def _GenerateEvent(self, event): |
329 """Creates a base::Value given a property. Generated code passes ownership | 380 # TODO(kalman): use event.unix_name not Classname. |
| 381 c = Code() |
| 382 event_namespace = cpp_util.Classname(event.name) |
| 383 (c.Append('namespace %s {' % event_namespace) |
| 384 .Append() |
| 385 .Cblock(self._GenerateCreateCallbackArguments(None, event)) |
| 386 .Append('} // namespace %s' % event_namespace) |
| 387 ) |
| 388 return c |
| 389 |
| 390 def _CreateValueFromType(self, type_, var, is_ptr=False): |
| 391 """Creates a base::Value given a type. Generated code passes ownership |
330 to caller. | 392 to caller. |
331 | 393 |
332 var: variable or variable* | 394 var: variable or variable* |
333 | 395 |
334 E.g for std::string, generate base::Value::CreateStringValue(var) | 396 E.g for std::string, generate base::Value::CreateStringValue(var) |
335 """ | 397 """ |
336 if prop.type_ == PropertyType.CHOICES: | 398 underlying_type = self._type_helper.FollowRef(type_) |
337 return 'Get%sChoiceValue().release()' % cpp_util.Classname(prop.name) | 399 if (underlying_type.property_type == PropertyType.CHOICES or |
338 elif self._IsObjectOrObjectRef(prop): | 400 underlying_type.property_type == PropertyType.OBJECT): |
339 if prop.optional: | 401 if is_ptr: |
340 return '%s->ToValue().release()' % var | 402 return '(%s)->ToValue().release()' % var |
341 else: | 403 else: |
342 return '%s.ToValue().release()' % var | 404 return '(%s).ToValue().release()' % var |
343 elif prop.type_ == PropertyType.ANY: | 405 elif (underlying_type.property_type == PropertyType.ANY or |
344 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var) | 406 underlying_type.property_type == PropertyType.FUNCTION): |
345 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 407 if is_ptr: |
346 return '%s.DeepCopy()' % var | 408 vardot = '(%s)->' % var |
347 elif prop.type_ == PropertyType.FUNCTION: | |
348 if prop.optional: | |
349 vardot = var + '->' | |
350 else: | 409 else: |
351 vardot = var + '.' | 410 vardot = '(%s).' % var |
352 return '%sDeepCopy()' % vardot | 411 return '%sDeepCopy()' % vardot |
353 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 412 elif underlying_type.property_type == PropertyType.ENUM: |
354 return 'base::Value::CreateStringValue(ToString(%s))' % var | 413 return 'base::Value::CreateStringValue(ToString(%s))' % var |
355 elif prop.type_ == PropertyType.BINARY: | 414 elif underlying_type.property_type == PropertyType.BINARY: |
356 if prop.optional: | 415 if is_ptr: |
357 vardot = var + '->' | 416 vardot = var + '->' |
358 else: | 417 else: |
359 vardot = var + '.' | 418 vardot = var + '.' |
360 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % | 419 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % |
361 (vardot, vardot)) | 420 (vardot, vardot)) |
362 elif self._IsArrayOrArrayRef(prop): | 421 elif underlying_type.property_type == PropertyType.ARRAY: |
363 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( | 422 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( |
364 self._cpp_type_generator.GetReferencedProperty(prop), var, | 423 underlying_type, |
365 prop.optional) | 424 var, |
366 elif self._IsFundamentalOrFundamentalRef(prop): | 425 is_ptr) |
367 # If prop.type != prop.compiled_type, then no asterisk is necessary | 426 elif underlying_type.property_type.is_fundamental: |
368 # because the target is a local variable and not a dereferenced scoped | 427 if is_ptr: |
369 # pointer. The asterisk is instead prepended to conversion_src around line | 428 var = '*%s' % var |
370 # 273. | 429 if underlying_type.property_type == PropertyType.STRING: |
371 if prop.optional and prop.type_ == prop.compiled_type: | 430 return 'new base::StringValue(%s)' % var |
372 var = '*' + var | 431 else: |
373 prop = self._cpp_type_generator.GetReferencedProperty(prop); | 432 return 'new base::FundamentalValue(%s)' % var |
374 return { | |
375 PropertyType.STRING: 'base::Value::CreateStringValue(%s)', | |
376 PropertyType.BOOLEAN: 'base::Value::CreateBooleanValue(%s)', | |
377 PropertyType.INTEGER: 'base::Value::CreateIntegerValue(%s)', | |
378 PropertyType.DOUBLE: 'base::Value::CreateDoubleValue(%s)', | |
379 }[prop.type_] % var | |
380 else: | 433 else: |
381 raise NotImplementedError('Conversion of %s to base::Value not ' | 434 raise NotImplementedError('Conversion of %s to base::Value not ' |
382 'implemented' % repr(prop.type_)) | 435 'implemented' % repr(type_.type_)) |
383 | 436 |
384 def _GenerateParamsCheck(self, function, var): | 437 def _GenerateParamsCheck(self, function, var): |
385 """Generates a check for the correct number of arguments when creating | 438 """Generates a check for the correct number of arguments when creating |
386 Params. | 439 Params. |
387 """ | 440 """ |
388 c = Code() | 441 c = Code() |
389 num_required = 0 | 442 num_required = 0 |
390 for param in function.params: | 443 for param in function.params: |
391 if not param.optional: | 444 if not param.optional: |
392 num_required += 1 | 445 num_required += 1 |
393 if num_required == len(function.params): | 446 if num_required == len(function.params): |
394 c.Append('if (%(var)s.GetSize() != %(total)d)') | 447 c.Append('if (%(var)s.GetSize() != %(total)d)') |
395 elif not num_required: | 448 elif not num_required: |
396 c.Append('if (%(var)s.GetSize() > %(total)d)') | 449 c.Append('if (%(var)s.GetSize() > %(total)d)') |
397 else: | 450 else: |
398 c.Append('if (%(var)s.GetSize() < %(required)d' | 451 c.Append('if (%(var)s.GetSize() < %(required)d' |
399 ' || %(var)s.GetSize() > %(total)d)') | 452 ' || %(var)s.GetSize() > %(total)d)') |
400 c.Append(' return scoped_ptr<Params>();') | 453 c.Append(' return scoped_ptr<Params>();') |
401 c.Substitute({ | 454 c.Substitute({ |
402 'var': var, | 455 'var': var, |
403 'required': num_required, | 456 'required': num_required, |
404 'total': len(function.params), | 457 'total': len(function.params), |
405 }) | 458 }) |
406 return c | 459 return c |
407 | 460 |
408 def _GenerateFunctionParamsCreate(self, cpp_namespace, function): | 461 def _GenerateFunctionParamsCreate(self, function): |
409 """Generate function to create an instance of Params. The generated | 462 """Generate function to create an instance of Params. The generated |
410 function takes a base::ListValue of arguments. | 463 function takes a base::ListValue of arguments. |
411 | 464 |
412 E.g for function "Bar", generate Bar::Params::Create() | 465 E.g for function "Bar", generate Bar::Params::Create() |
413 """ | 466 """ |
414 c = Code() | 467 c = Code() |
415 (c.Append('// static') | 468 (c.Append('// static') |
416 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' | 469 .Sblock('scoped_ptr<Params> ' |
417 '%(cpp_namespace)s::Params::Create(const base::ListValue& args) {') | 470 'Params::Create(const base::ListValue& args) {') |
418 .Concat(self._GenerateParamsCheck(function, 'args')) | 471 .Concat(self._GenerateParamsCheck(function, 'args')) |
419 .Append('scoped_ptr<Params> params(new Params());') | 472 .Append('scoped_ptr<Params> params(new Params());') |
420 ) | 473 ) |
421 c.Substitute({'cpp_namespace': cpp_namespace}) | |
422 | 474 |
423 for param in function.params: | 475 for param in function.params: |
424 c.Concat(self._InitializePropertyToDefault(param, 'params')) | 476 c.Concat(self._InitializePropertyToDefault(param, 'params')) |
425 | 477 |
426 for i, param in enumerate(function.params): | 478 for i, param in enumerate(function.params): |
427 # Any failure will cause this function to return. If any argument is | 479 # Any failure will cause this function to return. If any argument is |
428 # incorrect or missing, those following it are not processed. Note that | 480 # incorrect or missing, those following it are not processed. Note that |
429 # for optional arguments, we allow missing arguments and proceed because | 481 # for optional arguments, we allow missing arguments and proceed because |
430 # there may be other arguments following it. | 482 # there may be other arguments following it. |
431 failure_value = 'scoped_ptr<Params>()' | 483 failure_value = 'scoped_ptr<Params>()' |
432 c.Append() | 484 c.Append() |
433 value_var = param.unix_name + '_value' | 485 value_var = param.unix_name + '_value' |
434 (c.Append('const base::Value* %(value_var)s = NULL;') | 486 (c.Append('const base::Value* %(value_var)s = NULL;') |
435 .Append('if (args.Get(%(i)s, &%(value_var)s) &&\n' | 487 .Append('if (args.Get(%(i)s, &%(value_var)s) &&') |
436 ' !%(value_var)s->IsType(base::Value::TYPE_NULL))') | 488 .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {') |
437 .Sblock('{') | |
438 .Concat(self._GeneratePopulatePropertyFromValue( | 489 .Concat(self._GeneratePopulatePropertyFromValue( |
439 param, value_var, 'params', failure_value)) | 490 param, value_var, 'params', failure_value)) |
440 .Eblock('}') | 491 .Eblock('}') |
441 ) | 492 ) |
442 if not param.optional: | 493 if not param.optional: |
443 (c.Sblock('else {') | 494 (c.Sblock('else {') |
444 .Append('return %s;' % failure_value) | 495 .Append('return %s;' % failure_value) |
445 .Eblock('}') | 496 .Eblock('}') |
446 ) | 497 ) |
447 c.Substitute({'value_var': value_var, 'i': i}) | 498 c.Substitute({'value_var': value_var, 'i': i}) |
448 (c.Append() | 499 (c.Append() |
449 .Append('return params.Pass();') | 500 .Append('return params.Pass();') |
450 .Eblock('}') | 501 .Eblock('}') |
451 .Append() | 502 .Append() |
452 ) | 503 ) |
453 | 504 |
454 return c | 505 return c |
455 | 506 |
456 def _GeneratePopulatePropertyFromValue( | 507 def _GeneratePopulatePropertyFromValue(self, |
457 self, prop, value_var, dst, failure_value, check_type=True): | 508 prop, |
458 """Generates code to populate a model.Property given a base::Value*. The | 509 src_var, |
459 existence of data inside the base::Value* is assumed so checks for existence | 510 dst_class_var, |
460 should be performed before the code this generates. | 511 failure_value): |
461 | 512 """Generates code to populate property |prop| of |dst_class_var| (a |
462 prop: the property the code is populating. | 513 pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for |
463 value_var: a base::Value* that should represent |prop|. | 514 semantics. |
464 dst: the object with |prop| as a member. | 515 """ |
465 failure_value: the value to return if |prop| cannot be extracted from | 516 return self._GeneratePopulateVariableFromValue(prop.type_, |
466 |value_var| | 517 src_var, |
467 check_type: if true, will check if |value_var| is the correct | 518 '%s->%s' % (dst_class_var, |
468 base::Value::Type | 519 prop.unix_name), |
| 520 failure_value, |
| 521 is_ptr=prop.optional) |
| 522 |
| 523 def _GeneratePopulateVariableFromValue(self, |
| 524 type_, |
| 525 src_var, |
| 526 dst_var, |
| 527 failure_value, |
| 528 is_ptr=False): |
| 529 """Generates code to populate a variable |dst_var| of type |type_| from a |
| 530 Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated |
| 531 code, if |dst_var| fails to be populated then Populate will return |
| 532 |failure_value|. |
469 """ | 533 """ |
470 c = Code() | 534 c = Code() |
471 c.Sblock('{') | 535 c.Sblock('{') |
472 | 536 |
473 if self._IsFundamentalOrFundamentalRef(prop): | 537 underlying_type = self._type_helper.FollowRef(type_) |
474 self._GenerateFundamentalOrFundamentalRefPopulate(c, prop, value_var, dst) | 538 |
475 elif self._IsObjectOrObjectRef(prop): | 539 if underlying_type.property_type.is_fundamental: |
476 self._GenerateObjectOrObjectRefPopulate(c, prop) | 540 if is_ptr: |
477 elif prop.type_ == PropertyType.FUNCTION: | 541 (c.Append('%(cpp_type)s temp;') |
478 self._GenerateFunctionPopulate(c, prop) | 542 .Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
479 elif prop.type_ == PropertyType.ANY: | 543 self._type_helper.FollowRef(type_), src_var, '&temp')) |
480 self._GenerateAnyPopulate(c, prop, value_var, dst) | 544 .Append(' return %(failure_value)s;') |
481 elif self._IsArrayOrArrayRef(prop): | 545 .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));') |
482 self._GenerateArrayOrArrayRefPopulate(c, prop, dst) | 546 ) |
483 elif prop.type_ == PropertyType.CHOICES: | 547 else: |
484 self._GenerateChoicePopulate(c, prop, value_var, dst, failure_value) | 548 (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
485 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 549 self._type_helper.FollowRef(type_), |
486 self._GenerateEnumPopulate(c, prop, value_var) | 550 src_var, |
487 elif prop.type_ == PropertyType.BINARY: | 551 '&%s' % dst_var)) |
488 self._GenerateBinaryPopulate(c, prop) | 552 .Append(' return %(failure_value)s;') |
| 553 ) |
| 554 elif underlying_type.property_type == PropertyType.OBJECT: |
| 555 if is_ptr: |
| 556 (c.Append('const base::DictionaryValue* dictionary = NULL;') |
| 557 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') |
| 558 .Append(' return %(failure_value)s;') |
| 559 .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') |
| 560 .Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))') |
| 561 .Append(' return %(failure_value)s;') |
| 562 .Append('%(dst_var)s = temp.Pass();') |
| 563 ) |
| 564 else: |
| 565 (c.Append('const base::DictionaryValue* dictionary = NULL;') |
| 566 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') |
| 567 .Append(' return %(failure_value)s;') |
| 568 .Append('if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))') |
| 569 .Append(' return %(failure_value)s;') |
| 570 ) |
| 571 elif underlying_type.property_type == PropertyType.FUNCTION: |
| 572 if is_ptr: |
| 573 c.Append('%(dst_var)s.reset(new base::DictionaryValue());') |
| 574 elif underlying_type.property_type == PropertyType.ANY: |
| 575 c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());') |
| 576 elif underlying_type.property_type == PropertyType.ARRAY: |
| 577 # util_cc_helper deals with optional and required arrays |
| 578 (c.Append('const base::ListValue* list = NULL;') |
| 579 .Append('if (!%(src_var)s->GetAsList(&list))') |
| 580 .Append(' return %(failure_value)s;')) |
| 581 item_type = underlying_type.item_type |
| 582 if item_type.property_type == PropertyType.ENUM: |
| 583 c.Concat(self._GenerateListValueToEnumArrayConversion( |
| 584 item_type, |
| 585 'list', |
| 586 dst_var, |
| 587 failure_value, |
| 588 is_ptr=is_ptr)) |
| 589 else: |
| 590 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( |
| 591 underlying_type, |
| 592 'list', |
| 593 dst_var, |
| 594 is_ptr)) |
| 595 .Append(' return %(failure_value)s;') |
| 596 ) |
| 597 elif underlying_type.property_type == PropertyType.CHOICES: |
| 598 if is_ptr: |
| 599 (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') |
| 600 .Append('if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))') |
| 601 .Append(' return %(failure_value)s;') |
| 602 .Append('%(dst_var)s = temp.Pass();') |
| 603 ) |
| 604 else: |
| 605 (c.Append('if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))') |
| 606 .Append(' return %(failure_value)s;') |
| 607 ) |
| 608 elif underlying_type.property_type == PropertyType.ENUM: |
| 609 c.Concat(self._GenerateStringToEnumConversion(type_, |
| 610 src_var, |
| 611 dst_var, |
| 612 failure_value)) |
| 613 elif underlying_type.property_type == PropertyType.BINARY: |
| 614 (c.Append('if (!%(src_var)s->IsType(%(value_type)s))') |
| 615 .Append(' return %(failure_value)s;') |
| 616 .Append('const base::BinaryValue* binary_value =') |
| 617 .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);') |
| 618 ) |
| 619 if is_ptr: |
| 620 (c.Append('%(dst_var)s.reset(') |
| 621 .Append(' new std::string(binary_value->GetBuffer(),') |
| 622 .Append(' binary_value->GetSize()));') |
| 623 ) |
| 624 else: |
| 625 (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),') |
| 626 .Append(' binary_value->GetSize());') |
| 627 ) |
489 else: | 628 else: |
490 raise NotImplementedError(prop.type_) | 629 raise NotImplementedError(type_) |
491 c.Eblock('}') | 630 |
492 sub = { | 631 sub = { |
493 'value_var': value_var, | 632 'cpp_type': self._type_helper.GetCppType(type_), |
494 'name': prop.unix_name, | 633 'src_var': src_var, |
495 'dst': dst, | 634 'dst_var': dst_var, |
496 'failure_value': failure_value, | 635 'failure_value': failure_value, |
497 } | 636 } |
498 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY): | 637 |
499 sub['ctype'] = self._cpp_type_generator.GetType(prop) | 638 if underlying_type.property_type not in (PropertyType.ANY, |
500 sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop) | 639 PropertyType.CHOICES): |
501 sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator | 640 sub['value_type'] = cpp_util.GetValueType(underlying_type) |
502 .GetReferencedProperty(prop).type_) | 641 |
503 c.Substitute(sub) | 642 return c.Eblock('}').Substitute(sub) |
504 return c | 643 |
505 | 644 def _GenerateListValueToEnumArrayConversion(self, |
506 def _GenerateFundamentalOrFundamentalRefPopulate(self, | 645 item_type, |
507 c, | 646 src_var, |
508 prop, | 647 dst_var, |
509 value_var, | 648 failure_value, |
510 dst): | 649 is_ptr=False): |
511 if prop.optional: | 650 """Returns Code that converts a ListValue of string constants from |
512 (c.Append('%(ctype)s temp;') | 651 |src_var| into an array of enums of |type_| in |dst_var|. On failure, |
513 .Append('if (!%s)' % | 652 returns |failure_value|. |
514 cpp_util.GetAsFundamentalValue( | 653 """ |
515 self._cpp_type_generator.GetReferencedProperty(prop), | 654 c = Code() |
516 value_var, | 655 accessor = '.' |
517 '&temp')) | 656 if is_ptr: |
518 .Append(' return %(failure_value)s;') | 657 accessor = '->' |
519 ) | 658 cpp_type = self._type_helper.GetCppType(item_type, is_in_container=True) |
520 if prop.type_ != prop.compiled_type: | 659 c.Append('%s.reset(new std::vector<%s>);' % |
521 (c.Append('%(compiled_ctype)s temp2;') | 660 (dst_var, cpp_util.PadForGenerics(cpp_type))) |
522 .Append('if (!%s)' % | 661 (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); ' |
523 cpp_util.GenerateTypeToCompiledTypeConversion( | 662 'it != %s->end(); ++it) {' % (src_var, src_var)) |
524 self._cpp_type_generator.GetReferencedProperty(prop), | 663 .Append('%s tmp;' % self._type_helper.GetCppType(item_type)) |
525 'temp', | 664 .Concat(self._GenerateStringToEnumConversion(item_type, |
526 'temp2')) | 665 '(*it)', |
527 .Append(' return %(failure_value)s;') | 666 'tmp', |
528 .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));') | 667 failure_value)) |
529 ) | 668 .Append('%s%spush_back(tmp);' % (dst_var, accessor)) |
530 else: | |
531 c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));') | |
532 | |
533 else: | |
534 if prop.type_ == prop.compiled_type: | |
535 assignment_target = '&%s->%s' % (dst, prop.unix_name) | |
536 else: | |
537 c.Append('%(ctype)s temp;') | |
538 assignment_target = '&temp' | |
539 (c.Append('if (!%s)' % | |
540 cpp_util.GetAsFundamentalValue( | |
541 self._cpp_type_generator.GetReferencedProperty(prop), | |
542 value_var, | |
543 assignment_target)) | |
544 .Append(' return %(failure_value)s;') | |
545 ) | |
546 if prop.type_ != prop.compiled_type: | |
547 (c.Append('if (!%s)' % | |
548 cpp_util.GenerateTypeToCompiledTypeConversion( | |
549 self._cpp_type_generator.GetReferencedProperty(prop), | |
550 'temp', | |
551 '%s->%s' % (dst, prop.unix_name))) | |
552 .Append(' return %(failure_value)s;') | |
553 ) | |
554 | |
555 def _GenerateObjectOrObjectRefPopulate(self, c, prop): | |
556 if prop.optional: | |
557 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
558 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
559 .Append(' return %(failure_value)s;') | |
560 .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());') | |
561 .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))') | |
562 .Append(' return %(failure_value)s;') | |
563 .Append('%(dst)s->%(name)s = temp.Pass();') | |
564 ) | |
565 else: | |
566 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
567 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
568 .Append(' return %(failure_value)s;') | |
569 .Append( | |
570 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') | |
571 .Append(' return %(failure_value)s;') | |
572 ) | |
573 | |
574 def _GenerateFunctionPopulate(self, c, prop): | |
575 if prop.optional: | |
576 c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());') | |
577 | |
578 def _GenerateAnyPopulate(self, c, prop, value_var, dst): | |
579 if prop.optional: | |
580 c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());') | |
581 c.Append(self._any_helper.Init(prop, value_var, dst) + ';') | |
582 | |
583 def _GenerateArrayOrArrayRefPopulate(self, c, prop, dst): | |
584 # util_cc_helper deals with optional and required arrays | |
585 (c.Append('const base::ListValue* list = NULL;') | |
586 .Append('if (!%(value_var)s->GetAsList(&list))') | |
587 .Append(' return %(failure_value)s;')) | |
588 if prop.item_type.type_ == PropertyType.ENUM: | |
589 self._GenerateListValueToEnumArrayConversion(c, prop) | |
590 else: | |
591 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | |
592 self._cpp_type_generator.GetReferencedProperty(prop), 'list', | |
593 dst + '->' + prop.unix_name, prop.optional)) | |
594 .Append(' return %(failure_value)s;') | |
595 ) | |
596 | |
597 def _GenerateChoicePopulate(self, c, prop, value_var, dst, failure_value): | |
598 type_var = '%(dst)s->%(name)s_type' | |
599 c.Sblock('switch (%(value_var)s->GetType()) {') | |
600 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
601 (c.Sblock('case %s: {' % cpp_util.GetValueType( | |
602 self._cpp_type_generator.GetReferencedProperty(choice).type_)) | |
603 .Concat(self._GeneratePopulatePropertyFromValue( | |
604 choice, value_var, dst, failure_value, check_type=False)) | |
605 .Append('%s = %s;' % | |
606 (type_var, | |
607 self._cpp_type_generator.GetEnumValue( | |
608 prop, choice.type_.name))) | |
609 .Append('break;') | |
610 .Eblock('}') | 669 .Eblock('}') |
611 ) | 670 ) |
612 (c.Append('default:') | 671 return c |
613 .Append(' return %(failure_value)s;') | 672 |
614 ) | 673 def _GenerateStringToEnumConversion(self, |
615 c.Eblock('}') | 674 type_, |
616 | 675 src_var, |
617 def _GenerateEnumPopulate(self, c, prop, value_var): | 676 dst_var, |
618 c.Sblock('{') | 677 failure_value): |
619 self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp') | 678 """Returns Code that converts a string type in |src_var| to an enum with |
620 c.Append('%(dst)s->%(name)s = enum_temp;') | 679 type |type_| in |dst_var|. In the generated code, if |src_var| is not |
621 c.Eblock('}') | 680 a valid enum name then the function will return |failure_value|. |
622 | 681 """ |
623 def _GenerateBinaryPopulate(self, c, prop): | 682 c = Code() |
624 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') | 683 enum_as_string = '%s_as_string' % type_.unix_name |
625 .Append(' return %(failure_value)s;') | 684 (c.Append('std::string %s;' % enum_as_string) |
626 .Append('const base::BinaryValue* binary_value =') | 685 .Append('if (!%s->GetAsString(&%s))' % (src_var, enum_as_string)) |
627 .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);') | 686 .Append(' return %s;' % failure_value) |
628 ) | 687 .Append('%s = Parse%s(%s);' % (dst_var, |
629 if prop.optional: | 688 self._type_helper.GetCppType(type_), |
630 (c.Append('%(dst)s->%(name)s.reset(') | 689 enum_as_string)) |
631 .Append(' new std::string(binary_value->GetBuffer(),') | 690 .Append('if (%s == %s)' % (dst_var, |
632 .Append(' binary_value->GetSize()));') | 691 self._type_helper.GetEnumNoneValue(type_))) |
633 ) | 692 .Append(' return %s;' % failure_value) |
634 else: | 693 ) |
635 (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),') | 694 return c |
636 .Append(' binary_value->GetSize());') | 695 |
637 ) | 696 def _GeneratePropertyFunctions(self, namespace, params): |
638 | 697 """Generates the member functions for a list of parameters. |
639 def _GenerateListValueToEnumArrayConversion(self, c, prop): | 698 """ |
640 """Appends code that converts a ListValue of string contstants to | 699 return self._GenerateTypes(namespace, (param.type_ for param in params)) |
641 an array of enums in dst. | 700 |
642 Leaves dst, name, and failure_value unsubstituted. | 701 def _GenerateTypes(self, namespace, types): |
643 | 702 """Generates the member functions for a list of types. |
644 c: the Code object that is being appended to. | 703 """ |
645 prop: the property that the code is populating. | 704 c = Code() |
646 """ | 705 for type_ in types: |
647 accessor = '.' | 706 c.Cblock(self._GenerateType(namespace, type_)) |
648 if prop.optional: | 707 return c |
649 c.Append('%(dst)s->%(name)s.reset(new std::vector<' + ( | 708 |
650 self._cpp_type_generator.GetType(prop.item_type) + '>);')) | 709 def _GenerateEnumToString(self, cpp_namespace, type_): |
651 accessor = '->' | |
652 c.Sblock('for (ListValue::const_iterator it = list->begin(); ' | |
653 'it != list->end(); ++it) {') | |
654 self._GenerateStringToEnumConversion( | |
655 c, prop.item_type, '(*it)', 'enum_temp') | |
656 c.Append('%(dst)s->%(name)s' + accessor + 'push_back(enum_temp);') | |
657 c.Eblock('}') | |
658 | |
659 def _GenerateStringToEnumConversion(self, c, prop, value_var, enum_temp): | |
660 """Appends code that converts a string to an enum. | |
661 Leaves failure_value unsubstituted. | |
662 | |
663 c: the code that is appended to. | |
664 prop: the property that the code is populating. | |
665 value_var: the string value that is being converted. | |
666 enum_temp: the name used to store the temporary enum value. | |
667 """ | |
668 (c.Append('std::string enum_as_string;') | |
669 .Append('if (!%s->GetAsString(&enum_as_string))' % value_var) | |
670 .Append(' return %(failure_value)s;') | |
671 .Append('%(type)s %(enum)s = From%(type)sString(enum_as_string);' % { | |
672 'type': self._cpp_type_generator.GetCompiledType(prop), | |
673 'enum': enum_temp | |
674 }) | |
675 .Append('if (%s == %s)' % | |
676 (enum_temp, self._cpp_type_generator.GetEnumNoneValue(prop))) | |
677 .Append(' return %(failure_value)s;')) | |
678 | |
679 def _GeneratePropertyFunctions(self, param_namespace, params): | |
680 """Generate the functions for structures generated by a property such as | |
681 CreateEnumValue for ENUMs and Populate/ToValue for Params/Results objects. | |
682 """ | |
683 c = Code() | |
684 for param in params: | |
685 if param.type_ == PropertyType.OBJECT: | |
686 c.Concat(self._GenerateType( | |
687 param_namespace + '::' + cpp_util.Classname(param.name), | |
688 param)) | |
689 c.Append() | |
690 elif param.type_ == PropertyType.ARRAY: | |
691 c.Concat(self._GeneratePropertyFunctions( | |
692 param_namespace, [param.item_type])) | |
693 elif param.type_ == PropertyType.CHOICES: | |
694 c.Concat(self._GeneratePropertyFunctions( | |
695 param_namespace, param.choices.values())) | |
696 if param.from_client: | |
697 c.Concat(self._GenerateGetChoiceValue(param_namespace, param)) | |
698 elif param.type_ == PropertyType.ENUM: | |
699 (c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) | |
700 .Append() | |
701 .Concat(self._GenerateEnumFromString(param_namespace, | |
702 param, | |
703 use_namespace=True)) | |
704 .Append() | |
705 .Concat(self._GenerateEnumToString(param_namespace, | |
706 param, | |
707 use_namespace=True)) | |
708 .Append()) | |
709 return c | |
710 | |
711 def _GenerateGetChoiceValue(self, cpp_namespace, prop): | |
712 """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value> | |
713 representing the choice value. | |
714 """ | |
715 c = Code() | |
716 (c.Sblock('scoped_ptr<base::Value> ' | |
717 '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {') | |
718 .Sblock('switch (%s_type) {' % prop.unix_name) | |
719 .Concat(self._GenerateReturnCase( | |
720 self._cpp_type_generator.GetEnumNoneValue(prop), | |
721 'scoped_ptr<base::Value>()'))) | |
722 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
723 c.Concat(self._GenerateReturnCase( | |
724 self._cpp_type_generator.GetEnumValue(prop, choice.type_.name), | |
725 'make_scoped_ptr<base::Value>(%s)' % | |
726 self._CreateValueFromProperty(choice, choice.unix_name))) | |
727 (c.Eblock('}') | |
728 .Append('return scoped_ptr<base::Value>();') | |
729 .Eblock('}') | |
730 .Append() | |
731 .Substitute({ | |
732 'cpp_namespace': cpp_namespace, | |
733 'choice': cpp_util.Classname(prop.name) | |
734 }) | |
735 ) | |
736 return c | |
737 | |
738 def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop): | |
739 """Generates CreateEnumValue() that returns the base::StringValue | |
740 representation of an enum type. | |
741 """ | |
742 c = Code() | |
743 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | |
744 (c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' % | |
745 (classname, classname.lower())) | |
746 .Append('std::string enum_temp = ToString(%s);' % classname.lower()) | |
747 .Append('if (enum_temp.empty())') | |
748 .Append(' return scoped_ptr<base::Value>();') | |
749 .Append('return scoped_ptr<base::Value>(' | |
750 'base::Value::CreateStringValue(enum_temp));') | |
751 .Eblock('}')) | |
752 return c | |
753 | |
754 def _GenerateEnumToString(self, cpp_namespace, prop, use_namespace=False): | |
755 """Generates ToString() which gets the string representation of an enum. | 710 """Generates ToString() which gets the string representation of an enum. |
756 """ | 711 """ |
757 c = Code() | 712 c = Code() |
758 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 713 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
759 if use_namespace: | 714 |
760 namespace = '%s::' % cpp_namespace | 715 if cpp_namespace is not None: |
761 else: | 716 c.Append('// static') |
762 namespace = '' | 717 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
763 | 718 |
764 (c.Append('// static') | 719 c.Sblock('std::string %sToString(%s enum_param) {' % |
765 .Sblock('std::string %(namespace)sToString(%(class)s enum_param) {')) | 720 (maybe_namespace, classname)) |
766 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
767 c.Sblock('switch (enum_param) {') | 721 c.Sblock('switch (enum_param) {') |
768 for enum_value in enum_prop.enum_values: | 722 for enum_value in self._type_helper.FollowRef(type_).enum_values: |
769 c.Concat(self._GenerateReturnCase( | 723 (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value)) |
770 self._cpp_type_generator.GetEnumValue(prop, enum_value), | 724 .Append(' return "%s";' % enum_value)) |
771 '"%s"' % enum_value)) | 725 (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_)) |
772 (c.Append('case %s:' % self._cpp_type_generator.GetEnumNoneValue(prop)) | |
773 .Append(' return "";') | 726 .Append(' return "";') |
774 .Eblock('}') | 727 .Eblock('}') |
| 728 .Append('NOTREACHED();') |
775 .Append('return "";') | 729 .Append('return "";') |
776 .Eblock('}') | 730 .Eblock('}') |
777 .Substitute({ | 731 ) |
778 'namespace': namespace, | 732 return c |
779 'class': classname | 733 |
780 })) | 734 def _GenerateEnumFromString(self, cpp_namespace, type_): |
781 return c | |
782 | |
783 def _GenerateEnumFromString(self, cpp_namespace, prop, use_namespace=False): | |
784 """Generates FromClassNameString() which gets an enum from its string | 735 """Generates FromClassNameString() which gets an enum from its string |
785 representation. | 736 representation. |
786 """ | 737 """ |
787 c = Code() | 738 c = Code() |
788 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 739 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
789 if use_namespace: | 740 |
790 namespace = '%s::' % cpp_namespace | 741 if cpp_namespace is not None: |
791 else: | 742 c.Append('// static') |
792 namespace = '' | 743 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
793 | 744 |
794 (c.Append('// static') | 745 c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' % |
795 .Sblock('%(namespace)s%(class)s' | 746 (maybe_namespace, classname, maybe_namespace, classname)) |
796 ' %(namespace)sFrom%(class)sString(' | |
797 'const std::string& enum_string) {')) | |
798 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
799 for i, enum_value in enumerate( | 747 for i, enum_value in enumerate( |
800 self._cpp_type_generator.GetReferencedProperty(prop).enum_values): | 748 self._type_helper.FollowRef(type_).enum_values): |
801 # This is broken up into all ifs with no else ifs because we get | 749 # This is broken up into all ifs with no else ifs because we get |
802 # "fatal error C1061: compiler limit : blocks nested too deeply" | 750 # "fatal error C1061: compiler limit : blocks nested too deeply" |
803 # on Windows. | 751 # on Windows. |
804 (c.Append('if (enum_string == "%s")' % enum_value) | 752 (c.Append('if (enum_string == "%s")' % enum_value) |
805 .Append(' return %s;' % | 753 .Append(' return %s;' % |
806 self._cpp_type_generator.GetEnumValue(prop, enum_value))) | 754 self._type_helper.GetEnumValue(type_, enum_value))) |
807 (c.Append('return %s;' % | 755 (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_)) |
808 self._cpp_type_generator.GetEnumNoneValue(prop)) | |
809 .Eblock('}') | 756 .Eblock('}') |
810 .Substitute({ | 757 ) |
811 'namespace': namespace, | 758 return c |
812 'class': classname | 759 |
813 })) | 760 def _GenerateCreateCallbackArguments(self, function_scope, callback): |
814 return c | |
815 | |
816 # TODO(chebert): This is basically the same as GenerateCreateEnumTypeValue(). | |
817 # The plan is to phase out the old-style enums, and make all enums into REF | |
818 # types. | |
819 def _GenerateCreateEnumValue(self, cpp_namespace, prop): | |
820 """Generates CreateEnumValue() that returns the base::StringValue | |
821 representation of an enum. | |
822 """ | |
823 c = Code() | |
824 (c.Append('// static') | |
825 .Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' | |
826 '%(arg)s) {') | |
827 .Append('std::string enum_temp = ToString(%s);' % prop.unix_name) | |
828 .Append('if (enum_temp.empty())') | |
829 .Append(' return scoped_ptr<base::Value>();') | |
830 .Append('return scoped_ptr<base::Value>(' | |
831 'base::Value::CreateStringValue(enum_temp));') | |
832 .Eblock('}') | |
833 .Substitute({ | |
834 'cpp_namespace': cpp_namespace, | |
835 'arg': cpp_util.GetParameterDeclaration( | |
836 prop, self._cpp_type_generator.GetType(prop)) | |
837 })) | |
838 return c | |
839 | |
840 def _GenerateReturnCase(self, case_value, return_value): | |
841 """Generates a single return case for a switch block. | |
842 """ | |
843 c = Code() | |
844 (c.Append('case %s:' % case_value) | |
845 .Append(' return %s;' % return_value) | |
846 ) | |
847 return c | |
848 | |
849 def _GenerateCreateCallbackArguments(self, | |
850 function_scope, | |
851 callback, | |
852 generate_to_json=False): | |
853 """Generate all functions to create Value parameters for a callback. | 761 """Generate all functions to create Value parameters for a callback. |
854 | 762 |
855 E.g for function "Bar", generate Bar::Results::Create | 763 E.g for function "Bar", generate Bar::Results::Create |
856 E.g for event "Baz", generate Baz::Create | 764 E.g for event "Baz", generate Baz::Create |
857 | 765 |
858 function_scope: the function scope path, e.g. Foo::Bar for the function | 766 function_scope: the function scope path, e.g. Foo::Bar for the function |
859 Foo::Bar::Baz(). | 767 Foo::Bar::Baz(). May be None if there is no function scope. |
860 callback: the Function object we are creating callback arguments for. | 768 callback: the Function object we are creating callback arguments for. |
861 generate_to_json: Generate a ToJson method. | |
862 """ | 769 """ |
863 c = Code() | 770 c = Code() |
864 params = callback.params | 771 params = callback.params |
865 expanded_params = self._cpp_type_generator.ExpandParams(params) | 772 c.Concat(self._GeneratePropertyFunctions(function_scope, params)) |
866 c.Concat(self._GeneratePropertyFunctions(function_scope, expanded_params)) | 773 |
867 | 774 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' |
868 param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params) | 775 'Create(%(declaration_list)s) {') |
869 for param_list in param_lists: | 776 .Append('scoped_ptr<base::ListValue> create_results(' |
870 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::' | 777 'new base::ListValue());') |
871 'Create(%(declaration_list)s) {') | 778 ) |
872 .Append('scoped_ptr<base::ListValue> create_results(' | 779 declaration_list = [] |
873 'new base::ListValue());') | 780 for param in params: |
874 ) | 781 declaration_list.append(cpp_util.GetParameterDeclaration( |
875 declaration_list = [] | 782 param, self._type_helper.GetCppType(param.type_))) |
876 for param in param_list: | 783 c.Append('create_results->Append(%s);' % |
877 # We treat this argument as 'required' to avoid wrapping it in a | 784 self._CreateValueFromType(param.type_, param.unix_name)) |
878 # scoped_ptr if it's optional. | 785 c.Append('return create_results.Pass();') |
879 param_copy = param.Copy() | 786 c.Eblock('}') |
880 param_copy.optional = False | 787 c.Substitute({ |
881 declaration_list.append("const %s" % cpp_util.GetParameterDeclaration( | 788 'function_scope': ('%s::' % function_scope) if function_scope else '', |
882 param_copy, self._cpp_type_generator.GetCompiledType(param_copy))) | 789 'declaration_list': ', '.join(declaration_list), |
883 param_name = param_copy.unix_name | 790 'param_names': ', '.join(param.unix_name for param in params) |
884 if param_copy.type_ != param_copy.compiled_type: | 791 }) |
885 param_name = 'temp_' + param_name | |
886 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(param_copy), | |
887 param_name)) | |
888 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | |
889 param_copy, | |
890 param_copy.unix_name, | |
891 param_name) + ';') | |
892 ) | |
893 c.Append('create_results->Append(%s);' % | |
894 self._CreateValueFromProperty(param_copy, param_name)) | |
895 | |
896 c.Append('return create_results.Pass();') | |
897 c.Eblock('}') | |
898 if generate_to_json: | |
899 c.Append() | |
900 (c.Sblock('std::string %(function_scope)s::' | |
901 'ToJson(%(declaration_list)s) {') | |
902 .Append('scoped_ptr<base::ListValue> create_results = ' | |
903 '%(function_scope)s::Create(%(param_list)s);') | |
904 .Append('std::string json;') | |
905 .Append('base::JSONWriter::Write(create_results.get(), &json);') | |
906 .Append('return json;') | |
907 ) | |
908 c.Eblock('}') | |
909 | |
910 c.Substitute({ | |
911 'function_scope': function_scope, | |
912 'declaration_list': ', '.join(declaration_list), | |
913 'param_list': ', '.join(param.unix_name for param in param_list) | |
914 }) | |
915 | |
916 return c | 792 return c |
917 | 793 |
918 def _InitializePropertyToDefault(self, prop, dst): | 794 def _InitializePropertyToDefault(self, prop, dst): |
919 """Initialize a model.Property to its default value inside an object. | 795 """Initialize a model.Property to its default value inside an object. |
920 | 796 |
921 E.g for optional enum "state", generate dst->state = STATE_NONE; | 797 E.g for optional enum "state", generate dst->state = STATE_NONE; |
922 | 798 |
923 dst: Type* | 799 dst: Type* |
924 """ | 800 """ |
925 c = Code() | 801 c = Code() |
926 if (self._cpp_type_generator.IsEnumOrEnumRef(prop) or | 802 underlying_type = self._type_helper.FollowRef(prop.type_) |
927 prop.type_ == PropertyType.CHOICES): | 803 if (underlying_type.property_type == PropertyType.ENUM and |
928 if prop.optional: | 804 prop.optional): |
929 prop_name = prop.unix_name | 805 c.Append('%s->%s = %s;' % ( |
930 if prop.type_ == PropertyType.CHOICES: | 806 dst, |
931 prop_name = prop.unix_name + '_type' | 807 prop.unix_name, |
932 c.Append('%s->%s = %s;' % ( | 808 self._type_helper.GetEnumNoneValue(prop.type_))) |
933 dst, | |
934 prop_name, | |
935 self._cpp_type_generator.GetEnumNoneValue(prop))) | |
936 return c | 809 return c |
937 | |
938 def _IsObjectOrObjectRef(self, prop): | |
939 """Determines if this property is an Object or is a ref to an Object. | |
940 """ | |
941 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
942 PropertyType.OBJECT) | |
943 | |
944 def _IsArrayOrArrayRef(self, prop): | |
945 """Determines if this property is an Array or is a ref to an Array. | |
946 """ | |
947 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
948 PropertyType.ARRAY) | |
949 | |
950 def _IsFundamentalOrFundamentalRef(self, prop): | |
951 """Determines if this property is a Fundamental type or is a ref to a | |
952 Fundamental type. | |
953 """ | |
954 return (self._cpp_type_generator.GetReferencedProperty(prop).type_. | |
955 is_fundamental) | |
OLD | NEW |