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

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

Issue 276603003: Support converting referenced enum array into string. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 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
« no previous file with comments | « no previous file | tools/json_schema_compiler/test/arrays.json » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 code import Code 5 from code import Code
6 from model import PropertyType 6 from model import PropertyType
7 import cpp_util 7 import cpp_util
8 import schema_util 8 import schema_util
9 import util_cc_helper 9 import util_cc_helper
10 10
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 if underlying_type.property_type == PropertyType.ENUM: 359 if underlying_type.property_type == PropertyType.ENUM:
360 c.Sblock('if (%s != %s) {' % 360 c.Sblock('if (%s != %s) {' %
361 (prop_var, 361 (prop_var,
362 self._type_helper.GetEnumNoneValue(prop.type_))) 362 self._type_helper.GetEnumNoneValue(prop.type_)))
363 else: 363 else:
364 c.Sblock('if (%s.get()) {' % prop_var) 364 c.Sblock('if (%s.get()) {' % prop_var)
365 365
366 # ANY is a base::Value which is abstract and cannot be a direct member, so 366 # ANY is a base::Value which is abstract and cannot be a direct member, so
367 # it will always be a pointer. 367 # it will always be a pointer.
368 is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY 368 is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
369 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( 369 c.Cblock(self._CreateValueFromType(
370 'value->SetWithoutPathExpansion("%s", %%s);' % prop.name,
370 prop.name, 371 prop.name,
371 self._CreateValueFromType(cpp_namespace, 372 prop.type_,
372 prop.type_, 373 prop_var,
373 prop_var, 374 is_ptr=is_ptr))
374 is_ptr=is_ptr)))
375 375
376 if prop.optional: 376 if prop.optional:
377 c.Eblock('}') 377 c.Eblock('}')
378 378
379 if type_.additional_properties is not None: 379 if type_.additional_properties is not None:
380 if type_.additional_properties.property_type == PropertyType.ANY: 380 if type_.additional_properties.property_type == PropertyType.ANY:
381 c.Append('value->MergeDictionary(&additional_properties);') 381 c.Append('value->MergeDictionary(&additional_properties);')
382 else: 382 else:
383 # Non-copyable types will be wrapped in a linked_ptr for inclusion in 383 # Non-copyable types will be wrapped in a linked_ptr for inclusion in
384 # maps, so we need to unwrap them. 384 # maps, so we need to unwrap them.
385 needs_unwrap = ( 385 needs_unwrap = (
386 not self._type_helper.IsCopyable(type_.additional_properties)) 386 not self._type_helper.IsCopyable(type_.additional_properties))
387 cpp_type = self._type_helper.GetCppType(type_.additional_properties, 387 cpp_type = self._type_helper.GetCppType(type_.additional_properties,
388 is_in_container=True) 388 is_in_container=True)
389 (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' % 389 (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' %
390 cpp_util.PadForGenerics(cpp_type)) 390 cpp_util.PadForGenerics(cpp_type))
391 .Append(' additional_properties.begin();') 391 .Append(' additional_properties.begin();')
392 .Append(' it != additional_properties.end(); ++it) {') 392 .Append(' it != additional_properties.end(); ++it) {')
393 .Append('value->SetWithoutPathExpansion(it->first, %s);' % 393 .Cblock(self._CreateValueFromType(
394 self._CreateValueFromType( 394 'value->SetWithoutPathExpansion(it->first, %s);',
395 cpp_namespace, 395 type_.additional_properties.name,
396 type_.additional_properties, 396 type_.additional_properties,
397 '%sit->second' % ('*' if needs_unwrap else ''))) 397 '%sit->second' % ('*' if needs_unwrap else '')))
398 .Eblock('}') 398 .Eblock('}')
399 ) 399 )
400 400
401 return (c.Append() 401 return (c.Append()
402 .Append('return value.Pass();') 402 .Append('return value.Pass();')
403 .Eblock('}')) 403 .Eblock('}'))
404 404
405 def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): 405 def _GenerateChoiceTypeToValue(self, cpp_namespace, type_):
406 """Generates a function that serializes a choice-representing type 406 """Generates a function that serializes a choice-representing type
407 into a base::Value. 407 into a base::Value.
408 """ 408 """
409 c = Code() 409 c = Code()
410 c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) 410 c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace)
411 c.Append('scoped_ptr<base::Value> result;') 411 c.Append('scoped_ptr<base::Value> result;')
412 for choice in type_.choices: 412 for choice in type_.choices:
413 choice_var = 'as_%s' % choice.unix_name 413 choice_var = 'as_%s' % choice.unix_name
414 (c.Sblock('if (%s) {' % choice_var) 414 (c.Sblock('if (%s) {' % choice_var)
415 .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' % 415 .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
416 type_.unix_name) 416 type_.unix_name)
417 .Append('result.reset(%s);' % self._CreateValueFromType( 417 .Cblock(self._CreateValueFromType('result.reset(%s);',
418 cpp_namespace, 418 choice.name,
419 choice, 419 choice,
420 '*%s' % choice_var)) 420 '*%s' % choice_var))
421 .Eblock('}') 421 .Eblock('}')
422 ) 422 )
423 (c.Append('DCHECK(result) << "Must set at least one choice for %s";' % 423 (c.Append('DCHECK(result) << "Must set at least one choice for %s";' %
424 type_.unix_name) 424 type_.unix_name)
425 .Append('return result.Pass();') 425 .Append('return result.Pass();')
426 .Eblock('}') 426 .Eblock('}')
427 ) 427 )
428 return c 428 return c
429 429
430 def _GenerateFunction(self, function): 430 def _GenerateFunction(self, function):
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 (c.Append('namespace %s {' % event_namespace) 467 (c.Append('namespace %s {' % event_namespace)
468 .Append() 468 .Append()
469 .Cblock(self._GenerateEventNameConstant(None, event)) 469 .Cblock(self._GenerateEventNameConstant(None, event))
470 .Cblock(self._GenerateCreateCallbackArguments(event_namespace, 470 .Cblock(self._GenerateCreateCallbackArguments(event_namespace,
471 None, 471 None,
472 event)) 472 event))
473 .Append('} // namespace %s' % event_namespace) 473 .Append('} // namespace %s' % event_namespace)
474 ) 474 )
475 return c 475 return c
476 476
477 def _CreateValueFromType(self, cpp_namespace, type_, var, is_ptr=False): 477 def _CreateValueFromType(self, code, prop_name, type_, var, is_ptr=False):
478 """Creates a base::Value given a type. Generated code passes ownership 478 """Creates a base::Value given a type. Generated code passes ownership
479 to caller. 479 to caller.
480 480
481 var: variable or variable* 481 var: variable or variable*
482 482
483 E.g for std::string, generate new base::StringValue(var) 483 E.g for std::string, generate new base::StringValue(var)
484 """ 484 """
485 c = Code()
486 underlying_type = self._type_helper.FollowRef(type_)
487 if underlying_type.property_type == PropertyType.ARRAY:
488 # Enums are treated specially because C++ templating thinks that they're
489 # ints, but really they're strings. So we create a vector of strings and
490 # populate it with the names of the enum in the array. The |ToString|
491 # function of the enum can be in another namespace when the enum is
492 # referenced. Templates can not be used here because C++ templating does
493 # not support passing a namespace as an argument.
494 item_type = self._type_helper.FollowRef(underlying_type.item_type)
495 if item_type.property_type == PropertyType.ENUM:
496 vardot = '(%s)%s' % (var, '->' if is_ptr else '.')
497
498 maybe_namespace = ''
499 if type_.item_type.property_type == PropertyType.REF:
500 maybe_namespace = '%s::' % item_type.namespace.unix_name
501
502 enum_list_var = '%s_list' % prop_name
503 # Scope the std::vector variable declaration inside braces.
504 (c.Sblock('{')
505 .Append('std::vector<std::string> %s;' % enum_list_var)
506 .Append('for (typename std::vector<%s>::const_iterator '
507 'it = %sbegin();'
508 % (self._type_helper.GetCppType(item_type), vardot))
509 .Sblock(' it != %send(); ++it) {' % vardot)
510 .Append('%s.push_back(%sToString(*it));' % (enum_list_var,
511 maybe_namespace))
512 .Eblock('}'))
513
514 # Because the std::vector above is always created for both required and
515 # optional enum arrays, |is_ptr| is set to false and uses the
516 # std::vector to create the values.
517 (c.Append(code %
518 self._GenerateCreateValueFromType(type_, enum_list_var, False))
519 .Eblock('}'))
wjywbs 2014/05/16 19:12:23 Because the variable is scoped, the code generated
520 return c
521
522 c.Append(code % self._GenerateCreateValueFromType(type_, var, is_ptr))
523 return c
524
525 def _GenerateCreateValueFromType(self, type_, var, is_ptr):
526 """Generates the statement to create a base::Value given a type.
527
528 type_: The type of the values being converted.
529 var: The name of the variable.
530 is_ptr: Whether |type_| is optional.
531 """
485 underlying_type = self._type_helper.FollowRef(type_) 532 underlying_type = self._type_helper.FollowRef(type_)
486 if (underlying_type.property_type == PropertyType.CHOICES or 533 if (underlying_type.property_type == PropertyType.CHOICES or
487 underlying_type.property_type == PropertyType.OBJECT): 534 underlying_type.property_type == PropertyType.OBJECT):
488 if is_ptr: 535 if is_ptr:
489 return '(%s)->ToValue().release()' % var 536 return '(%s)->ToValue().release()' % var
490 else: 537 else:
491 return '(%s).ToValue().release()' % var 538 return '(%s).ToValue().release()' % var
492 elif (underlying_type.property_type == PropertyType.ANY or 539 elif (underlying_type.property_type == PropertyType.ANY or
493 underlying_type.property_type == PropertyType.FUNCTION): 540 underlying_type.property_type == PropertyType.FUNCTION):
494 if is_ptr: 541 if is_ptr:
495 vardot = '(%s)->' % var 542 vardot = '(%s)->' % var
496 else: 543 else:
497 vardot = '(%s).' % var 544 vardot = '(%s).' % var
498 return '%sDeepCopy()' % vardot 545 return '%sDeepCopy()' % vardot
499 elif underlying_type.property_type == PropertyType.ENUM: 546 elif underlying_type.property_type == PropertyType.ENUM:
500 classname = cpp_util.Classname(schema_util.StripNamespace( 547 classname = cpp_util.Classname(schema_util.StripNamespace(
501 underlying_type.name)) 548 underlying_type.name))
502 return 'new base::StringValue(%sToString(%s))' % (classname, var) 549 return 'new base::StringValue(%sToString(%s))' % (classname, var)
503 elif underlying_type.property_type == PropertyType.BINARY: 550 elif underlying_type.property_type == PropertyType.BINARY:
504 if is_ptr: 551 if is_ptr:
505 vardot = var + '->' 552 vardot = var + '->'
506 else: 553 else:
507 vardot = var + '.' 554 vardot = var + '.'
508 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % 555 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
509 (vardot, vardot)) 556 (vardot, vardot))
510 elif underlying_type.property_type == PropertyType.ARRAY: 557 elif underlying_type.property_type == PropertyType.ARRAY:
511 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( 558 return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
512 cpp_namespace,
513 underlying_type,
514 var, 559 var,
515 is_ptr) 560 is_ptr)
516 elif underlying_type.property_type.is_fundamental: 561 elif underlying_type.property_type.is_fundamental:
517 if is_ptr: 562 if is_ptr:
518 var = '*%s' % var 563 var = '*%s' % var
519 if underlying_type.property_type == PropertyType.STRING: 564 if underlying_type.property_type == PropertyType.STRING:
520 return 'new base::StringValue(%s)' % var 565 return 'new base::StringValue(%s)' % var
521 else: 566 else:
522 return 'new base::FundamentalValue(%s)' % var 567 return 'new base::FundamentalValue(%s)' % var
523 else: 568 else:
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 999
955 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' 1000 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
956 'Create(%(declaration_list)s) {') 1001 'Create(%(declaration_list)s) {')
957 .Append('scoped_ptr<base::ListValue> create_results(' 1002 .Append('scoped_ptr<base::ListValue> create_results('
958 'new base::ListValue());') 1003 'new base::ListValue());')
959 ) 1004 )
960 declaration_list = [] 1005 declaration_list = []
961 for param in params: 1006 for param in params:
962 declaration_list.append(cpp_util.GetParameterDeclaration( 1007 declaration_list.append(cpp_util.GetParameterDeclaration(
963 param, self._type_helper.GetCppType(param.type_))) 1008 param, self._type_helper.GetCppType(param.type_)))
964 c.Append('create_results->Append(%s);' % self._CreateValueFromType( 1009 c.Cblock(self._CreateValueFromType('create_results->Append(%s);',
965 cpp_namespace, 1010 param.name,
966 param.type_, 1011 param.type_,
967 param.unix_name)) 1012 param.unix_name))
968 c.Append('return create_results.Pass();') 1013 c.Append('return create_results.Pass();')
969 c.Eblock('}') 1014 c.Eblock('}')
970 c.Substitute({ 1015 c.Substitute({
971 'function_scope': ('%s::' % function_scope) if function_scope else '', 1016 'function_scope': ('%s::' % function_scope) if function_scope else '',
972 'declaration_list': ', '.join(declaration_list), 1017 'declaration_list': ', '.join(declaration_list),
973 'param_names': ', '.join(param.unix_name for param in params) 1018 'param_names': ', '.join(param.unix_name for param in params)
974 }) 1019 })
975 return c 1020 return c
976 1021
977 def _GenerateEventNameConstant(self, function_scope, event): 1022 def _GenerateEventNameConstant(self, function_scope, event):
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 if self._generate_error_messages: 1063 if self._generate_error_messages:
1019 params = list(params) + ['base::string16* error'] 1064 params = list(params) + ['base::string16* error']
1020 return ', '.join(str(p) for p in params) 1065 return ', '.join(str(p) for p in params)
1021 1066
1022 def _GenerateArgs(self, args): 1067 def _GenerateArgs(self, args):
1023 """Builds the argument list for a function, given an array of arguments. 1068 """Builds the argument list for a function, given an array of arguments.
1024 """ 1069 """
1025 if self._generate_error_messages: 1070 if self._generate_error_messages:
1026 args = list(args) + ['error'] 1071 args = list(args) + ['error']
1027 return ', '.join(str(a) for a in args) 1072 return ', '.join(str(a) for a in args)
OLDNEW
« no previous file with comments | « no previous file | tools/json_schema_compiler/test/arrays.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698