Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: tools/json_schema_compiler/cc_generator.py

Issue 9456007: Add wider support to json_schema_compiler (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rework, add nocompile to extension.json Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 code 6 import code
7 import cpp_util 7 import cpp_util
8 import util_cc_helper 8 import util_cc_helper
9 9
10 class CCGenerator(object): 10 class CCGenerator(object):
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 (c.Concat(self._GenerateFunction(function)) 65 (c.Concat(self._GenerateFunction(function))
66 .Append() 66 .Append()
67 ) 67 )
68 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) 68 (c.Concat(self._cpp_type_generator.GetNamespaceEnd())
69 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) 69 .Concat(self._cpp_type_generator.GetRootNamespaceEnd())
70 .Append() 70 .Append()
71 ) 71 )
72 # TODO(calamity): Events 72 # TODO(calamity): Events
73 return c 73 return c
74 74
75 def _GenerateType(self, cpp_namespace, type_, serializable=True): 75 def _GenerateType(self, cpp_namespace, type_):
76 """Generates the function definitions for a type. 76 """Generates the function definitions for a type.
77 """ 77 """
78 classname = cpp_util.Classname(type_.name) 78 classname = cpp_util.Classname(type_.name)
79 c = code.Code() 79 c = code.Code()
80 80
81 (c.Append('%(namespace)s::%(classname)s() {}') 81 (c.Concat(self._GeneratePropertyFunctions(
82 cpp_namespace, type_.properties.values()))
83 .Append('%(namespace)s::%(classname)s() {}')
82 .Append('%(namespace)s::~%(classname)s() {}') 84 .Append('%(namespace)s::~%(classname)s() {}')
83 .Append() 85 .Append()
84 .Concat(self._GenerateTypePopulate(cpp_namespace, type_))
85 .Append()
86 ) 86 )
87 if serializable: 87 if type_.from_api:
88 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
89 .Append()
90 )
91 if type_.to_api:
88 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) 92 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
89 c.Append() 93 c.Append()
90 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) 94 c.Substitute({'classname': classname, 'namespace': cpp_namespace})
91 95
92 return c 96 return c
93 97
94 def _GenerateTypePopulate(self, cpp_namespace, type_): 98 def _GenerateTypePopulate(self, cpp_namespace, type_):
95 """Generates the function for populating a type given a pointer to it. 99 """Generates the function for populating a type given a pointer to it.
96 """ 100 """
97 classname = cpp_util.Classname(type_.name) 101 classname = cpp_util.Classname(type_.name)
(...skipping 24 matching lines...) Expand all
122 dst: Type* 126 dst: Type*
123 """ 127 """
124 c = code.Code() 128 c = code.Code()
125 value_var = prop.unix_name + '_value' 129 value_var = prop.unix_name + '_value'
126 c.Append('Value* %(value_var)s = NULL;') 130 c.Append('Value* %(value_var)s = NULL;')
127 if prop.optional: 131 if prop.optional:
128 (c.Sblock( 132 (c.Sblock(
129 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {' 133 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {'
130 ) 134 )
131 .Concat(self._GeneratePopulatePropertyFromValue( 135 .Concat(self._GeneratePopulatePropertyFromValue(
132 prop, value_var, 'out', 'false')) 136 prop, value_var, dst, 'false'))
133 .Eblock('}') 137 .Eblock('}')
134 ) 138 )
135 else: 139 else:
136 (c.Append( 140 (c.Append(
137 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') 141 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))')
138 .Append(' return false;') 142 .Append(' return false;')
139 .Concat(self._GeneratePopulatePropertyFromValue( 143 .Concat(self._GeneratePopulatePropertyFromValue(
140 prop, value_var, 'out', 'false')) 144 prop, value_var, dst, 'false'))
141 ) 145 )
142 c.Append() 146 c.Append()
143 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) 147 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src})
144 return c 148 return c
145 149
146 def _GenerateTypeToValue(self, cpp_namespace, type_): 150 def _GenerateTypeToValue(self, cpp_namespace, type_):
147 """Generates a function that serializes the type into a |DictionaryValue|. 151 """Generates a function that serializes the type into a |DictionaryValue|.
152 CHOICES properties are not supported.
not at google - send to devlin 2012/02/26 23:51:53 Similar comment to the one in cpp_type_generator.
calamity 2012/02/27 04:57:30 Put the comment in _CreateValueFromProperty, this
148 """ 153 """
149 c = code.Code() 154 c = code.Code()
150 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % 155 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' %
151 cpp_namespace) 156 cpp_namespace)
152 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') 157 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());')
153 .Append() 158 .Append()
154 ) 159 )
155 for prop in type_.properties.values(): 160 for prop in type_.properties.values():
156 c.Concat(self._CreateValueFromProperty(prop, prop.unix_name, 'value')) 161 if prop.optional:
162 if prop.type_ == PropertyType.ENUM:
163 c.Sblock('if (%s != %s)' %
164 (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop)))
165 else:
166 c.Sblock('if (%s.get())' % prop.unix_name)
167 c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
168 prop.name,
169 self._cpp_type_generator.CreateValueFromProperty(
170 self._util_cc_helper, prop, prop.unix_name)))
157 (c.Append() 171 (c.Append()
158 .Append('return value.Pass();') 172 .Append('return value.Pass();')
159 .Eblock('}') 173 .Eblock('}')
160 ) 174 )
161 return c 175 return c
162 176
163 def _CreateValueFromProperty(self, prop, var, dst):
164 """Generates code to serialize a single property in a type.
165
166 prop: Property to create from
167 var: variable with value to create from
168 """
169 c = code.Code()
170 if prop.type_ == PropertyType.ENUM:
171 c.Sblock('switch (%s) {' % var)
172 for enum_value in prop.enum_values:
173 (c.Append('case %s: {' %
174 self._cpp_type_generator.GetEnumValue(prop, enum_value))
175 .Append(' %s->SetWithoutPathExpansion('
176 '"%s", Value::CreateStringValue("%s"));' %
177 (dst, prop.name, enum_value))
178 .Append(' break;')
179 .Append('}')
180 )
181 # C++ requires the entire enum to be handled by a switch.
182 if prop.optional:
183 (c.Append('case %s: {' %
184 self._cpp_type_generator.GetEnumNoneValue(prop))
185 .Append(' break;')
186 .Append('}')
187 )
188 c.Eblock('}')
189 else:
190 if prop.optional:
191 c.Sblock('if (%s.get())' % var)
192 if prop.type_ == PropertyType.ARRAY:
193 c.Append('%s;' % self._util_cc_helper.PopulateDictionaryFromArray(
194 prop, var, prop.name, dst))
195 else:
196 c.Append('%s->SetWithoutPathExpansion("%s", %s);' %
197 (dst, prop.name, cpp_util.CreateValueFromSingleProperty(prop, var)))
198 return c
199
200 def _GenerateFunction(self, function): 177 def _GenerateFunction(self, function):
201 """Generates the definitions for function structs. 178 """Generates the definitions for function structs.
202 """ 179 """
203 classname = cpp_util.Classname(function.name) 180 classname = cpp_util.Classname(function.name)
204 c = code.Code() 181 c = code.Code()
205 182
206 # Params::Populate function 183 # Params::Populate function
207 if function.params: 184 if function.params:
208 for param in function.params: 185 c.Concat(self._GeneratePropertyFunctions(classname + '::Params',
209 if param.type_ == PropertyType.OBJECT: 186 function.params))
210 param_namespace = '%s::Params::%s' % (classname,
211 cpp_util.Classname(param.name))
212 c.Concat(
213 self._GenerateType(param_namespace, param, serializable=False))
214 c.Append()
215 (c.Append('%(name)s::Params::Params() {}') 187 (c.Append('%(name)s::Params::Params() {}')
216 .Append('%(name)s::Params::~Params() {}') 188 .Append('%(name)s::Params::~Params() {}')
217 .Append() 189 .Append()
218 .Concat(self._GenerateFunctionParamsCreate(function)) 190 .Concat(self._GenerateFunctionParamsCreate(function))
219 .Append() 191 .Append()
220 ) 192 )
221 193
222 # Result::Create function 194 # Result::Create function
223 c.Concat(self._GenerateFunctionResultCreate(function)) 195 if function.callback:
196 c.Concat(self._GenerateFunctionResultCreate(function))
224 197
225 c.Substitute({'name': classname}) 198 c.Substitute({'name': classname})
226 199
227 return c 200 return c
228 201
202 def _GenerateCreateEnumValue(self, cpp_namespace, prop):
203 """Generates a function that returns the |StringValue| representation of an
204 enum.
205 """
206 c = code.Code()
207 c.Append('// static')
208 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {')
209 c.Sblock('switch (%s) {' % prop.unix_name)
210 if prop.optional:
211 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop))
212 .Append(' return scoped_ptr<Value>();')
213 .Append('}')
214 )
215 for enum_value in prop.enum_values:
216 (c.Append('case %s: {' %
217 self._cpp_type_generator.GetEnumValue(prop, enum_value))
218 .Append(' return scoped_ptr<Value>(Value::CreateStringValue("%s"));' %
219 enum_value)
220 .Append('}')
221 )
222 c.Eblock('}')
223 c.Eblock('}')
224 c.Substitute({
225 'cpp_namespace': cpp_namespace,
226 'arg': cpp_util.GetParameterDeclaration(
227 prop, self._cpp_type_generator.GetType(prop))
228 })
229 return c
230
229 def _GenerateParamsCheck(self, function, var): 231 def _GenerateParamsCheck(self, function, var):
230 """Generates a check for the correct number of arguments when creating 232 """Generates a check for the correct number of arguments when creating
231 Params. 233 Params.
232 """ 234 """
233 c = code.Code() 235 c = code.Code()
234 num_required = 0 236 num_required = 0
235 for param in function.params: 237 for param in function.params:
236 if not param.optional: 238 if not param.optional:
237 num_required += 1 239 num_required += 1
238 if num_required == len(function.params): 240 if num_required == len(function.params):
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 prop: the property the code is populating. 307 prop: the property the code is populating.
306 value_var: a Value* that should represent |prop|. 308 value_var: a Value* that should represent |prop|.
307 dst: the object with |prop| as a member. 309 dst: the object with |prop| as a member.
308 failure_value: the value to return if |prop| cannot be extracted from 310 failure_value: the value to return if |prop| cannot be extracted from
309 |value_var| 311 |value_var|
310 check_type: if true, will check if |value_var| is the correct Value::Type 312 check_type: if true, will check if |value_var| is the correct Value::Type
311 """ 313 """
312 c = code.Code() 314 c = code.Code()
313 c.Sblock('{') 315 c.Sblock('{')
314 316
315 if check_type: 317 if check_type and prop.type_ != PropertyType.CHOICES:
316 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') 318 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))')
317 .Append(' return %(failure_value)s;') 319 .Append(' return %(failure_value)s;')
318 ) 320 )
319 321
320 if prop.type_.is_fundamental: 322 if prop.type_.is_fundamental:
321 if prop.optional: 323 if prop.optional:
322 (c.Append('%(ctype)s temp;') 324 (c.Append('%(ctype)s temp;')
323 .Append('if (%s)' % 325 .Append('if (%s)' %
324 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) 326 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp'))
325 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') 327 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));')
(...skipping 25 matching lines...) Expand all
351 elif prop.type_ == PropertyType.ARRAY: 353 elif prop.type_ == PropertyType.ARRAY:
352 # util_cc_helper deals with optional and required arrays 354 # util_cc_helper deals with optional and required arrays
353 (c.Append('ListValue* list = NULL;') 355 (c.Append('ListValue* list = NULL;')
354 .Append('if (!%(value_var)s->GetAsList(&list))') 356 .Append('if (!%(value_var)s->GetAsList(&list))')
355 .Append(' return %(failure_value)s;') 357 .Append(' return %(failure_value)s;')
356 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( 358 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
357 prop, 'list', dst + '->' + prop.unix_name)) 359 prop, 'list', dst + '->' + prop.unix_name))
358 .Append(' return %(failure_value)s;') 360 .Append(' return %(failure_value)s;')
359 ) 361 )
360 elif prop.type_ == PropertyType.CHOICES: 362 elif prop.type_ == PropertyType.CHOICES:
361 return self._GeneratePopulateChoices(prop, value_var, dst, failure_value) 363 type_var = '%(dst)s->%(name)s_type'
364 c.Sblock('switch (%(value_var)s->GetType()) {')
365 for choice in self._cpp_type_generator.GetExpandedChoicesInParams([prop]):
366 (c.Sblock('case %s: {' % cpp_util.GetValueType(choice))
367 .Concat(self._GeneratePopulatePropertyFromValue(
368 choice, value_var, dst, failure_value, check_type=False))
369 .Append('%s = %s;' %
370 (type_var,
371 self._cpp_type_generator.GetEnumValue(
372 prop, choice.type_.name)))
373 .Append('break;')
374 .Eblock('}')
375 )
376 (c.Append('default:')
377 .Append(' return %(failure_value)s;')
378 )
379 c.Eblock('}')
362 elif prop.type_ == PropertyType.ENUM: 380 elif prop.type_ == PropertyType.ENUM:
363 (c.Append('std::string enum_temp;') 381 (c.Append('std::string enum_temp;')
364 .Append('if (!%(value_var)s->GetAsString(&enum_temp))') 382 .Append('if (!%(value_var)s->GetAsString(&enum_temp))')
365 .Append(' return %(failure_value)s;') 383 .Append(' return %(failure_value)s;')
366 ) 384 )
367 for i, enum_value in enumerate(prop.enum_values): 385 for i, enum_value in enumerate(prop.enum_values):
368 (c.Append( 386 (c.Append(
369 ('if' if i == 0 else 'else if') + 387 ('if' if i == 0 else 'else if') +
370 '(enum_temp == "%s")' % enum_value) 388 '(enum_temp == "%s")' % enum_value)
371 .Append(' %s->%s = %s;' % ( 389 .Append(' %s->%s = %s;' % (
372 dst, 390 dst,
373 prop.unix_name, 391 prop.unix_name,
374 self._cpp_type_generator.GetEnumValue(prop, enum_value))) 392 self._cpp_type_generator.GetEnumValue(prop, enum_value)))
375 ) 393 )
376 (c.Append('else') 394 (c.Append('else')
377 .Append(' return %(failure_value)s;') 395 .Append(' return %(failure_value)s;')
378 ) 396 )
379 else: 397 else:
380 raise NotImplementedError(prop.type_) 398 raise NotImplementedError(prop.type_)
381 c.Eblock('}') 399 c.Eblock('}')
382 c.Substitute({ 400 sub = {
383 'value_var': value_var, 401 'value_var': value_var,
384 'name': prop.unix_name, 402 'name': prop.unix_name,
385 'dst': dst, 403 'dst': dst,
386 'ctype': self._cpp_type_generator.GetType(prop),
387 'failure_value': failure_value, 404 'failure_value': failure_value,
388 'value_type': cpp_util.GetValueType(prop), 405 }
389 }) 406 if prop.type_ != PropertyType.CHOICES:
407 sub['ctype'] = self._cpp_type_generator.GetType(prop)
408 sub['value_type'] = cpp_util.GetValueType(prop)
409 c.Substitute(sub)
390 return c 410 return c
391 411
392 def _GeneratePopulateChoices(self, prop, value_var, dst, failure_value): 412 def _GeneratePropertyFunctions(self, param_namespace, params):
393 """Generates the code to populate a PropertyType.CHOICES parameter or 413 """Generate the functions for structures generated by a property such as
394 property. The existence of data inside the Value* is assumed so checks for 414 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects.
395 existence should be performed before the code this generates.
396
397 prop: the property the code is populating..
398 value_var: a Value* that should represent |prop|.
399 dst: the object with |prop| as a member.
400 failure_value: the value to return if |prop| cannot be extracted from
401 |value_var|.
402 """ 415 """
403 type_var = '%s->%s_type' % (dst, prop.unix_name)
404
405 c = code.Code() 416 c = code.Code()
406 c.Sblock('switch (%s->GetType()) {' % value_var) 417 for param in params:
407 for choice in self._cpp_type_generator.GetExpandedChoicesInParams([prop]): 418 if param.type_ == PropertyType.OBJECT:
408 (c.Sblock('case %s: {' % cpp_util.GetValueType(choice)) 419 c.Concat(self._GenerateType(
409 .Concat(self._GeneratePopulatePropertyFromValue( 420 param_namespace + '::' + cpp_util.Classname(param.name),
410 choice, value_var, dst, failure_value, check_type=False)) 421 param))
411 .Append('%s = %s;' % 422 c.Append()
412 (type_var, 423 elif param.type_ == PropertyType.ENUM:
413 self._cpp_type_generator.GetEnumValue( 424 c.Concat(self._GenerateCreateEnumValue(param_namespace, param))
414 prop, choice.type_.name))) 425 c.Append()
415 .Append('break;')
416 .Eblock('}')
417 )
418 (c.Append('default:')
419 .Append(' return %s;' % failure_value)
420 )
421 c.Eblock('}')
422 return c 426 return c
423 427
424 def _GenerateFunctionResultCreate(self, function): 428 def _GenerateFunctionResultCreate(self, function):
425 """Generate function to create a Result given the return value. 429 """Generate function to create a Result given the return value.
426 """ 430 """
427 classname = cpp_util.Classname(function.name) 431 classname = cpp_util.Classname(function.name)
428 c = code.Code() 432 c = code.Code()
429 params = function.callback.params 433 params = function.callback.params
430 434
431 if not params: 435 if not params:
432 (c.Append('Value* %s::Result::Create() {' % classname) 436 (c.Append('Value* %s::Result::Create() {' % classname)
433 .Append(' return Value::CreateNullValue();') 437 .Append(' return Value::CreateNullValue();')
434 .Append('}') 438 .Append('}')
435 ) 439 )
436 else: 440 else:
441 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams(
442 params)
443 c.Concat(self._GeneratePropertyFunctions(
444 classname + '::Result', expanded_params))
445
437 # If there is a single parameter, this is straightforward. However, if 446 # If there is a single parameter, this is straightforward. However, if
438 # the callback parameter is of 'choices', this generates a Create method 447 # the callback parameter is of 'choices', this generates a Create method
439 # for each choice. This works because only 1 choice can be returned at a 448 # for each choice. This works because only 1 choice can be returned at a
440 # time. 449 # time.
441 for param in self._cpp_type_generator.GetExpandedChoicesInParams(params): 450 for param in expanded_params:
442 # We treat this argument as 'required' to avoid wrapping it in a 451 # We treat this argument as 'required' to avoid wrapping it in a
443 # scoped_ptr if it's optional. 452 # scoped_ptr if it's optional.
444 param_copy = param.Copy() 453 param_copy = param.Copy()
445 param_copy.optional = False 454 param_copy.optional = False
446 c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {') 455 c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {')
447 if param_copy.type_ == PropertyType.ARRAY: 456 c.Append('return %s;' %
448 (c.Append('ListValue* value = new ListValue();') 457 self._cpp_type_generator.CreateValueFromProperty(
449 .Append('%s;' % self._util_cc_helper.PopulateListFromArray( 458 self._util_cc_helper, param_copy, param_copy.unix_name))
450 param_copy, param_copy.unix_name, 'value')) 459 c.Eblock('}')
451 .Append('return value;')
452 )
453 else:
454 c.Append('return %s;' %
455 cpp_util.CreateValueFromSingleProperty(param_copy,
456 param_copy.unix_name))
457 c.Substitute({'classname': classname, 460 c.Substitute({'classname': classname,
458 'arg': cpp_util.GetParameterDeclaration( 461 'arg': cpp_util.GetParameterDeclaration(
459 param_copy, self._cpp_type_generator.GetType(param_copy)) 462 param_copy, self._cpp_type_generator.GetType(param_copy))
460 }) 463 })
461 c.Eblock('}')
462 464
463 return c 465 return c
464 466
465 def _InitializePropertyToDefault(self, prop, dst): 467 def _InitializePropertyToDefault(self, prop, dst):
466 """Initialize a model.Property to its default value inside an object. 468 """Initialize a model.Property to its default value inside an object.
467 469
468 dst: Type* 470 dst: Type*
469 """ 471 """
470 c = code.Code() 472 c = code.Code()
471 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): 473 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES):
472 if prop.optional: 474 if prop.optional:
473 prop_name = prop.unix_name 475 prop_name = prop.unix_name
474 if prop.type_ == PropertyType.CHOICES: 476 if prop.type_ == PropertyType.CHOICES:
475 prop_name = prop.unix_name + '_type' 477 prop_name = prop.unix_name + '_type'
476 c.Append('%s->%s = %s;' % ( 478 c.Append('%s->%s = %s;' % (
477 dst, 479 dst,
478 prop_name, 480 prop_name,
479 self._cpp_type_generator.GetEnumNoneValue(prop))) 481 self._cpp_type_generator.GetEnumNoneValue(prop)))
480 return c 482 return c
481 483
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698