summaryrefslogtreecommitdiffstats
path: root/tools/json_schema_compiler
diff options
context:
space:
mode:
authorhebert.christopherj@chromium.org <hebert.christopherj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-23 19:56:22 +0000
committerhebert.christopherj@chromium.org <hebert.christopherj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-23 19:56:22 +0000
commiteb59ebb261bd14325b13f357d67cecd97332efc9 (patch)
treecc9e7e0c7e384db9740973fa3c7673593cc990a0 /tools/json_schema_compiler
parent71221af8e1864119137c8c90f713d5a639478f06 (diff)
downloadchromium_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.py121
-rw-r--r--tools/json_schema_compiler/h_generator.py20
-rw-r--r--tools/json_schema_compiler/test/choices.json22
-rw-r--r--tools/json_schema_compiler/test/choices_unittest.cc43
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;