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 model import PropertyType | 5 from model import PropertyType |
| 6 import any_helper |
6 import code | 7 import code |
7 import cpp_util | 8 import cpp_util |
| 9 import model |
8 import util_cc_helper | 10 import util_cc_helper |
9 | 11 |
10 class CCGenerator(object): | 12 class CCGenerator(object): |
11 """A .cc generator for a namespace. | 13 """A .cc generator for a namespace. |
12 """ | 14 """ |
13 def __init__(self, namespace, cpp_type_generator): | 15 def __init__(self, namespace, cpp_type_generator): |
14 self._cpp_type_generator = cpp_type_generator | 16 self._cpp_type_generator = cpp_type_generator |
15 self._namespace = namespace | 17 self._namespace = namespace |
16 self._target_namespace = ( | 18 self._target_namespace = ( |
17 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 19 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) |
18 self._util_cc_helper = ( | 20 self._util_cc_helper = ( |
19 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | 21 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) |
| 22 self._any_helper = any_helper.AnyHelper() |
20 | 23 |
21 def Generate(self): | 24 def Generate(self): |
22 """Generates a code.Code object with the .cc for a single namespace. | 25 """Generates a code.Code object with the .cc for a single namespace. |
23 """ | 26 """ |
24 c = code.Code() | 27 c = code.Code() |
25 (c.Append(cpp_util.CHROMIUM_LICENSE) | 28 (c.Append(cpp_util.CHROMIUM_LICENSE) |
26 .Append() | 29 .Append() |
27 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 30 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
28 .Append() | 31 .Append() |
29 .Append(self._util_cc_helper.GetIncludePath()) | 32 .Append(self._util_cc_helper.GetIncludePath()) |
30 .Append('#include "%s/%s.h"' % | 33 .Append('#include "%s/%s.h"' % |
31 (self._namespace.source_file_dir, self._namespace.name)) | 34 (self._namespace.source_file_dir, self._namespace.name)) |
32 ) | 35 ) |
33 includes = self._cpp_type_generator.GenerateIncludes() | 36 includes = self._cpp_type_generator.GenerateIncludes() |
34 if not includes.IsEmpty(): | 37 if not includes.IsEmpty(): |
35 (c.Concat(includes) | 38 (c.Concat(includes) |
36 .Append() | 39 .Append() |
37 ) | 40 ) |
38 | 41 |
39 (c.Append() | 42 (c.Append() |
40 .Append('using base::Value;') | 43 .Append('using base::Value;') |
41 .Append('using base::DictionaryValue;') | 44 .Append('using base::DictionaryValue;') |
42 .Append('using base::ListValue;') | 45 .Append('using base::ListValue;') |
| 46 .Append('using %s;' % any_helper.ANY_CLASS) |
43 .Append() | 47 .Append() |
44 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) | 48 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) |
45 .Concat(self._cpp_type_generator.GetNamespaceStart()) | 49 .Concat(self._cpp_type_generator.GetNamespaceStart()) |
46 .Append() | 50 .Append() |
47 ) | 51 ) |
48 if self._namespace.types: | 52 if self._namespace.types: |
49 (c.Append('//') | 53 (c.Append('//') |
50 .Append('// Types') | 54 .Append('// Types') |
51 .Append('//') | 55 .Append('//') |
52 .Append() | 56 .Append() |
53 ) | 57 ) |
54 for type_ in self._namespace.types.values(): | 58 for type_ in self._namespace.types.values(): |
55 (c.Concat(self._GenerateType(type_.name, type_)) | 59 (c.Concat(self._GenerateType(type_.name, type_)) |
56 .Append() | 60 .Append() |
57 ) | 61 ) |
58 if self._namespace.functions: | 62 if self._namespace.functions: |
59 (c.Append('//') | 63 (c.Append('//') |
60 .Append('// Functions') | 64 .Append('// Functions') |
61 .Append('//') | 65 .Append('//') |
62 .Append() | 66 .Append() |
63 ) | 67 ) |
64 for function in self._namespace.functions.values(): | 68 for function in self._namespace.functions.values(): |
65 (c.Concat(self._GenerateFunction(function)) | 69 (c.Concat(self._GenerateFunction( |
| 70 cpp_util.Classname(function.name), function)) |
66 .Append() | 71 .Append() |
67 ) | 72 ) |
68 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) | 73 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) |
69 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | 74 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) |
70 .Append() | 75 .Append() |
71 ) | 76 ) |
72 # TODO(calamity): Events | 77 # TODO(calamity): Events |
73 return c | 78 return c |
74 | 79 |
75 def _GenerateType(self, cpp_namespace, type_): | 80 def _GenerateType(self, cpp_namespace, type_): |
76 """Generates the function definitions for a type. | 81 """Generates the function definitions for a type. |
77 """ | 82 """ |
78 classname = cpp_util.Classname(type_.name) | 83 classname = cpp_util.Classname(type_.name) |
79 c = code.Code() | 84 c = code.Code() |
80 | 85 |
81 (c.Concat(self._GeneratePropertyFunctions( | 86 if type_.functions: |
82 cpp_namespace, type_.properties.values())) | 87 # Types with functions are not instantiable in C++ because they are |
83 .Append('%(namespace)s::%(classname)s() {}') | 88 # handled in pure Javascript and hence have no properties or |
84 .Append('%(namespace)s::~%(classname)s() {}') | 89 # additionalProperties. |
85 .Append() | 90 if type_.properties: |
86 ) | 91 raise NotImplementedError('\n'.join(model.GetModelHierarchy(type_)) + |
87 if type_.from_json: | 92 '\nCannot generate both functions and properties on a type') |
88 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | 93 for function in type_.functions.values(): |
| 94 (c.Concat( |
| 95 self._GenerateFunction( |
| 96 cpp_namespace + '::' + cpp_util.Classname(function.name), |
| 97 function)) |
| 98 .Append() |
| 99 ) |
| 100 else: |
| 101 (c.Concat(self._GeneratePropertyFunctions( |
| 102 cpp_namespace, type_.properties.values())) |
| 103 .Append('%(namespace)s::%(classname)s() {}') |
| 104 .Append('%(namespace)s::~%(classname)s() {}') |
89 .Append() | 105 .Append() |
90 ) | 106 ) |
91 if type_.from_client: | 107 if type_.from_json: |
92 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | 108 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) |
93 c.Append() | 109 .Append() |
| 110 ) |
| 111 if type_.from_client: |
| 112 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) |
| 113 .Append() |
| 114 ) |
94 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) | 115 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) |
95 | 116 |
96 return c | 117 return c |
97 | 118 |
98 def _GenerateTypePopulate(self, cpp_namespace, type_): | 119 def _GenerateTypePopulate(self, cpp_namespace, type_): |
99 """Generates the function for populating a type given a pointer to it. | 120 """Generates the function for populating a type given a pointer to it. |
| 121 |
| 122 E.g for type "Foo", generates Foo::Populate() |
100 """ | 123 """ |
101 classname = cpp_util.Classname(type_.name) | 124 classname = cpp_util.Classname(type_.name) |
102 c = code.Code() | 125 c = code.Code() |
103 (c.Append('// static') | 126 (c.Append('// static') |
104 .Sblock('bool %(namespace)s::Populate' | 127 .Sblock('bool %(namespace)s::Populate' |
105 '(const Value& value, %(name)s* out) {') | 128 '(const Value& value, %(name)s* out) {') |
106 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') | 129 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') |
107 .Append(' return false;') | 130 .Append(' return false;') |
108 .Append('const DictionaryValue* dict = ' | 131 .Append('const DictionaryValue* dict = ' |
109 'static_cast<const DictionaryValue*>(&value);') | 132 'static_cast<const DictionaryValue*>(&value);') |
110 .Append() | 133 .Append() |
111 ) | 134 ) |
112 for prop in type_.properties.values(): | 135 for prop in type_.properties.values(): |
113 c.Concat(self._InitializePropertyToDefault(prop, 'out')) | 136 c.Concat(self._InitializePropertyToDefault(prop, 'out')) |
114 for prop in type_.properties.values(): | 137 for prop in type_.properties.values(): |
115 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | 138 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: |
| 139 c.Append('out->additional_properties.MergeDictionary(dict);') |
| 140 # remove all keys that are actual properties |
| 141 for cur_prop in type_.properties.values(): |
| 142 if prop != cur_prop: |
| 143 c.Append('out->additional_properties' |
| 144 '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name) |
| 145 c.Append() |
| 146 else: |
| 147 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
116 (c.Append('return true;') | 148 (c.Append('return true;') |
117 .Eblock('}') | 149 .Eblock('}') |
118 ) | 150 ) |
119 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | 151 c.Substitute({'namespace': cpp_namespace, 'name': classname}) |
120 return c | 152 return c |
121 | 153 |
122 def _GenerateTypePopulateProperty(self, prop, src, dst): | 154 def _GenerateTypePopulateProperty(self, prop, src, dst): |
123 """Generate the code to populate a single property in a type. | 155 """Generate the code to populate a single property in a type. |
124 | 156 |
125 src: DictionaryValue* | 157 src: DictionaryValue* |
(...skipping 16 matching lines...) Expand all Loading... |
142 .Append(' return false;') | 174 .Append(' return false;') |
143 .Concat(self._GeneratePopulatePropertyFromValue( | 175 .Concat(self._GeneratePopulatePropertyFromValue( |
144 prop, value_var, dst, 'false')) | 176 prop, value_var, dst, 'false')) |
145 ) | 177 ) |
146 c.Append() | 178 c.Append() |
147 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) | 179 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) |
148 return c | 180 return c |
149 | 181 |
150 def _GenerateTypeToValue(self, cpp_namespace, type_): | 182 def _GenerateTypeToValue(self, cpp_namespace, type_): |
151 """Generates a function that serializes the type into a |DictionaryValue|. | 183 """Generates a function that serializes the type into a |DictionaryValue|. |
| 184 |
| 185 E.g. for type "Foo" generates Foo::ToValue() |
152 """ | 186 """ |
153 c = code.Code() | 187 c = code.Code() |
154 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % | 188 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % |
155 cpp_namespace) | 189 cpp_namespace) |
156 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') | 190 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') |
157 .Append() | 191 .Append() |
158 ) | 192 ) |
159 for prop in type_.properties.values(): | 193 for prop in type_.properties.values(): |
160 if prop.optional: | 194 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: |
161 if prop.type_ == PropertyType.ENUM: | 195 c.Append('value->MergeDictionary(&%s);' % prop.unix_name) |
162 c.Sblock('if (%s != %s)' % | 196 else: |
163 (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) | 197 if prop.optional: |
164 else: | 198 if prop.type_ == PropertyType.ENUM: |
165 c.Sblock('if (%s.get())' % prop.unix_name) | 199 c.Sblock('if (%s != %s)' % |
166 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 200 (prop.unix_name, |
167 prop.name, | 201 self._cpp_type_generator.GetEnumNoneValue(prop))) |
168 self._CreateValueFromProperty(prop, prop.unix_name))) | 202 else: |
169 if prop.optional: | 203 c.Sblock('if (%s.get())' % prop.unix_name) |
170 c.Eblock(); | 204 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( |
| 205 prop.name, |
| 206 self._CreateValueFromProperty(prop, prop.unix_name))) |
| 207 if prop.optional: |
| 208 c.Eblock(); |
171 (c.Append() | 209 (c.Append() |
172 .Append('return value.Pass();') | 210 .Append('return value.Pass();') |
173 .Eblock('}') | 211 .Eblock('}') |
174 ) | 212 ) |
175 return c | 213 return c |
176 | 214 |
177 def _GenerateFunction(self, function): | 215 def _GenerateFunction(self, cpp_namespace, function): |
178 """Generates the definitions for function structs. | 216 """Generates the definitions for function structs. |
179 """ | 217 """ |
180 classname = cpp_util.Classname(function.name) | |
181 c = code.Code() | 218 c = code.Code() |
182 | 219 |
183 # Params::Populate function | 220 # Params::Populate function |
184 if function.params: | 221 if function.params: |
185 c.Concat(self._GeneratePropertyFunctions(classname + '::Params', | 222 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params', |
186 function.params)) | 223 function.params)) |
187 (c.Append('%(name)s::Params::Params() {}') | 224 (c.Append('%(cpp_namespace)s::Params::Params() {}') |
188 .Append('%(name)s::Params::~Params() {}') | 225 .Append('%(cpp_namespace)s::Params::~Params() {}') |
189 .Append() | 226 .Append() |
190 .Concat(self._GenerateFunctionParamsCreate(function)) | 227 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function)) |
191 .Append() | 228 .Append() |
192 ) | 229 ) |
193 | 230 |
194 # Result::Create function | 231 # Result::Create function |
195 if function.callback: | 232 if function.callback: |
196 c.Concat(self._GenerateFunctionResultCreate(function)) | 233 c.Concat(self._GenerateFunctionResultCreate(cpp_namespace, function)) |
197 | 234 |
198 c.Substitute({'name': classname}) | 235 c.Substitute({'cpp_namespace': cpp_namespace}) |
199 | 236 |
200 return c | 237 return c |
201 | 238 |
202 def _GenerateCreateEnumValue(self, cpp_namespace, prop): | 239 def _GenerateCreateEnumValue(self, cpp_namespace, prop): |
203 """Generates a function that returns the |StringValue| representation of an | 240 """Generates CreateEnumValue() that returns the |StringValue| |
204 enum. | 241 representation of an enum. |
205 """ | 242 """ |
206 c = code.Code() | 243 c = code.Code() |
207 c.Append('// static') | 244 c.Append('// static') |
208 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') | 245 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') |
209 c.Sblock('switch (%s) {' % prop.unix_name) | 246 c.Sblock('switch (%s) {' % prop.unix_name) |
210 if prop.optional: | 247 if prop.optional: |
211 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) | 248 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) |
212 .Append(' return scoped_ptr<Value>();') | 249 .Append(' return scoped_ptr<Value>();') |
213 .Append('}') | 250 .Append('}') |
214 ) | 251 ) |
(...skipping 11 matching lines...) Expand all Loading... |
226 c.Eblock('}') | 263 c.Eblock('}') |
227 c.Eblock('}') | 264 c.Eblock('}') |
228 c.Substitute({ | 265 c.Substitute({ |
229 'cpp_namespace': cpp_namespace, | 266 'cpp_namespace': cpp_namespace, |
230 'arg': cpp_util.GetParameterDeclaration( | 267 'arg': cpp_util.GetParameterDeclaration( |
231 prop, self._cpp_type_generator.GetType(prop)) | 268 prop, self._cpp_type_generator.GetType(prop)) |
232 }) | 269 }) |
233 return c | 270 return c |
234 | 271 |
235 def _CreateValueFromProperty(self, prop, var): | 272 def _CreateValueFromProperty(self, prop, var): |
236 """Creates a Value given a single property. Generated code passes ownership | 273 """Creates a Value given a property. Generated code passes ownership |
237 to caller. | 274 to caller. |
238 | 275 |
239 var: variable or variable* | 276 var: variable or variable* |
| 277 |
| 278 E.g for std::string, generate Value::CreateStringValue(var) |
240 """ | 279 """ |
241 if prop.type_ == PropertyType.CHOICES: | 280 if prop.type_ == PropertyType.CHOICES: |
242 # CHOICES conversion not implemented because it's not used. If needed, | 281 # CHOICES conversion not implemented. If needed, write something to |
243 # write something to generate a function that returns a scoped_ptr<Value> | 282 # generate a function that returns a scoped_ptr<Value> and put it in |
244 # and put it in _GeneratePropertyFunctions. | 283 # _GeneratePropertyFunctions, then use it here. Look at CreateEnumValue() |
| 284 # for reference. |
245 raise NotImplementedError( | 285 raise NotImplementedError( |
246 'Conversion of CHOICES to Value not implemented') | 286 'Conversion of CHOICES to Value not implemented') |
247 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT): | 287 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT): |
248 if prop.optional: | 288 if prop.optional: |
249 return '%s->ToValue().release()' % var | 289 return '%s->ToValue().release()' % var |
250 else: | 290 else: |
251 return '%s.ToValue().release()' % var | 291 return '%s.ToValue().release()' % var |
| 292 elif prop.type_ == PropertyType.ANY: |
| 293 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var) |
| 294 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: |
| 295 return '%s.DeepCopy()' % var |
252 elif prop.type_ == PropertyType.ENUM: | 296 elif prop.type_ == PropertyType.ENUM: |
253 return 'CreateEnumValue(%s).release()' % var | 297 return 'CreateEnumValue(%s).release()' % var |
254 elif prop.type_ == PropertyType.ARRAY: | 298 elif prop.type_ == PropertyType.ARRAY: |
255 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( | 299 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( |
256 prop, var) | 300 prop, var) |
257 elif prop.type_.is_fundamental: | 301 elif prop.type_.is_fundamental: |
258 if prop.optional: | 302 if prop.optional: |
259 var = '*' + var | 303 var = '*' + var |
260 return { | 304 return { |
261 PropertyType.STRING: 'Value::CreateStringValue(%s)', | 305 PropertyType.STRING: 'Value::CreateStringValue(%s)', |
(...skipping 22 matching lines...) Expand all Loading... |
284 c.Append('if (%(var)s.GetSize() < %(required)d' | 328 c.Append('if (%(var)s.GetSize() < %(required)d' |
285 ' || %(var)s.GetSize() > %(total)d)') | 329 ' || %(var)s.GetSize() > %(total)d)') |
286 c.Append(' return scoped_ptr<Params>();') | 330 c.Append(' return scoped_ptr<Params>();') |
287 c.Substitute({ | 331 c.Substitute({ |
288 'var': var, | 332 'var': var, |
289 'required': num_required, | 333 'required': num_required, |
290 'total': len(function.params), | 334 'total': len(function.params), |
291 }) | 335 }) |
292 return c | 336 return c |
293 | 337 |
294 def _GenerateFunctionParamsCreate(self, function): | 338 def _GenerateFunctionParamsCreate(self, cpp_namespace, function): |
295 """Generate function to create an instance of Params. The generated | 339 """Generate function to create an instance of Params. The generated |
296 function takes a ListValue of arguments. | 340 function takes a ListValue of arguments. |
| 341 |
| 342 E.g for function "Bar", generate Bar::Params::Create() |
297 """ | 343 """ |
298 classname = cpp_util.Classname(function.name) | |
299 c = code.Code() | 344 c = code.Code() |
300 (c.Append('// static') | 345 (c.Append('// static') |
301 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' | 346 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' |
302 '(const ListValue& args) {') | 347 '%(cpp_namespace)s::Params::Create(const ListValue& args) {') |
303 .Concat(self._GenerateParamsCheck(function, 'args')) | 348 .Concat(self._GenerateParamsCheck(function, 'args')) |
304 .Append('scoped_ptr<Params> params(new Params());') | 349 .Append('scoped_ptr<Params> params(new Params());') |
305 ) | 350 ) |
306 c.Substitute({'classname': classname}) | 351 c.Substitute({'cpp_namespace': cpp_namespace}) |
307 | 352 |
308 for param in function.params: | 353 for param in function.params: |
309 c.Concat(self._InitializePropertyToDefault(param, 'params')) | 354 c.Concat(self._InitializePropertyToDefault(param, 'params')) |
310 | 355 |
311 for i, param in enumerate(function.params): | 356 for i, param in enumerate(function.params): |
312 # Any failure will cause this function to return. If any argument is | 357 # Any failure will cause this function to return. If any argument is |
313 # incorrect or missing, those following it are not processed. Note that | 358 # incorrect or missing, those following it are not processed. Note that |
314 # this is still correct in the case of multiple optional arguments as an | 359 # this is still correct in the case of multiple optional arguments as an |
315 # optional argument at position 4 cannot exist without an argument at | 360 # optional argument at position 4 cannot exist without an argument at |
316 # position 3. | 361 # position 3. |
(...skipping 29 matching lines...) Expand all Loading... |
346 prop: the property the code is populating. | 391 prop: the property the code is populating. |
347 value_var: a Value* that should represent |prop|. | 392 value_var: a Value* that should represent |prop|. |
348 dst: the object with |prop| as a member. | 393 dst: the object with |prop| as a member. |
349 failure_value: the value to return if |prop| cannot be extracted from | 394 failure_value: the value to return if |prop| cannot be extracted from |
350 |value_var| | 395 |value_var| |
351 check_type: if true, will check if |value_var| is the correct Value::Type | 396 check_type: if true, will check if |value_var| is the correct Value::Type |
352 """ | 397 """ |
353 c = code.Code() | 398 c = code.Code() |
354 c.Sblock('{') | 399 c.Sblock('{') |
355 | 400 |
356 if check_type and prop.type_ != PropertyType.CHOICES: | 401 if check_type and prop.type_ not in ( |
| 402 PropertyType.CHOICES, PropertyType.ANY): |
357 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') | 403 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') |
358 .Append(' return %(failure_value)s;') | 404 .Append(' return %(failure_value)s;') |
359 ) | 405 ) |
360 | 406 |
361 if prop.type_.is_fundamental: | 407 if prop.type_.is_fundamental: |
362 if prop.optional: | 408 if prop.optional: |
363 (c.Append('%(ctype)s temp;') | 409 (c.Append('%(ctype)s temp;') |
364 .Append('if (%s)' % | 410 .Append('if (%s)' % |
365 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) | 411 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) |
366 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') | 412 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') |
(...skipping 15 matching lines...) Expand all Loading... |
382 .Append('%(dst)s->%(name)s = temp.Pass();') | 428 .Append('%(dst)s->%(name)s = temp.Pass();') |
383 ) | 429 ) |
384 else: | 430 else: |
385 (c.Append('DictionaryValue* dictionary = NULL;') | 431 (c.Append('DictionaryValue* dictionary = NULL;') |
386 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | 432 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') |
387 .Append(' return %(failure_value)s;') | 433 .Append(' return %(failure_value)s;') |
388 .Append( | 434 .Append( |
389 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') | 435 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') |
390 .Append(' return %(failure_value)s;') | 436 .Append(' return %(failure_value)s;') |
391 ) | 437 ) |
| 438 elif prop.type_ == PropertyType.ANY: |
| 439 if prop.optional: |
| 440 c.Append('%(dst)s->%(name)s.reset(new Any());') |
| 441 c.Append(self._any_helper.Init(prop, value_var, dst) + ';') |
392 elif prop.type_ == PropertyType.ARRAY: | 442 elif prop.type_ == PropertyType.ARRAY: |
393 # util_cc_helper deals with optional and required arrays | 443 # util_cc_helper deals with optional and required arrays |
394 (c.Append('ListValue* list = NULL;') | 444 (c.Append('ListValue* list = NULL;') |
395 .Append('if (!%(value_var)s->GetAsList(&list))') | 445 .Append('if (!%(value_var)s->GetAsList(&list))') |
396 .Append(' return %(failure_value)s;') | 446 .Append(' return %(failure_value)s;') |
397 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | 447 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( |
398 prop, 'list', dst + '->' + prop.unix_name)) | 448 prop, 'list', dst + '->' + prop.unix_name)) |
399 .Append(' return %(failure_value)s;') | 449 .Append(' return %(failure_value)s;') |
400 ) | 450 ) |
401 elif prop.type_ == PropertyType.CHOICES: | 451 elif prop.type_ == PropertyType.CHOICES: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 ) | 485 ) |
436 else: | 486 else: |
437 raise NotImplementedError(prop.type_) | 487 raise NotImplementedError(prop.type_) |
438 c.Eblock('}') | 488 c.Eblock('}') |
439 sub = { | 489 sub = { |
440 'value_var': value_var, | 490 'value_var': value_var, |
441 'name': prop.unix_name, | 491 'name': prop.unix_name, |
442 'dst': dst, | 492 'dst': dst, |
443 'failure_value': failure_value, | 493 'failure_value': failure_value, |
444 } | 494 } |
445 if prop.type_ != PropertyType.CHOICES: | 495 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY): |
446 sub['ctype'] = self._cpp_type_generator.GetType(prop) | 496 sub['ctype'] = self._cpp_type_generator.GetType(prop) |
447 sub['value_type'] = cpp_util.GetValueType(prop) | 497 sub['value_type'] = cpp_util.GetValueType(prop) |
448 c.Substitute(sub) | 498 c.Substitute(sub) |
449 return c | 499 return c |
450 | 500 |
451 def _GeneratePropertyFunctions(self, param_namespace, params): | 501 def _GeneratePropertyFunctions(self, param_namespace, params): |
452 """Generate the functions for structures generated by a property such as | 502 """Generate the functions for structures generated by a property such as |
453 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. | 503 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. |
454 """ | 504 """ |
455 c = code.Code() | 505 c = code.Code() |
456 for param in params: | 506 for param in params: |
457 if param.type_ == PropertyType.OBJECT: | 507 if param.type_ == PropertyType.OBJECT: |
458 c.Concat(self._GenerateType( | 508 c.Concat(self._GenerateType( |
459 param_namespace + '::' + cpp_util.Classname(param.name), | 509 param_namespace + '::' + cpp_util.Classname(param.name), |
460 param)) | 510 param)) |
461 c.Append() | 511 c.Append() |
| 512 elif param.type_ == PropertyType.CHOICES: |
| 513 c.Concat(self._GeneratePropertyFunctions( |
| 514 param_namespace, param.choices.values())) |
462 elif param.type_ == PropertyType.ENUM: | 515 elif param.type_ == PropertyType.ENUM: |
463 c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) | 516 c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) |
464 c.Append() | 517 c.Append() |
465 return c | 518 return c |
466 | 519 |
467 def _GenerateFunctionResultCreate(self, function): | 520 def _GenerateFunctionResultCreate(self, cpp_namespace, function): |
468 """Generate function to create a Result given the return value. | 521 """Generate function to create a Result given the return value. |
| 522 |
| 523 E.g for function "Bar", generate Bar::Result::Create |
469 """ | 524 """ |
470 classname = cpp_util.Classname(function.name) | |
471 c = code.Code() | 525 c = code.Code() |
472 params = function.callback.params | 526 params = function.callback.params |
473 | 527 |
474 if not params: | 528 if not params: |
475 (c.Append('Value* %s::Result::Create() {' % classname) | 529 (c.Append('Value* %s::Result::Create() {' % cpp_namespace) |
476 .Append(' return Value::CreateNullValue();') | 530 .Append(' return Value::CreateNullValue();') |
477 .Append('}') | 531 .Append('}') |
478 ) | 532 ) |
479 else: | 533 else: |
480 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( | 534 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( |
481 params) | 535 params) |
482 c.Concat(self._GeneratePropertyFunctions( | 536 c.Concat(self._GeneratePropertyFunctions( |
483 classname + '::Result', expanded_params)) | 537 cpp_namespace + '::Result', expanded_params)) |
484 | 538 |
485 # If there is a single parameter, this is straightforward. However, if | 539 # If there is a single parameter, this is straightforward. However, if |
486 # the callback parameter is of 'choices', this generates a Create method | 540 # the callback parameter is of 'choices', this generates a Create method |
487 # for each choice. This works because only 1 choice can be returned at a | 541 # for each choice. This works because only 1 choice can be returned at a |
488 # time. | 542 # time. |
489 for param in expanded_params: | 543 for param in expanded_params: |
| 544 if param.type_ == PropertyType.ANY: |
| 545 # Generation of Value* Create(Value*) is redundant. |
| 546 continue |
490 # We treat this argument as 'required' to avoid wrapping it in a | 547 # We treat this argument as 'required' to avoid wrapping it in a |
491 # scoped_ptr if it's optional. | 548 # scoped_ptr if it's optional. |
492 param_copy = param.Copy() | 549 param_copy = param.Copy() |
493 param_copy.optional = False | 550 param_copy.optional = False |
494 c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {') | 551 c.Sblock('Value* %(cpp_namespace)s::Result::Create(const %(arg)s) {') |
495 c.Append('return %s;' % | 552 c.Append('return %s;' % |
496 self._CreateValueFromProperty(param_copy, param_copy.unix_name)) | 553 self._CreateValueFromProperty(param_copy, param_copy.unix_name)) |
497 c.Eblock('}') | 554 c.Eblock('}') |
498 c.Substitute({'classname': classname, | 555 c.Substitute({ |
| 556 'cpp_namespace': cpp_namespace, |
499 'arg': cpp_util.GetParameterDeclaration( | 557 'arg': cpp_util.GetParameterDeclaration( |
500 param_copy, self._cpp_type_generator.GetType(param_copy)) | 558 param_copy, self._cpp_type_generator.GetType(param_copy)) |
501 }) | 559 }) |
502 | 560 |
503 return c | 561 return c |
504 | 562 |
505 def _InitializePropertyToDefault(self, prop, dst): | 563 def _InitializePropertyToDefault(self, prop, dst): |
506 """Initialize a model.Property to its default value inside an object. | 564 """Initialize a model.Property to its default value inside an object. |
507 | 565 |
| 566 E.g for optional enum "state", generate dst->state = STATE_NONE; |
| 567 |
508 dst: Type* | 568 dst: Type* |
509 """ | 569 """ |
510 c = code.Code() | 570 c = code.Code() |
511 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): | 571 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): |
512 if prop.optional: | 572 if prop.optional: |
513 prop_name = prop.unix_name | 573 prop_name = prop.unix_name |
514 if prop.type_ == PropertyType.CHOICES: | 574 if prop.type_ == PropertyType.CHOICES: |
515 prop_name = prop.unix_name + '_type' | 575 prop_name = prop.unix_name + '_type' |
516 c.Append('%s->%s = %s;' % ( | 576 c.Append('%s->%s = %s;' % ( |
517 dst, | 577 dst, |
518 prop_name, | 578 prop_name, |
519 self._cpp_type_generator.GetEnumNoneValue(prop))) | 579 self._cpp_type_generator.GetEnumNoneValue(prop))) |
520 return c | 580 return c |
521 | 581 |
OLD | NEW |