Chromium Code Reviews| 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 cc9214e31342d93a7189605222c9d128cb0fbea5..f261af7bf7e24f7c112542fc0e9d4b9f9d3b3034 100644 |
| --- a/tools/json_schema_compiler/cc_generator.py |
| +++ b/tools/json_schema_compiler/cc_generator.py |
| @@ -72,19 +72,21 @@ class CCGenerator(object): |
| # TODO(calamity): Events |
| return c |
| - def _GenerateType(self, cpp_namespace, type_, serializable=True): |
| + def _GenerateType(self, cpp_namespace, type_): |
| """Generates the function definitions for a type. |
| """ |
| classname = cpp_util.Classname(type_.name) |
| c = code.Code() |
| - (c.Append('%(namespace)s::%(classname)s() {}') |
| + (c.Concat(self._GeneratePropertyFunctions( |
| + cpp_namespace, type_.properties.values())) |
| + .Append('%(namespace)s::%(classname)s() {}') |
| .Append('%(namespace)s::~%(classname)s() {}') |
| .Append() |
| .Concat(self._GenerateTypePopulate(cpp_namespace, type_)) |
| .Append() |
| ) |
| - if serializable: |
| + if type_.serializable: |
| c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) |
| c.Append() |
| c.Substitute({'classname': classname, 'namespace': cpp_namespace}) |
| @@ -129,7 +131,7 @@ class CCGenerator(object): |
| 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {' |
| ) |
| .Concat(self._GeneratePopulatePropertyFromValue( |
| - prop, value_var, 'out', 'false')) |
| + prop, value_var, dst, 'false')) |
| .Eblock('}') |
| ) |
| else: |
| @@ -137,7 +139,7 @@ class CCGenerator(object): |
| 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') |
| .Append(' return false;') |
| .Concat(self._GeneratePopulatePropertyFromValue( |
| - prop, value_var, 'out', 'false')) |
| + prop, value_var, dst, 'false')) |
| ) |
| c.Append() |
| c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) |
| @@ -167,34 +169,17 @@ class CCGenerator(object): |
| var: variable with value to create from |
| """ |
| c = code.Code() |
| - if prop.type_ == PropertyType.ENUM: |
| - c.Sblock('switch (%s) {' % var) |
| - for enum_value in prop.enum_values: |
| - (c.Append('case %s: {' % |
| - self._cpp_type_generator.GetEnumValue(prop, enum_value)) |
| - .Append(' %s->SetWithoutPathExpansion(' |
| - '"%s", Value::CreateStringValue("%s"));' % |
| - (dst, prop.name, enum_value)) |
| - .Append(' break;') |
| - .Append('}') |
| - ) |
| - # C++ requires the entire enum to be handled by a switch. |
| - if prop.optional: |
| - (c.Append('case %s: {' % |
| - self._cpp_type_generator.GetEnumNoneValue(prop)) |
| - .Append(' break;') |
| - .Append('}') |
| - ) |
| - c.Eblock('}') |
| - else: |
| - if prop.optional: |
| - c.Sblock('if (%s.get())' % var) |
| - if prop.type_ == PropertyType.ARRAY: |
| - c.Append('%s;' % self._util_cc_helper.PopulateDictionaryFromArray( |
| - prop, var, prop.name, dst)) |
| + if prop.optional: |
| + if prop.type_ == PropertyType.ENUM: |
| + c.Sblock('if (%s != %s)' % |
| + (var, self._cpp_type_generator.GetEnumNoneValue(prop))) |
| else: |
| - c.Append('%s->SetWithoutPathExpansion("%s", %s);' % |
| - (dst, prop.name, cpp_util.CreateValueFromSingleProperty(prop, var))) |
| + c.Sblock('if (%s.get())' % var) |
|
not at google - send to devlin
2012/02/24 03:53:05
will this work for CHOICES?
calamity
2012/02/24 15:10:40
No. There is currently no facility for turning a C
|
| + c.Append('%s->SetWithoutPathExpansion("%s", %s);' % ( |
| + dst, |
| + prop.name, |
| + cpp_util.CreateValueFromSingleProperty( |
| + prop, var, self._util_cc_helper))) |
| return c |
| def _GenerateFunction(self, function): |
| @@ -205,13 +190,8 @@ class CCGenerator(object): |
| # 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.Concat(self._GeneratePropertyFunctions(classname + '::Params', |
| + function.params)) |
| (c.Append('%(name)s::Params::Params() {}') |
| .Append('%(name)s::Params::~Params() {}') |
| .Append() |
| @@ -220,12 +200,41 @@ class CCGenerator(object): |
| ) |
| # Result::Create function |
| - c.Concat(self._GenerateFunctionResultCreate(function)) |
| + if function.callback: |
| + c.Concat(self._GenerateFunctionResultCreate(function)) |
| c.Substitute({'name': classname}) |
| return c |
| + def _GenerateCreateEnumValue(self, cpp_namespace, prop): |
| + """Generates a function that returns the Value representation of an enum. |
|
Yoyo Zhou
2012/02/24 04:02:22
Should this mention that they are string values?
calamity
2012/02/24 15:10:40
Done.
|
| + """ |
| + c = code.Code() |
| + c.Append('// static') |
| + c.Sblock('scoped_ptr<Value> %(namespace)s::CreateEnumValue(%(arg)s) {') |
|
not at google - send to devlin
2012/02/24 03:53:05
call string substitution same name as variable, so
calamity
2012/02/24 15:10:40
Done.
|
| + c.Sblock('switch (%s) {' % prop.unix_name) |
| + if prop.optional: |
| + (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) |
| + .Append(' return scoped_ptr<Value>();') |
| + .Append('}') |
| + ) |
| + for enum_value in prop.enum_values: |
| + (c.Append('case %s: {' % |
| + self._cpp_type_generator.GetEnumValue(prop, enum_value)) |
| + .Append(' return scoped_ptr<Value>(Value::CreateStringValue("%s"));' % |
| + enum_value) |
| + .Append('}') |
| + ) |
| + c.Eblock('}') |
| + c.Eblock('}') |
| + c.Substitute({ |
| + 'namespace': cpp_namespace, |
| + 'arg': cpp_util.GetParameterDeclaration( |
| + prop, self._cpp_type_generator.GetType(prop)) |
| + }) |
| + return c |
| + |
| def _GenerateParamsCheck(self, function, var): |
| """Generates a check for the correct number of arguments when creating |
| Params. |
| @@ -310,9 +319,10 @@ class CCGenerator(object): |
| check_type: if true, will check if |value_var| is the correct Value::Type |
| """ |
| c = code.Code() |
| + c.Append('// %s' % prop.name) |
|
not at google - send to devlin
2012/02/24 03:53:05
2 spaces between the // and the %s (sorry... yeah,
calamity
2012/02/24 15:10:40
Removed. This made the code uglier. I must have le
|
| c.Sblock('{') |
| - if check_type: |
| + if check_type and prop.type_ != PropertyType.CHOICES: |
| (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') |
| .Append(' return %(failure_value)s;') |
| ) |
| @@ -358,7 +368,23 @@ class CCGenerator(object): |
| .Append(' return %(failure_value)s;') |
| ) |
| elif prop.type_ == PropertyType.CHOICES: |
| - return self._GeneratePopulateChoices(prop, value_var, dst, failure_value) |
| + type_var = '%(dst)s->%(name)s_type' |
| + c.Sblock('switch (%(value_var)s->GetType()) {') |
| + for choice in self._cpp_type_generator.GetExpandedChoicesInParams([prop]): |
| + (c.Sblock('case %s: {' % cpp_util.GetValueType(choice)) |
| + .Concat(self._GeneratePopulatePropertyFromValue( |
| + choice, value_var, dst, failure_value, check_type=False)) |
| + .Append('%s = %s;' % |
| + (type_var, |
| + self._cpp_type_generator.GetEnumValue( |
| + prop, choice.type_.name))) |
| + .Append('break;') |
| + .Eblock('}') |
| + ) |
| + (c.Append('default:') |
| + .Append(' return %(failure_value)s;') |
| + ) |
| + c.Eblock('}') |
| elif prop.type_ == PropertyType.ENUM: |
| (c.Append('std::string enum_temp;') |
| .Append('if (!%(value_var)s->GetAsString(&enum_temp))') |
| @@ -379,46 +405,32 @@ class CCGenerator(object): |
| else: |
| raise NotImplementedError(prop.type_) |
| c.Eblock('}') |
| - c.Substitute({ |
| + sub = { |
| 'value_var': value_var, |
| 'name': prop.unix_name, |
| 'dst': dst, |
| - 'ctype': self._cpp_type_generator.GetType(prop), |
| 'failure_value': failure_value, |
| - 'value_type': cpp_util.GetValueType(prop), |
| - }) |
| + } |
| + if prop.type_ != PropertyType.CHOICES: |
| + sub['ctype'] = self._cpp_type_generator.GetType(prop) |
| + sub['value_type'] = cpp_util.GetValueType(prop) |
| + c.Substitute(sub) |
| return c |
| - def _GeneratePopulateChoices(self, prop, value_var, dst, failure_value): |
| - """Generates the code to populate a PropertyType.CHOICES parameter or |
| - property. The existence of data inside the Value* is assumed so checks for |
| - existence should be performed before the code this generates. |
| - |
| - prop: the property the code is populating.. |
| - value_var: a Value* that should represent |prop|. |
| - dst: the object with |prop| as a member. |
| - failure_value: the value to return if |prop| cannot be extracted from |
| - |value_var|. |
| + def _GeneratePropertyFunctions(self, param_namespace, params): |
| + """Generate the structures required by a property such as functions OBJECT |
| + properties and enum to Value conversion. |
|
not at google - send to devlin
2012/02/24 03:53:05
Ugh, I don't understand how the method name and co
calamity
2012/02/24 15:10:40
Done.
|
| """ |
| - type_var = '%s->%s_type' % (dst, prop.unix_name) |
| - |
| c = code.Code() |
| - c.Sblock('switch (%s->GetType()) {' % value_var) |
| - for choice in self._cpp_type_generator.GetExpandedChoicesInParams([prop]): |
| - (c.Sblock('case %s: {' % cpp_util.GetValueType(choice)) |
| - .Concat(self._GeneratePopulatePropertyFromValue( |
| - choice, value_var, dst, failure_value, check_type=False)) |
| - .Append('%s = %s;' % |
| - (type_var, |
| - self._cpp_type_generator.GetEnumValue( |
| - prop, choice.type_.name))) |
| - .Append('break;') |
| - .Eblock('}') |
| - ) |
| - (c.Append('default:') |
| - .Append(' return %s;' % failure_value) |
| - ) |
| - c.Eblock('}') |
| + for param in params: |
| + if param.type_ == PropertyType.OBJECT: |
| + c.Concat(self._GenerateType( |
| + param_namespace + '::' + cpp_util.Classname(param.name), |
| + param)) |
| + c.Append() |
| + elif param.type_ == PropertyType.ENUM: |
| + c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) |
| + c.Append() |
| return c |
| def _GenerateFunctionResultCreate(self, function): |
| @@ -434,31 +446,29 @@ class CCGenerator(object): |
| .Append('}') |
| ) |
| else: |
| + expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( |
| + params) |
| + c.Concat(self._GeneratePropertyFunctions( |
| + classname + '::Result', expanded_params)) |
|
not at google - send to devlin
2012/02/24 03:53:05
too much indentation
calamity
2012/02/24 15:10:40
Done.
|
| + |
| # 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.GetExpandedChoicesInParams(params): |
| + for param in expanded_params: |
| # We treat this argument as 'required' to avoid wrapping it in a |
| # scoped_ptr if it's optional. |
| param_copy = param.Copy() |
| param_copy.optional = False |
| c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {') |
| - if param_copy.type_ == PropertyType.ARRAY: |
| - (c.Append('ListValue* value = new ListValue();') |
| - .Append('%s;' % self._util_cc_helper.PopulateListFromArray( |
| - param_copy, param_copy.unix_name, 'value')) |
| - .Append('return value;') |
| - ) |
| - else: |
| - c.Append('return %s;' % |
| - cpp_util.CreateValueFromSingleProperty(param_copy, |
| - param_copy.unix_name)) |
| + c.Append('return %s;' % |
| + cpp_util.CreateValueFromSingleProperty(param_copy, |
| + param_copy.unix_name, self._util_cc_helper)) |
| + c.Eblock('}') |
| c.Substitute({'classname': classname, |
| 'arg': cpp_util.GetParameterDeclaration( |
| param_copy, self._cpp_type_generator.GetType(param_copy)) |
| }) |
| - c.Eblock('}') |
| return c |