Index: tools/json_schema_compiler/cc_generator.py |
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py |
index d0c57decdf8deabcf78dd63adb105fc611407945..213f98f8c3c8ff433564a6b1a6064561005f4989 100644 |
--- a/tools/json_schema_compiler/cc_generator.py |
+++ b/tools/json_schema_compiler/cc_generator.py |
@@ -5,6 +5,7 @@ |
from model import PropertyType |
import code |
import cpp_util |
+import util_cc_helper |
class CCGenerator(object): |
"""A .cc generator for a namespace. |
@@ -14,6 +15,8 @@ class CCGenerator(object): |
self._namespace = namespace |
self._target_namespace = ( |
self._cpp_type_generator.GetCppNamespaceName(self._namespace)) |
+ self._util_cc_helper = ( |
+ util_cc_helper.UtilCCHelper(self._cpp_type_generator)) |
def Generate(self): |
"""Generates a code.Code object with the .cc for a single namespace. |
@@ -23,11 +26,19 @@ class CCGenerator(object): |
.Append() |
.Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
.Append() |
- .Append('#include "tools/json_schema_compiler/util.h"') |
+ .Append(self._util_cc_helper.GetIncludePath()) |
.Append('#include "%s/%s.h"' % |
- (self._namespace.source_file_dir, self._target_namespace)) |
- .Append() |
- .Concat(self._cpp_type_generator.GetCppNamespaceStart()) |
+ (self._namespace.source_file_dir, self._namespace.name)) |
+ ) |
+ includes = self._cpp_type_generator.GenerateIncludes() |
+ if not includes.IsEmpty(): |
+ (c.Concat(includes) |
+ .Append() |
+ ) |
+ |
+ (c.Append() |
+ .Concat(self._cpp_type_generator.GetRootNamespaceStart()) |
+ .Concat(self._cpp_type_generator.GetNamespaceStart()) |
.Append() |
.Append('//') |
.Append('// Types') |
@@ -35,7 +46,7 @@ class CCGenerator(object): |
.Append() |
) |
for type_ in self._namespace.types.values(): |
- (c.Concat(self._GenerateType(type_)) |
+ (c.Concat(self._GenerateType(type_.name, type_)) |
.Append() |
) |
(c.Append('//') |
@@ -47,152 +58,187 @@ class CCGenerator(object): |
(c.Concat(self._GenerateFunction(function)) |
.Append() |
) |
- (c.Concat(self._cpp_type_generator.GetCppNamespaceEnd()) |
+ (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) |
+ .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) |
.Append() |
) |
# TODO(calamity): Events |
return c |
- def _GenerateType(self, type_): |
+ def _GenerateType(self, cpp_namespace, type_, serializable=True): |
"""Generates the function definitions for a type. |
""" |
+ classname = cpp_util.Classname(type_.name) |
c = code.Code() |
- (c.Append('%(classname)s::%(classname)s() {}') |
- .Append('%(classname)s::~%(classname)s() {}') |
+ (c.Append('%(namespace)s::%(classname)s() {}') |
+ .Append('%(namespace)s::~%(classname)s() {}') |
.Append() |
) |
- c.Substitute({'classname': type_.name}) |
+ c.Substitute({'classname': classname, 'namespace': cpp_namespace}) |
- c.Concat(self._GenerateTypePopulate(type_)) |
+ c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) |
c.Append() |
- # TODO(calamity): deal with non-serializable |
- c.Concat(self._GenerateTypeTovalue(type_)) |
+ if serializable: |
+ c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) |
c.Append() |
return c |
- def _GenerateTypePopulate(self, type_): |
+ def _GenerateTypePopulate(self, cpp_namespace, type_): |
"""Generates the function for populating a type given a pointer to it. |
""" |
+ classname = cpp_util.Classname(type_.name) |
c = code.Code() |
(c.Append('// static') |
- .Sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {') |
+ .Sblock('bool %(namespace)s::Populate' |
+ '(const Value& value, %(name)s* out) {') |
.Append('if (!value.IsType(Value::TYPE_DICTIONARY))') |
.Append(' return false;') |
.Append('const DictionaryValue* dict = ' |
'static_cast<const DictionaryValue*>(&value);') |
.Append() |
) |
- c.Substitute({'name': type_.name}) |
+ c.Substitute({'namespace': cpp_namespace, 'name': classname}) |
# TODO(calamity): this handle single PropertyType.REF properties. |
# add ALL the types |
for prop in type_.properties.values(): |
- sub = {'name': prop.name} |
- if prop.type_ == PropertyType.ARRAY: |
- if prop.item_type.type_ == PropertyType.REF: |
- if prop.optional: |
- (c.Append('if (!json_schema_compiler::util::' |
- 'GetOptionalTypes<%(type)s>(*dict,') |
- .Append(' "%(name)s", &out->%(name)s))') |
- .Append(' return false;') |
- ) |
- else: |
- (c.Append('if (!json_schema_compiler::util::' |
- 'GetTypes<%(type)s>(*dict,') |
- .Append(' "%(name)s", &out->%(name)s))') |
- .Append(' return false;') |
- ) |
- sub['type'] = self._cpp_type_generator.GetType(prop.item_type, |
- pad_for_generics=True) |
- elif prop.item_type.type_ == PropertyType.STRING: |
- if prop.optional: |
- (c.Append('if (!json_schema_compiler::util::GetOptionalStrings' |
- '(*dict, "%(name)s", &out->%(name)s))') |
- .Append(' return false;') |
- ) |
- else: |
- (c.Append('if (!json_schema_compiler::util::GetStrings' |
- '(*dict, "%(name)s", &out->%(name)s))') |
- .Append(' return false;') |
- ) |
- else: |
- raise NotImplementedError(prop.item_type.type_) |
- elif prop.type_.is_fundamental: |
- c.Append('if (!dict->%s)' % |
- cpp_util.GetFundamentalValue(prop, '&out->%s' % prop.name)) |
- c.Append(' return false;') |
- else: |
- raise NotImplementedError(prop.type_) |
- c.Substitute(sub) |
+ c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
(c.Append('return true;') |
.Eblock('}') |
not at google - send to devlin
2012/02/08 05:02:08
indent 2 spaces. I can see why you might have done
calamity
2012/02/08 07:01:18
Done.
|
) |
return c |
- def _GenerateTypeTovalue(self, type_): |
+ def _GenerateTypePopulateProperty(self, prop, src, dst): |
not at google - send to devlin
2012/02/08 05:02:08
As discussed, most of this code will be replaced w
calamity
2012/02/08 07:01:18
Done.
|
+ """Generate the code to populate a single property. |
+ |
+ src: DictionaryValue* |
+ dst: Type* |
+ """ |
+ c = code.Code() |
+ dst_member = dst + '->' + prop.unix_name |
+ if prop.type_ == PropertyType.ARRAY: |
+ (c.Append('if (!%s)' % |
+ self._util_cc_helper.GetArray(prop, src, prop.name, dst_member)) |
+ .Append(' return false;') |
+ ) |
+ elif prop.type_ == PropertyType.CHOICES: |
+ if prop.optional: |
+ c.Append('%(dst)s_type = %(enum)s::NONE') |
+ for choice in self._cpp_type_generator.ExpandedChoicesInParams([prop]): |
+ dst_member = dst + '->' + choice.unix_name |
+ if choice.type_ == PropertyType.ARRAY: |
+ (c.Append('if (!%s)' % |
+ self._util_cc_helper.GetArray( |
+ choice, src, choice.name,dst_member)) |
+ .Append(' return false;') |
+ ) |
+ else: |
+ (c.Sblock('{') |
+ .Append('%(type)s %(name)s_temp;') |
+ .Append('if (%s) {' % self._GeneratePopulatePropertyFunctionCall( |
+ choice, src, '&%s_temp' % choice.unix_name)) |
+ .Append(' out->%(name)s.reset(new %(type)s(%(name)s_temp));') |
+ .Append(' %(dst)s = %(enum)s;') |
+ .Append('}') |
+ .Eblock('}') |
+ ) |
+ c.Substitute({ |
+ 'src': src, |
+ 'dst': dst + '->%s_type' % prop.unix_name, |
+ 'name': choice.unix_name, |
+ 'enum': self._cpp_type_generator.GetChoiceEnum(prop, choice.type_), |
+ 'type': self._cpp_type_generator.GetType(choice) |
+ }) |
+ else: |
+ if prop.optional: |
+ if prop.type_.is_fundamental: |
+ (c.Sblock('{') |
+ .Append('%(type)s %(name)s_temp;') |
+ .Append('if (%s)' % self._GeneratePopulatePropertyFunctionCall( |
+ prop, src, '&%s_temp' % prop.unix_name)) |
+ .Append(' out->%(name)s.reset(new %(type)s(%(name)s_temp));') |
+ .Eblock('}') |
+ ) |
+ else: |
+ raise NotImplementedError('Optional %s not implemented' % prop.type_) |
+ else: |
+ (c.Append('if (!%s)' % |
+ self._GeneratePopulatePropertyFunctionCall( |
+ prop, src, '&' + dst_member)) |
+ .Append(' return false;') |
+ ) |
+ c.Substitute({ |
+ 'src': src, 'dst': dst_member, 'name': prop.unix_name, |
+ 'type': self._cpp_type_generator.GetType(prop) |
not at google - send to devlin
2012/02/08 05:02:08
too much indentation, and spread out each member o
calamity
2012/02/08 07:01:18
Done.
|
+ }) |
+ return c |
not at google - send to devlin
2012/02/08 05:02:08
Can delay substituting src until the end?
c.Subst
calamity
2012/02/08 07:01:18
Done.
not at google - send to devlin
2012/02/09 02:49:36
Not done?
Also you have the same thing above now,
|
+ |
+ def _GeneratePopulatePropertyFunctionCall(self, prop, src, dst): |
+ """Generates the function call that populates the given property. |
+ |
+ src: DictionaryValue* |
+ dst: Property* or scoped_ptr<Property> |
+ """ |
+ if prop.type_.is_fundamental: |
+ populate_line = cpp_util.GetFundamentalValue( |
+ prop, src, prop.name, dst) |
+ elif prop.type_ in (PropertyType.REF, PropertyType.OBJECT): |
+ populate_line = '%(type)s::Populate(*%(src)s, %(dst)s)' |
+ else: |
+ raise NotImplementedError('%s populate is not implemented' % |
+ prop.type_) |
+ return populate_line |
+ |
+ |
+ def _GenerateTypeToValue(self, cpp_namespace, type_): |
"""Generates a function that serializes the type into a |DictionaryValue|. |
""" |
c = code.Code() |
- (c.Sblock('DictionaryValue* %s::ToValue() const {' % type_.name) |
- .Append('DictionaryValue* value = new DictionaryValue();') |
- .Append() |
+ (c.Sblock('DictionaryValue* %s::ToValue() const {' % cpp_namespace) |
+ .Append('DictionaryValue* value = new DictionaryValue();') |
+ .Append() |
) |
- name = type_.name.lower() |
for prop in type_.properties.values(): |
- prop_name = name + '_' + prop.name if name else prop.name |
- this_var = prop.name |
- c.Concat(self._CreateValueFromProperty(prop_name, prop, this_var)) |
+ c.Concat(self._CreateValueFromProperty(prop, prop.unix_name, 'value')) |
(c.Append() |
.Append('return value;') |
.Eblock('}') |
) |
return c |
- # TODO(calamity): object and choices prop types |
- def _CreateValueFromProperty(self, name, prop, var): |
+ def _CreateValueFromProperty(self, prop, var, dst): |
"""Generates code to serialize a single property in a type. |
+ |
+ prop: Property to create from |
+ var: variable with value to create from |
""" |
c = code.Code() |
- if prop.type_.is_fundamental: |
- c.Append('Value* %s_value = %s;' % |
- (name, cpp_util.CreateFundamentalValue(prop, var))) |
- elif prop.type_ == PropertyType.ARRAY: |
- if prop.item_type.type_ == PropertyType.STRING: |
- if prop.optional: |
- c.Append('json_schema_compiler::util::' |
- 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name)) |
- else: |
- c.Append('json_schema_compiler::util::' |
- 'SetStrings(%s, "%s", value);' % (var, prop.name)) |
- else: |
- item_name = name + '_single' |
- (c.Append('ListValue* %(name)s_value = new ListValue();') |
- .Append('for (%(it_type)s::iterator it = %(var)s->begin();') |
- .Sblock(' it != %(var)s->end(); ++it) {') |
- .Concat(self._CreateValueFromProperty(item_name, prop.item_type, |
- '*it')) |
- .Append('%(name)s_value->Append(%(prop_val)s_value);') |
- .Eblock('}') |
- ) |
- c.Substitute( |
- {'it_type': self._cpp_type_generator.GetType(prop), |
- 'name': name, 'var': var, 'prop_val': item_name}) |
- elif prop.type_ == PropertyType.REF: |
- c.Append('Value* %s_value = %s.ToValue();' % (name, var)) |
+ if prop.optional: |
+ c.Sblock('if (%s.get())' % var) |
+ if prop.type_ == PropertyType.ARRAY: |
+ c.Append('%s;' % self._util_cc_helper.SetArray(prop, var, prop.name, dst)) |
else: |
- raise NotImplementedError |
+ c.Append('%s->SetWithoutPathExpansion("%s", %s);' % |
+ (dst, prop.name, cpp_util.CreateValueFromSingleProperty(prop, var))) |
return c |
def _GenerateFunction(self, function): |
"""Generates the definitions for function structs. |
""" |
- classname = cpp_util.CppName(function.name) |
+ classname = cpp_util.Classname(function.name) |
c = code.Code() |
# Params::Populate function |
if function.params: |
+ for param in function.params: |
+ if param.type_ == PropertyType.OBJECT: |
+ param_namespace = '%s::Params::%s' % (classname, |
+ cpp_util.Classname(param.name)) |
+ c.Concat( |
+ self._GenerateType(param_namespace, param, serializable=False)) |
+ c.Append() |
(c.Append('%(name)s::Params::Params() {}') |
.Append('%(name)s::Params::~Params() {}') |
.Append() |
@@ -207,88 +253,191 @@ class CCGenerator(object): |
return c |
+ def _GenerateParamsCheck(self, function, var): |
+ """Generates a check for the correct number of arguments when creating Params. |
+ """ |
+ c = code.Code() |
+ num_optional = 0 |
+ num_required = 0 |
+ for param in function.params: |
+ if param.optional: |
+ num_optional += 1 |
+ else: |
+ num_required += 1 |
+ if num_optional: |
+ (c.Append('if (%(var)s.GetSize() > %(total)d)') |
+ .Append(' return scoped_ptr<Params>();') |
+ ) |
+ if num_required: |
+ (c.Append('if (%(var)s.GetSize() < %(req)d)') |
+ .Append(' return scoped_ptr<Params>();') |
+ ) |
+ c.Substitute({ |
+ 'var': var, |
+ 'req': num_required, |
+ 'total': num_optional + num_required, |
+ }) |
+ return c |
not at google - send to devlin
2012/02/08 05:02:08
y u no write it like I wrote?
I can see why you d
calamity
2012/02/08 07:01:18
Wups, my bad. Note that you can't do args.GetSize(
not at google - send to devlin
2012/02/09 02:49:36
Hah.
|
+ |
def _GenerateFunctionParamsCreate(self, function): |
"""Generate function to create an instance of Params given a pointer. |
""" |
- classname = cpp_util.CppName(function.name) |
+ classname = cpp_util.Classname(function.name) |
c = code.Code() |
(c.Append('// static') |
.Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' |
'(const ListValue& args) {') |
- .Append('if (args.GetSize() != %d)' % len(function.params)) |
- .Append(' return scoped_ptr<Params>();') |
- .Append() |
+ .Concat(self._GenerateParamsCheck(function, 'args')) |
.Append('scoped_ptr<Params> params(new Params());') |
) |
c.Substitute({'classname': classname}) |
- # TODO(calamity): generalize, needs to move to function to do populates for |
- # wider variety of args |
for i, param in enumerate(function.params): |
- sub = {'name': param.name, 'pos': i} |
+ dst = 'params->' + param.unix_name |
+ if param.optional: |
+ return_line = ' return params.Pass();' |
+ else: |
+ return_line = ' return scoped_ptr<Params>();' |
c.Append() |
- # TODO(calamity): Make valid for not just objects |
- c.Append('DictionaryValue* %(name)s_param = NULL;') |
- c.Append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))') |
- c.Append(' return scoped_ptr<Params>();') |
- if param.type_ == PropertyType.REF: |
- c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' |
- '¶ms->%(name)s))') |
- c.Append(' return scoped_ptr<Params>();') |
- sub['ctype'] = self._cpp_type_generator.GetType(param) |
- elif param.type_.is_fundamental: |
- raise NotImplementedError('Fundamental types are unimplemented') |
- elif param.type_ == PropertyType.OBJECT: |
- c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' |
- '¶ms->%(name)s))') |
- c.Append(' return scoped_ptr<Params>();') |
- sub['ctype'] = self._cpp_type_generator.GetType(param) |
+ param_var = param.unix_name + '_param' |
+ if param.type_ == PropertyType.ARRAY: |
+ (c.Append('ListValue* %(var)s = NULL;') |
+ .Append('if (!args.GetList(%(index)d, &%(var)s))') |
+ .Append(return_line) |
+ .Append('if (!%s)' % self._util_cc_helper.GetArrayFromList( |
+ param, param_var, dst)) |
+ .Append(return_line) |
+ ) |
+ c.Substitute({'var': param_var, 'index': i}) |
elif param.type_ == PropertyType.CHOICES: |
- raise NotImplementedError('Choices is unimplemented') |
+ c.Concat(self._GeneratePopulateChoices(param, 'args', i, return_line)) |
else: |
- raise NotImplementedError(param.type_) |
- c.Substitute(sub) |
- c.Append() |
- c.Append('return params.Pass();') |
- c.Eblock('}') |
+ if param.optional: |
+ dst = dst + '.get()' |
+ else: |
+ dst = '&' + dst |
+ if param.type_ in (PropertyType.REF, PropertyType.OBJECT): |
+ (c.Append('DictionaryValue* %s = NULL;' % param_var) |
+ .Append('if (!args.GetDictionary(%d, &%s))' % (i, param_var)) |
+ .Append(return_line) |
+ ) |
+ if param.optional: |
+ c.Append('params->%s.reset(new %s());' % |
+ (param.unix_name, cpp_util.Classname(param.name))) |
+ (c.Append('if (!%(ctype)s::Populate(*%(var)s, %(dst)s))' % { |
+ 'var': param_var, 'dst': dst, |
+ 'ctype': self._cpp_type_generator.GetType(param) |
+ }) |
+ .Append(return_line) |
+ ) |
+ elif param.type_.is_fundamental: |
+ (c.Append( |
+ 'if (!%s)' % cpp_util.GetValueFromList(param, 'args', i, dst)) |
+ .Append(return_line) |
+ ) |
+ (c.Append() |
+ .Append('return params.Pass();') |
+ .Eblock('}') |
+ ) |
return c |
+ def _GeneratePopulateChoices(self, param, src, index, return_line): |
not at google - send to devlin
2012/02/08 05:02:08
confused by the use of the word "populate" here bu
calamity
2012/02/08 07:01:18
Now it populates. Woo.
|
+ """Generates the code to populate a PropertyType.CHOICES parameter. |
+ |
+ src: ListValue* |
+ index: index of the ListValue the parameter is in |
+ return_line: return line to be used if the choices parameter is not present |
+ """ |
not at google - send to devlin
2012/02/08 05:02:08
as discussed, refactoring to do here.
calamity
2012/02/08 07:01:18
Done.
|
+ c = code.Code() |
+ type_var = 'params->%s_type' % param.unix_name |
+ if param.optional: |
+ type_var = '*' + type_var |
+ c.Append('%s = %s;' % |
+ (type_var, self._cpp_type_generator.GetChoiceEnum(param, None))) |
+ value_var = param.unix_name + '_value' |
not at google - send to devlin
2012/02/08 05:02:08
Refactoring being making this method accept the na
calamity
2012/02/08 07:01:18
Done.
|
+ c.Append('Value* %(value)s = NULL;') |
+ c.Append('if (!%(src)s.Get(%(index)s, &%(value)s))') |
+ c.Append(return_line) |
not at google - send to devlin
2012/02/08 05:02:08
This means that optional parameters can only appea
calamity
2012/02/08 07:01:18
Couldn't figure a case where requires args happen
|
+ c.Sblock('switch (%(value)s->GetType()) {') |
+ c.Substitute({'src': src, 'index': index, 'value': value_var}) |
not at google - send to devlin
2012/02/08 05:02:08
IMO try to put substitutions at the end of these c
calamity
2012/02/08 07:01:18
Done. I'm wary of someone else changing a value in
|
+ for choice in self._cpp_type_generator.ExpandedChoicesInParams([param]): |
+ if choice.type_.is_fundamental: |
+ c.Sblock('case %s: {' % { |
+ PropertyType.STRING: 'Value::TYPE_STRING', |
+ PropertyType.INTEGER: 'Value::TYPE_INTEGER', |
+ PropertyType.BOOLEAN: 'Value::TYPE_BOOLEAN', |
+ PropertyType.DOUBLE: 'Value::TYPE_DOUBLE' |
+ }[choice.type_]) |
+ |
+ dst = 'params->%s.get()' % choice.unix_name |
+ (c.Append(' %(type)s = %(enum)s;') |
not at google - send to devlin
2012/02/08 05:02:08
why the extra spaces before %(type)s?
calamity
2012/02/08 07:01:18
Done.
|
+ .Append('%s;' % |
+ cpp_util.GetAsFundamentalValue(choice, value_var, dst)) |
+ .Append('break;') |
+ .Eblock('}') |
+ ) |
+ elif choice.type_ == PropertyType.ARRAY: |
+ dst = 'params->%s' % choice.unix_name |
+ (c.Sblock('case Value::TYPE_LIST: {') |
+ .Append('%(type)s = %(enum)s;') |
+ .Append('if (!%s)' % self._util_cc_helper.GetArrayFromList( |
+ choice, 'static_cast<ListValue*>(%s)' % value_var, dst)) |
+ .Append(' return scoped_ptr<Params>();') |
+ .Append('break;') |
+ .Eblock('}') |
+ ) |
+ else: |
+ raise NotImplementedError(choice.type_) |
+ c.Substitute({'type': type_var, |
+ 'enum': self._cpp_type_generator.GetChoiceEnum(param, choice.type_)}) |
not at google - send to devlin
2012/02/08 05:02:08
I don't know whether enum refers to the type or th
calamity
2012/02/08 07:01:18
Done.
|
+ if not param.optional: |
+ (c.Append('default:') |
+ .Append(' return scoped_ptr<Params>();') |
+ ) |
+ c.Eblock('}') |
+ return c |
+ |
def _GenerateFunctionResultCreate(self, function): |
"""Generate function to create a Result given the return value. |
""" |
- classname = cpp_util.CppName(function.name) |
+ classname = cpp_util.Classname(function.name) |
c = code.Code() |
c.Append('// static') |
- param = function.callback.param |
- arg = '' |
- if param: |
- if param.type_ == PropertyType.REF: |
- arg = 'const %(type)s& %(name)s' |
- else: |
- arg = 'const %(type)s %(name)s' |
- arg = arg % { |
- 'type': self._cpp_type_generator.GetType(param), |
- 'name': param.name |
- } |
- c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {') |
- sub = {'classname': classname, 'arg': arg} |
- # TODO(calamity): Choices |
- if not param: |
- c.Append('return Value::CreateNullValue();') |
+ params = function.callback.params |
+ |
+ if not params: |
+ (c.Append('Value* %s::Result::Create() {' % classname) |
+ .Append(' return Value::CreateNullValue();') |
+ .Append('}') |
+ ) |
else: |
- sub['argname'] = param.name |
- if param.type_.is_fundamental: |
- c.Append('return %s;' % |
- cpp_util.CreateFundamentalValue(param, param.name)) |
- elif param.type_ == PropertyType.REF: |
- c.Append('return %(argname)s.ToValue();') |
- elif param.type_ == PropertyType.OBJECT: |
- raise NotImplementedError('Objects not implemented') |
- elif param.type_ == PropertyType.ARRAY: |
- raise NotImplementedError('Arrays not implemented') |
- else: |
- raise NotImplementedError(param.type_) |
- c.Substitute(sub) |
- c.Eblock('}') |
+ # If there is a single parameter, this is straightforward. However, if |
+ # the callback parameter is of 'choices', this generates a Create method |
+ # for each choice. This works because only 1 choice can be returned at a |
+ # time. |
+ for param in self._cpp_type_generator.ExpandedChoicesInParams(params): |
+ if param.type_ == PropertyType.REF: |
+ arg = 'const %(type)s& %(name)s' |
+ else: |
+ arg = 'const %(type)s %(name)s' |
+ arg %= { |
+ 'type': self._cpp_type_generator.GetType(param, wrap_optional=True), |
+ 'name': param.unix_name, |
+ } |
+ if param and param.description: |
+ c.Comment(param.description) |
+ c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {') |
+ if param.type_ == PropertyType.ARRAY: |
+ (c.Append('ListValue* value = new ListValue();') |
+ .Append('%s;' % self._util_cc_helper.SetArrayToList(param, |
+ param.unix_name, 'value')) |
+ .Append('return value;') |
+ ) |
+ else: |
+ c.Append('return %s;' % cpp_util.CreateValueFromSingleProperty(param, |
+ param.unix_name)) |
+ c.Substitute({'classname': classname, 'arg': arg}) |
+ c.Eblock('}') |
+ |
return c |