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

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
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.
490 underlying_item_type = self._type_helper.FollowRef(
not at google - send to devlin 2014/05/14 22:52:45 just |item_type| will be fine.
491 underlying_type.item_type)
492 if underlying_item_type.property_type == PropertyType.ENUM:
493 if is_ptr:
494 vardot = '(%s)->' % var
495 else:
496 vardot = '(%s).' % var
not at google - send to devlin 2014/05/14 22:52:45 how about just: vardot = '(%s)%s' % (var, '->' if
497
498 maybe_namespace = ''
499 if type_.item_type.property_type == PropertyType.REF:
500 maybe_namespace = '%s::' % underlying_item_type.namespace.unix_name
501
502 enum_list_var = '%s_list' % prop_name
not at google - send to devlin 2014/05/14 22:52:45 try to scope variable declarations inside braces.
wjywbs 2014/05/16 00:47:37 Do you mean something like this: enum_array_dict =
not at google - send to devlin 2014/05/16 17:13:47 I meant the C++ generated code. The python is fine
not at google - send to devlin 2014/05/16 17:36:34 Because i'm worried that somewhere up in the stack
wjywbs 2014/05/16 19:12:23 Done, but this makes the python code here more com
503 (c.Append('std::vector<std::string> %s;' % enum_list_var)
504 .Append('for (typename std::vector<%s>::const_iterator '
505 'it = %sbegin();'
506 % (self._type_helper.GetCppType(underlying_item_type), vardot))
507 .Sblock(' it != %send(); ++it) {' % vardot)
508 .Append('%s.push_back(%sToString(*it));' % (enum_list_var,
509 maybe_namespace))
not at google - send to devlin 2014/05/14 22:52:45 the reason why this logic was implemented in C++ b
not at google - send to devlin 2014/05/16 17:36:34 When I said "but note that" I mean add a comment f
wjywbs 2014/05/16 19:12:23 I added the comment above in the paragraph of "Enu
510 .Eblock('}'))
511
512 is_ptr = False
513 var = enum_list_var
not at google - send to devlin 2014/05/14 22:52:45 needs comments around here explaining what is goin
514
515 c.Append(code % self._CreateValueFromTypeInternal(type_, var, is_ptr))
not at google - send to devlin 2014/05/14 22:52:45 why "internal"? this separation seems mostly arbit
516 return c
517
518 def _CreateValueFromTypeInternal(self, type_, var, is_ptr):
485 underlying_type = self._type_helper.FollowRef(type_) 519 underlying_type = self._type_helper.FollowRef(type_)
486 if (underlying_type.property_type == PropertyType.CHOICES or 520 if (underlying_type.property_type == PropertyType.CHOICES or
487 underlying_type.property_type == PropertyType.OBJECT): 521 underlying_type.property_type == PropertyType.OBJECT):
488 if is_ptr: 522 if is_ptr:
489 return '(%s)->ToValue().release()' % var 523 return '(%s)->ToValue().release()' % var
490 else: 524 else:
491 return '(%s).ToValue().release()' % var 525 return '(%s).ToValue().release()' % var
492 elif (underlying_type.property_type == PropertyType.ANY or 526 elif (underlying_type.property_type == PropertyType.ANY or
493 underlying_type.property_type == PropertyType.FUNCTION): 527 underlying_type.property_type == PropertyType.FUNCTION):
494 if is_ptr: 528 if is_ptr:
495 vardot = '(%s)->' % var 529 vardot = '(%s)->' % var
496 else: 530 else:
497 vardot = '(%s).' % var 531 vardot = '(%s).' % var
498 return '%sDeepCopy()' % vardot 532 return '%sDeepCopy()' % vardot
499 elif underlying_type.property_type == PropertyType.ENUM: 533 elif underlying_type.property_type == PropertyType.ENUM:
500 classname = cpp_util.Classname(schema_util.StripNamespace( 534 classname = cpp_util.Classname(schema_util.StripNamespace(
501 underlying_type.name)) 535 underlying_type.name))
502 return 'new base::StringValue(%sToString(%s))' % (classname, var) 536 return 'new base::StringValue(%sToString(%s))' % (classname, var)
503 elif underlying_type.property_type == PropertyType.BINARY: 537 elif underlying_type.property_type == PropertyType.BINARY:
504 if is_ptr: 538 if is_ptr:
505 vardot = var + '->' 539 vardot = var + '->'
506 else: 540 else:
507 vardot = var + '.' 541 vardot = var + '.'
508 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % 542 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
509 (vardot, vardot)) 543 (vardot, vardot))
510 elif underlying_type.property_type == PropertyType.ARRAY: 544 elif underlying_type.property_type == PropertyType.ARRAY:
511 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( 545 return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
512 cpp_namespace,
513 underlying_type,
514 var, 546 var,
515 is_ptr) 547 is_ptr)
516 elif underlying_type.property_type.is_fundamental: 548 elif underlying_type.property_type.is_fundamental:
517 if is_ptr: 549 if is_ptr:
518 var = '*%s' % var 550 var = '*%s' % var
519 if underlying_type.property_type == PropertyType.STRING: 551 if underlying_type.property_type == PropertyType.STRING:
520 return 'new base::StringValue(%s)' % var 552 return 'new base::StringValue(%s)' % var
521 else: 553 else:
522 return 'new base::FundamentalValue(%s)' % var 554 return 'new base::FundamentalValue(%s)' % var
523 else: 555 else:
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 986
955 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' 987 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
956 'Create(%(declaration_list)s) {') 988 'Create(%(declaration_list)s) {')
957 .Append('scoped_ptr<base::ListValue> create_results(' 989 .Append('scoped_ptr<base::ListValue> create_results('
958 'new base::ListValue());') 990 'new base::ListValue());')
959 ) 991 )
960 declaration_list = [] 992 declaration_list = []
961 for param in params: 993 for param in params:
962 declaration_list.append(cpp_util.GetParameterDeclaration( 994 declaration_list.append(cpp_util.GetParameterDeclaration(
963 param, self._type_helper.GetCppType(param.type_))) 995 param, self._type_helper.GetCppType(param.type_)))
964 c.Append('create_results->Append(%s);' % self._CreateValueFromType( 996 c.Cblock(self._CreateValueFromType('create_results->Append(%s);',
965 cpp_namespace, 997 param.name,
966 param.type_, 998 param.type_,
967 param.unix_name)) 999 param.unix_name))
968 c.Append('return create_results.Pass();') 1000 c.Append('return create_results.Pass();')
969 c.Eblock('}') 1001 c.Eblock('}')
970 c.Substitute({ 1002 c.Substitute({
971 'function_scope': ('%s::' % function_scope) if function_scope else '', 1003 'function_scope': ('%s::' % function_scope) if function_scope else '',
972 'declaration_list': ', '.join(declaration_list), 1004 'declaration_list': ', '.join(declaration_list),
973 'param_names': ', '.join(param.unix_name for param in params) 1005 'param_names': ', '.join(param.unix_name for param in params)
974 }) 1006 })
975 return c 1007 return c
976 1008
977 def _GenerateEventNameConstant(self, function_scope, event): 1009 def _GenerateEventNameConstant(self, function_scope, event):
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 if self._generate_error_messages: 1050 if self._generate_error_messages:
1019 params = list(params) + ['base::string16* error'] 1051 params = list(params) + ['base::string16* error']
1020 return ', '.join(str(p) for p in params) 1052 return ', '.join(str(p) for p in params)
1021 1053
1022 def _GenerateArgs(self, args): 1054 def _GenerateArgs(self, args):
1023 """Builds the argument list for a function, given an array of arguments. 1055 """Builds the argument list for a function, given an array of arguments.
1024 """ 1056 """
1025 if self._generate_error_messages: 1057 if self._generate_error_messages:
1026 args = list(args) + ['error'] 1058 args = list(args) + ['error']
1027 return ', '.join(str(a) for a in args) 1059 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') | tools/json_schema_compiler/test/arrays_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698