diff options
author | hebert.christopherj@chromium.org <hebert.christopherj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-23 19:56:22 +0000 |
---|---|---|
committer | hebert.christopherj@chromium.org <hebert.christopherj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-23 19:56:22 +0000 |
commit | eb59ebb261bd14325b13f357d67cecd97332efc9 (patch) | |
tree | cc9e7e0c7e384db9740973fa3c7673593cc990a0 /tools/json_schema_compiler | |
parent | 71221af8e1864119137c8c90f713d5a639478f06 (diff) | |
download | chromium_src-eb59ebb261bd14325b13f357d67cecd97332efc9.zip chromium_src-eb59ebb261bd14325b13f357d67cecd97332efc9.tar.gz chromium_src-eb59ebb261bd14325b13f357d67cecd97332efc9.tar.bz2 |
JSON Schema Compiler now supports conversion from Choice to base::Value.
BUG=133636
TEST=choices_unittest.cc
Review URL: https://chromiumcodereview.appspot.com/10790040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147904 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/json_schema_compiler')
-rw-r--r-- | tools/json_schema_compiler/cc_generator.py | 121 | ||||
-rw-r--r-- | tools/json_schema_compiler/h_generator.py | 20 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/choices.json | 22 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/choices_unittest.cc | 43 |
4 files changed, 162 insertions, 44 deletions
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index 770ae48..8cea17b 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py @@ -254,7 +254,11 @@ class CCGenerator(object): if prop.type_ == PropertyType.ENUM: c.Sblock('if (%s != %s)' % (prop.unix_name, - self._cpp_type_generator.GetEnumNoneValue(prop))) + self._cpp_type_generator.GetEnumNoneValue(prop))) + elif prop.type_ == PropertyType.CHOICES: + c.Sblock('if (%s_type != %s)' % + (prop.unix_name, + self._cpp_type_generator.GetEnumNoneValue(prop))) else: c.Sblock('if (%s.get())' % prop.unix_name) c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( @@ -293,41 +297,6 @@ class CCGenerator(object): return c - def _GenerateCreateEnumValue(self, cpp_namespace, prop): - """Generates CreateEnumValue() that returns the |base::StringValue| - representation of an enum. - """ - c = Code() - c.Append('// static') - c.Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' - '%(arg)s) {') - c.Sblock('switch (%s) {' % prop.unix_name) - if prop.optional: - (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) - .Append(' return scoped_ptr<base::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<base::Value>(' - 'base::Value::CreateStringValue("%s"));' % - enum_value) - .Append('}') - ) - (c.Append('default: {') - .Append(' return scoped_ptr<base::Value>();') - .Append('}') - ) - c.Eblock('}') - c.Eblock('}') - c.Substitute({ - 'cpp_namespace': cpp_namespace, - 'arg': cpp_util.GetParameterDeclaration( - prop, self._cpp_type_generator.GetType(prop)) - }) - return c - def _CreateValueFromProperty(self, prop, var): """Creates a base::Value given a property. Generated code passes ownership to caller. @@ -337,13 +306,8 @@ class CCGenerator(object): E.g for std::string, generate base::Value::CreateStringValue(var) """ if prop.type_ == PropertyType.CHOICES: - # CHOICES conversion not implemented. If needed, write something to - # generate a function that returns a scoped_ptr<base::Value> and put it in - # _GeneratePropertyFunctions, then use it here. Look at CreateEnumValue() - # for reference. - raise NotImplementedError( - 'Conversion of CHOICES to base::Value not implemented') - if self._IsObjectOrObjectRef(prop): + return 'Get%sChoiceValue().release()' % cpp_util.Classname(prop.name) + elif self._IsObjectOrObjectRef(prop): if prop.optional: return '%s->ToValue().release()' % var else: @@ -639,11 +603,82 @@ class CCGenerator(object): elif param.type_ == PropertyType.CHOICES: c.Concat(self._GeneratePropertyFunctions( param_namespace, param.choices.values())) + if param.from_client: + c.Concat(self._GenerateGetChoiceValue(param_namespace, param)) elif param.type_ == PropertyType.ENUM: c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) c.Append() return c + def _GenerateGetChoiceValue(self, cpp_namespace, prop): + """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value> + representing the choice value. + """ + c = Code() + (c.Sblock('scoped_ptr<base::Value> ' + '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {') + .Sblock('switch (%s_type) {' % prop.unix_name) + ) + if prop.optional: + c.Concat(self._GenerateReturnCase( + self._cpp_type_generator.GetEnumNoneValue(prop), + 'scoped_ptr<base::Value>()')) + for choice in self._cpp_type_generator.ExpandParams([prop]): + c.Concat(self._GenerateReturnCase( + self._cpp_type_generator.GetEnumValue(prop, choice.type_.name), + 'make_scoped_ptr<base::Value>(%s)' % + self._CreateValueFromProperty(choice, choice.unix_name))) + (c.Eblock('}') + .Append('NOTREACHED();') + .Append('return scoped_ptr<base::Value>();') + .Eblock('}') + .Append() + .Substitute({ + 'cpp_namespace': cpp_namespace, + 'choice': cpp_util.Classname(prop.name) + }) + ) + return c + + def _GenerateCreateEnumValue(self, cpp_namespace, prop): + """Generates CreateEnumValue() that returns the base::StringValue + representation of an enum. + """ + c = Code() + c.Append('// static') + c.Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' + '%(arg)s) {') + c.Sblock('switch (%s) {' % prop.unix_name) + if prop.optional: + c.Concat(self._GenerateReturnCase( + self._cpp_type_generator.GetEnumNoneValue(prop), + 'scoped_ptr<base::Value>()')) + for enum_value in prop.enum_values: + c.Concat(self._GenerateReturnCase( + self._cpp_type_generator.GetEnumValue(prop, enum_value), + 'scoped_ptr<base::Value>(base::Value::CreateStringValue("%s"))' % + enum_value)) + (c.Eblock('}') + .Append('NOTREACHED();') + .Append('return scoped_ptr<base::Value>();') + .Eblock('}') + .Substitute({ + 'cpp_namespace': cpp_namespace, + 'arg': cpp_util.GetParameterDeclaration( + prop, self._cpp_type_generator.GetType(prop)) + }) + ) + return c + + def _GenerateReturnCase(self, case_value, return_value): + """Generates a single return case for a switch block. + """ + c = Code() + (c.Append('case %s:' % case_value) + .Append(' return %s;' % return_value) + ) + return c + def _GenerateCreateCallbackArguments(self, function_scope, callback): """Generate all functions to create Value parameters for a callback. diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py index 5f59ffb..ba7c5ca 100644 --- a/tools/json_schema_compiler/h_generator.py +++ b/tools/json_schema_compiler/h_generator.py @@ -35,6 +35,7 @@ class HGenerator(object): .Append('#include <vector>') .Append() .Append('#include "base/basictypes.h"') + .Append('#include "base/logging.h"') .Append('#include "base/memory/linked_ptr.h"') .Append('#include "base/memory/scoped_ptr.h"') .Append('#include "base/values.h"') @@ -214,6 +215,9 @@ class HGenerator(object): (c.Eblock() .Sblock(' private:') + .Concat(self._GeneratePrivatePropertyStructures( + type_.properties.values())) + .Append() .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);') .Eblock('};') ) @@ -303,6 +307,22 @@ class HGenerator(object): c.Append(create_enum_value) return c + def _GeneratePrivatePropertyStructures(self, props): + """Generate the private structures required by a property such as OBJECT + classes and enums. + """ + c = Code() + for prop in props: + if prop.type_ == PropertyType.ARRAY: + c.Concat(self._GeneratePrivatePropertyStructures([prop.item_type])) + c.Append() + elif prop.type_ == PropertyType.CHOICES: + # We only need GetChoiceValue() if there is a ToValue() method. + if prop.from_client: + c.Append('scoped_ptr<base::Value> Get%sChoiceValue() const;' % ( + cpp_util.Classname(prop.name))) + return c + def _GenerateCreateCallbackArguments(self, function): """Generates functions for passing paramaters to a callback. """ diff --git a/tools/json_schema_compiler/test/choices.json b/tools/json_schema_compiler/test/choices.json index e53ac13..24683c4 100644 --- a/tools/json_schema_compiler/test/choices.json +++ b/tools/json_schema_compiler/test/choices.json @@ -1,7 +1,27 @@ [ { "namespace": "choices", - "types": [], + "types": [ + { + "id": "ChoiceType", + "type": "object", + "properties": { + "integers": { + "choices": [ + {"type": "array", "items": {"type": "integer", "minimum": 0}}, + {"type": "integer"} + ] + }, + "strings": { + "choices": [ + {"type": "array", "items": {"type": "string", "minimum": 0}}, + {"type": "string"} + ], + "optional": true + } + } + } + ], "functions": [ { "name": "takesIntegers", diff --git a/tools/json_schema_compiler/test/choices_unittest.cc b/tools/json_schema_compiler/test/choices_unittest.cc index ce5a0ee..b4e76a1 100644 --- a/tools/json_schema_compiler/test/choices_unittest.cc +++ b/tools/json_schema_compiler/test/choices_unittest.cc @@ -111,6 +111,49 @@ TEST(JsonSchemaCompilerChoicesTest, ObjectWithChoicesParamsCreateFail) { } } +TEST(JsonSchemaCompilerChoicesTest, PopulateChoiceType) { + std::vector<std::string> strings; + strings.push_back("list"); + strings.push_back("of"); + strings.push_back("strings"); + + ListValue* strings_value = new ListValue(); + for (size_t i = 0; i < strings.size(); ++i) + strings_value->Append(Value::CreateStringValue(strings[i])); + + DictionaryValue value; + value.SetInteger("integers", 4); + value.Set("strings", strings_value); + + ChoiceType out; + ASSERT_TRUE(ChoiceType::Populate(value, &out)); + EXPECT_EQ(ChoiceType::INTEGERS_INTEGER, out.integers_type); + ASSERT_TRUE(out.integers_integer.get()); + EXPECT_FALSE(out.integers_array.get()); + EXPECT_EQ(4, *out.integers_integer); + + EXPECT_EQ(ChoiceType::STRINGS_ARRAY, out.strings_type); + EXPECT_FALSE(out.strings_string.get()); + ASSERT_TRUE(out.strings_array.get()); + EXPECT_EQ(strings, *out.strings_array); +} + +TEST(JsonSchemaCompilerChoicesTest, ChoiceTypeToValue) { + ListValue* strings_value = new ListValue(); + strings_value->Append(Value::CreateStringValue("list")); + strings_value->Append(Value::CreateStringValue("of")); + strings_value->Append(Value::CreateStringValue("strings")); + + DictionaryValue value; + value.SetInteger("integers", 5); + value.Set("strings", strings_value); + + ChoiceType out; + ASSERT_TRUE(ChoiceType::Populate(value, &out)); + + EXPECT_TRUE(value.Equals(out.ToValue().get())); +} + TEST(JsonSchemaCompilerChoicesTest, ReturnChoices) { { std::vector<int> integers; |