summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 06:50:31 +0000
committerkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-17 06:50:31 +0000
commit242d5e7aaf2658a88f1ed4954e34876d7082f1a7 (patch)
tree677cff28f304753c8e9f1d1e9062a9b2de871a77 /tools
parent3543975945a5667aa3fb48c6d0e1b6312d1ed293 (diff)
downloadchromium_src-242d5e7aaf2658a88f1ed4954e34876d7082f1a7.zip
chromium_src-242d5e7aaf2658a88f1ed4954e34876d7082f1a7.tar.gz
chromium_src-242d5e7aaf2658a88f1ed4954e34876d7082f1a7.tar.bz2
Overhaul JSON Schema Compiler to support a number of features required to
support the full range of JSON/IDL features, improve the interface of generated code, and improve generated code formatting, notably: * Make "choices" generate a struct containing each possible type, rather than multiple fields with different names plus and enum. This makes it possible to embed choices inside containers - notably within arrays (as in bug). It also improves optional choices detection. * Remove the Any C++ type generated by "any", and model it as a base::Value. * Make "additionalProperties" generated a std::map with the actual types as values, rather than just a DictionaryValue forcing callers to extract types. * Fix enum naming, it was unnecessarily including the namespace as a prefix. R=yoz@chromium.org BUG=162044 Review URL: https://codereview.chromium.org/11827026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177361 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/json_schema_compiler/any.cc32
-rw-r--r--tools/json_schema_compiler/any.h40
-rw-r--r--tools/json_schema_compiler/any_helper.py32
-rw-r--r--tools/json_schema_compiler/api_gen_util.gyp1
-rw-r--r--tools/json_schema_compiler/cc_generator.py1080
-rw-r--r--tools/json_schema_compiler/code.py7
-rw-r--r--tools/json_schema_compiler/cpp_type_generator.py273
-rwxr-xr-xtools/json_schema_compiler/cpp_type_generator_test.py134
-rw-r--r--tools/json_schema_compiler/cpp_util.py58
-rw-r--r--tools/json_schema_compiler/h_generator.py353
-rw-r--r--tools/json_schema_compiler/idl_schema.py1
-rwxr-xr-xtools/json_schema_compiler/idl_schema_test.py28
-rw-r--r--tools/json_schema_compiler/json_schema.py1
-rw-r--r--tools/json_schema_compiler/model.py464
-rwxr-xr-xtools/json_schema_compiler/model_test.py44
-rwxr-xr-xtools/json_schema_compiler/preview.py2
-rw-r--r--tools/json_schema_compiler/schema_util.py26
-rwxr-xr-xtools/json_schema_compiler/schema_util_test.py54
-rw-r--r--tools/json_schema_compiler/test/additional_properties.json2
-rw-r--r--tools/json_schema_compiler/test/additional_properties_unittest.cc32
-rw-r--r--tools/json_schema_compiler/test/any_unittest.cc16
-rw-r--r--tools/json_schema_compiler/test/arrays.json49
-rw-r--r--tools/json_schema_compiler/test/arrays_unittest.cc43
-rw-r--r--tools/json_schema_compiler/test/choices_unittest.cc99
-rw-r--r--tools/json_schema_compiler/test/enums.json1
-rw-r--r--tools/json_schema_compiler/test/enums_unittest.cc10
-rw-r--r--tools/json_schema_compiler/test/functions_on_types_unittest.cc26
-rw-r--r--tools/json_schema_compiler/test/idl_schemas_unittest.cc6
-rw-r--r--tools/json_schema_compiler/test/objects_unittest.cc5
-rw-r--r--tools/json_schema_compiler/util.cc29
-rw-r--r--tools/json_schema_compiler/util.h23
-rw-r--r--tools/json_schema_compiler/util_cc_helper.py6
32 files changed, 1243 insertions, 1734 deletions
diff --git a/tools/json_schema_compiler/any.cc b/tools/json_schema_compiler/any.cc
deleted file mode 100644
index cd4e5c3..0000000
--- a/tools/json_schema_compiler/any.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/json_schema_compiler/any.h"
-
-#include "base/logging.h"
-#include "base/values.h"
-
-namespace json_schema_compiler {
-namespace any {
-
-Any::Any() {}
-
-Any::Any(scoped_ptr<base::Value> from_value)
- : value_(from_value.Pass()) {
-}
-
-Any::~Any() {}
-
-void Any::Init(const base::Value& from_value) {
- CHECK(!value_.get());
- value_.reset(from_value.DeepCopy());
-}
-
-const base::Value& Any::value() const {
- CHECK(value_.get());
- return *value_;
-}
-
-} // namespace any
-} // namespace json_schema_compiler
diff --git a/tools/json_schema_compiler/any.h b/tools/json_schema_compiler/any.h
deleted file mode 100644
index 83b84d6..0000000
--- a/tools/json_schema_compiler/any.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_JSON_SCHEMA_COMPILER_ANY_H__
-#define TOOLS_JSON_SCHEMA_COMPILER_ANY_H__
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace base {
-class Value;
-}
-
-namespace json_schema_compiler {
-namespace any {
-
-// Represents an "any" type in JSON schema as a wrapped Value.
-class Any {
- public:
- Any();
- explicit Any(scoped_ptr<base::Value> from_value);
- ~Any();
-
- // Initializes the Value in this Any. Fails if already initialized.
- void Init(const base::Value& from_value);
-
- // Get the Value from this Any.
- const base::Value& value() const;
-
- private:
- scoped_ptr<base::Value> value_;
-
- DISALLOW_COPY_AND_ASSIGN(Any);
-};
-
-} // namespace any
-} // namespace json_schema_compiler
-
-#endif // TOOLS_JSON_SCHEMA_COMPILER_ANY_H__
diff --git a/tools/json_schema_compiler/any_helper.py b/tools/json_schema_compiler/any_helper.py
deleted file mode 100644
index a087ffd..0000000
--- a/tools/json_schema_compiler/any_helper.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-ANY_NAMESPACE = 'json_schema_compiler::any'
-ANY_CLASS = ANY_NAMESPACE + '::Any'
-
-class AnyHelper(object):
- """A util class that generates code that uses
- tools/json_schema_compiler/any.cc.
- """
- def Init(self, any_prop, src, dst):
- """Initialize |dst|.|any_prop| to |src|.
-
- src: Value*
- dst: Type*
- """
- if any_prop.optional:
- return '%s->%s->Init(*%s)' % (dst, any_prop.unix_name, src)
- else:
- return '%s->%s.Init(*%s)' % (dst, any_prop.unix_name, src)
-
- def GetValue(self, any_prop, var):
- """Get |var| as a const Value&.
-
- var: Any* or Any
- """
- if any_prop.optional:
- return '%s->value()' % var
- else:
- return '%s.value()' % var
-
diff --git a/tools/json_schema_compiler/api_gen_util.gyp b/tools/json_schema_compiler/api_gen_util.gyp
index b1c220d..54966cc 100644
--- a/tools/json_schema_compiler/api_gen_util.gyp
+++ b/tools/json_schema_compiler/api_gen_util.gyp
@@ -10,7 +10,6 @@
'target_name': 'api_gen_util',
'type': 'static_library',
'sources': [
- 'any.cc',
'util.cc',
],
'dependencies': ['<(DEPTH)/base/base.gyp:base'],
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index 2e42998..86724fc 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -3,8 +3,7 @@
# found in the LICENSE file.
from code import Code
-from model import PropertyType
-import any_helper
+from model import PropertyType, Type
import cpp_util
import model
import schema_util
@@ -15,13 +14,12 @@ class CCGenerator(object):
"""A .cc generator for a namespace.
"""
def __init__(self, namespace, cpp_type_generator):
- self._cpp_type_generator = cpp_type_generator
+ self._type_helper = cpp_type_generator
self._namespace = namespace
self._target_namespace = (
- self._cpp_type_generator.GetCppNamespaceName(self._namespace))
+ self._type_helper.GetCppNamespaceName(self._namespace))
self._util_cc_helper = (
- util_cc_helper.UtilCCHelper(self._cpp_type_generator))
- self._any_helper = any_helper.AnyHelper()
+ util_cc_helper.UtilCCHelper(self._type_helper))
def Generate(self):
"""Generates a Code object with the .cc for a single namespace.
@@ -34,17 +32,10 @@ class CCGenerator(object):
.Append(self._util_cc_helper.GetIncludePath())
.Append('#include "%s/%s.h"' %
(self._namespace.source_file_dir, self._namespace.unix_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('#include "base/logging.h"')
+ .Cblock(self._type_helper.GenerateIncludes())
+ .Concat(self._type_helper.GetRootNamespaceStart())
+ .Cblock(self._type_helper.GetNamespaceStart())
)
if self._namespace.properties:
(c.Append('//')
@@ -53,21 +44,18 @@ class CCGenerator(object):
.Append()
)
for property in self._namespace.properties.values():
- property_code = self._cpp_type_generator.GeneratePropertyValues(
+ property_code = self._type_helper.GeneratePropertyValues(
property,
'const %(type)s %(name)s = %(value)s;',
nodoc=True)
if property_code:
- c.Concat(property_code).Append()
+ c.Cblock(property_code)
if self._namespace.types:
(c.Append('//')
.Append('// Types')
.Append('//')
.Append()
- )
- for type_ in self._namespace.types.values():
- (c.Concat(self._GenerateType(
- schema_util.StripSchemaNamespace(type_.name), type_)).Append()
+ .Cblock(self._GenerateTypes(None, self._namespace.types.values()))
)
if self._namespace.functions:
(c.Append('//')
@@ -76,24 +64,17 @@ class CCGenerator(object):
.Append()
)
for function in self._namespace.functions.values():
- (c.Concat(self._GenerateFunction(
- cpp_util.Classname(function.name), function))
- .Append()
- )
+ c.Cblock(self._GenerateFunction(function))
if self._namespace.events:
(c.Append('//')
.Append('// Events')
.Append('//')
.Append()
)
- for event in self._namespace.events.values():
- (c.Concat(self._GenerateCreateCallbackArguments(
- cpp_util.Classname(event.name), event, generate_to_json=True))
- .Append()
- )
- (c.Concat(self._cpp_type_generator.GetNamespaceEnd())
- .Concat(self._cpp_type_generator.GetRootNamespaceEnd())
- .Append()
+ for event in self._namespace.events.values():
+ c.Cblock(self._GenerateEvent(event))
+ (c.Concat(self._type_helper.GetNamespaceEnd())
+ .Cblock(self._type_helper.GetRootNamespaceEnd())
)
return c
@@ -104,33 +85,40 @@ class CCGenerator(object):
c = Code()
if type_.functions:
- for function in type_.functions.values():
- (c.Concat(
- self._GenerateFunction(
- cpp_namespace + '::' + cpp_util.Classname(function.name),
- function))
- .Append())
- elif type_.type_ == PropertyType.OBJECT:
- (c.Concat(self._GeneratePropertyFunctions(
- cpp_namespace, type_.properties.values()))
- .Sblock('%(namespace)s::%(classname)s()')
- .Concat(self._GenerateInitializersAndBody(type_))
- .Eblock('%(namespace)s::~%(classname)s() {}')
+ # Wrap functions within types in the type's namespace.
+ (c.Append('namespace %s {' % classname)
.Append())
- if type_.from_json:
- (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
- .Append())
- if type_.from_client:
- (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
- .Append())
- elif self._cpp_type_generator.IsEnumOrEnumRef(type_):
- (c.Concat(self._GenerateCreateEnumTypeValue(cpp_namespace, type_))
- .Append()
- .Concat(self._GenerateEnumFromString(cpp_namespace, type_))
+ for function in type_.functions.values():
+ c.Cblock(self._GenerateFunction(function))
+ c.Append('} // namespace %s' % classname)
+ elif type_.property_type == PropertyType.ARRAY:
+ c.Cblock(self._GenerateType(cpp_namespace, type_.item_type))
+ elif (type_.property_type == PropertyType.OBJECT or
+ type_.property_type == PropertyType.CHOICES):
+ if cpp_namespace is None:
+ classname_in_namespace = classname
+ else:
+ classname_in_namespace = '%s::%s' % (cpp_namespace, classname)
+
+ if type_.property_type == PropertyType.OBJECT:
+ c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace,
+ type_.properties.values()))
+ else:
+ c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices))
+
+ (c.Append('%s::%s()' % (classname_in_namespace, classname))
+ .Cblock(self._GenerateInitializersAndBody(type_))
+ .Append('%s::~%s() {}' % (classname_in_namespace, classname))
.Append()
- .Concat(self._GenerateEnumToString(cpp_namespace, type_))
- .Append())
- c.Substitute({'classname': classname, 'namespace': cpp_namespace})
+ )
+ if type_.origin.from_json:
+ c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
+ if type_.origin.from_client:
+ c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_))
+ elif type_.property_type == PropertyType.ENUM:
+ (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_))
+ .Cblock(self._GenerateEnumFromString(cpp_namespace, type_))
+ )
return c
@@ -141,29 +129,28 @@ class CCGenerator(object):
continue
t = prop.type_
- if t == PropertyType.INTEGER:
+ if t.property_type == PropertyType.INTEGER:
items.append('%s(0)' % prop.unix_name)
- elif t == PropertyType.DOUBLE:
+ elif t.property_type == PropertyType.DOUBLE:
items.append('%s(0.0)' % prop.unix_name)
- elif t == PropertyType.BOOLEAN:
+ elif t.property_type == PropertyType.BOOLEAN:
items.append('%s(false)' % prop.unix_name)
- elif t == PropertyType.BINARY:
+ elif t.property_type == PropertyType.BINARY:
items.append('%s(NULL)' % prop.unix_name)
- elif (t == PropertyType.ADDITIONAL_PROPERTIES or
- t == PropertyType.ANY or
- t == PropertyType.ARRAY or
- t == PropertyType.CHOICES or
- t == PropertyType.ENUM or
- t == PropertyType.OBJECT or
- t == PropertyType.FUNCTION or
- t == PropertyType.REF or
- t == PropertyType.STRING):
+ elif (t.property_type == PropertyType.ANY or
+ t.property_type == PropertyType.ARRAY or
+ t.property_type == PropertyType.CHOICES or
+ t.property_type == PropertyType.ENUM or
+ t.property_type == PropertyType.OBJECT or
+ t.property_type == PropertyType.FUNCTION or
+ t.property_type == PropertyType.REF or
+ t.property_type == PropertyType.STRING):
# TODO(miket): It would be nice to initialize CHOICES and ENUM, but we
# don't presently have the semantics to indicate which one of a set
# should be the default.
continue
else:
- sys.exit("Unhandled PropertyType: %s" % t)
+ raise TypeError(t)
if items:
s = ': %s' % (', '.join(items))
@@ -180,33 +167,54 @@ class CCGenerator(object):
classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
c = Code()
(c.Append('// static')
- .Sblock('bool %(namespace)s::Populate'
- '(const base::Value& value, %(name)s* out) {')
- .Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))')
- .Append(' return false;')
+ .Append('bool %(namespace)s::Populate(')
+ .Sblock(' const base::Value& value, %(name)s* out) {')
)
- if type_.properties:
- (c.Append('const base::DictionaryValue* dict = '
- 'static_cast<const base::DictionaryValue*>(&value);')
- .Append()
+ if type_.property_type == PropertyType.CHOICES:
+ for choice in type_.choices:
+ value_type = cpp_util.GetValueType(self._type_helper.FollowRef(choice))
+ (c.Sblock('if (value.IsType(%s)) {' % value_type)
+ .Concat(self._GeneratePopulateVariableFromValue(
+ choice,
+ '(&value)',
+ 'out->as_%s' % choice.unix_name,
+ 'false',
+ is_ptr=True))
+ .Append('return true;')
+ .Eblock('}')
+ )
+ c.Append('return false;')
+ elif type_.property_type == PropertyType.OBJECT:
+ (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))')
+ .Append(' return false;')
)
+ if type_.properties or type_.additional_properties is not None:
+ c.Append('const base::DictionaryValue* dict = '
+ 'static_cast<const base::DictionaryValue*>(&value);')
for prop in type_.properties.values():
c.Concat(self._InitializePropertyToDefault(prop, 'out'))
for prop in type_.properties.values():
- if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
+ c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
+ if type_.additional_properties is not None:
+ if type_.additional_properties.property_type == PropertyType.ANY:
c.Append('out->additional_properties.MergeDictionary(dict);')
- # remove all keys that are actual properties
- for cur_prop in type_.properties.values():
- if prop != cur_prop:
- c.Append('out->additional_properties'
- '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name)
- c.Append()
else:
- c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
- (c.Append('return true;')
- .Eblock('}')
- )
- c.Substitute({'namespace': cpp_namespace, 'name': classname})
+ cpp_type = self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)
+ (c.Append('for (base::DictionaryValue::Iterator it(*dict);')
+ .Sblock(' it.HasNext(); it.Advance()) {')
+ .Append('%s tmp;' % cpp_type)
+ .Concat(self._GeneratePopulateVariableFromValue(
+ type_.additional_properties,
+ '(&it.value())',
+ 'tmp',
+ 'false'))
+ .Append('out->additional_properties[it.key()] = tmp;')
+ .Eblock('}')
+ )
+ c.Append('return true;')
+ (c.Eblock('}')
+ .Substitute({'namespace': cpp_namespace, 'name': classname}))
return c
def _GenerateTypePopulateProperty(self, prop, src, dst):
@@ -223,10 +231,11 @@ class CCGenerator(object):
'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
.Concat(self._GeneratePopulatePropertyFromValue(
prop, value_var, dst, 'false')))
- if self._cpp_type_generator.IsEnumOrEnumRef(prop):
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if underlying_type.property_type == PropertyType.ENUM:
(c.Append('} else {')
.Append('%%(dst)s->%%(name)s = %s;' %
- self._cpp_type_generator.GetEnumNoneValue(prop)))
+ self._type_helper.GetEnumNoneValue(prop.type_)))
c.Eblock('}')
else:
(c.Append(
@@ -246,140 +255,184 @@ class CCGenerator(object):
return c
def _GenerateTypeToValue(self, cpp_namespace, type_):
- """Generates a function that serializes the type into a
- |base::DictionaryValue|.
-
+ """Generates a function that serializes the type into a base::Value.
E.g. for type "Foo" generates Foo::ToValue()
"""
+ if type_.property_type == PropertyType.OBJECT:
+ return self._GenerateObjectTypeToValue(cpp_namespace, type_)
+ elif type_.property_type == PropertyType.CHOICES:
+ return self._GenerateChoiceTypeToValue(cpp_namespace, type_)
+ else:
+ raise ValueError("Unsupported property type %s" % type_.type_)
+
+ def _GenerateObjectTypeToValue(self, cpp_namespace, type_):
+ """Generates a function that serializes an object-representing type
+ into a base::DictionaryValue.
+ """
c = Code()
(c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' %
cpp_namespace)
.Append('scoped_ptr<base::DictionaryValue> value('
- 'new base::DictionaryValue());')
+ 'new base::DictionaryValue());')
.Append()
)
+
for prop in type_.properties.values():
- if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
- c.Append('value->MergeDictionary(&%s);' % prop.unix_name)
- else:
- if prop.optional:
- if self._cpp_type_generator.IsEnumOrEnumRef(prop):
- c.Sblock('if (%s != %s) {' %
- (prop.unix_name,
- 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)
-
- if prop.type_ == prop.compiled_type:
- c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
- prop.name,
- self._CreateValueFromProperty(prop, 'this->' + prop.unix_name)))
+ if prop.optional:
+ # Optional enum values are generated with a NONE enum value.
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if underlying_type.property_type == PropertyType.ENUM:
+ c.Sblock('if (%s != %s) {' %
+ (prop.unix_name,
+ self._type_helper.GetEnumNoneValue(prop.type_)))
else:
- conversion_src = 'this->' + prop.unix_name
- if prop.optional:
- conversion_src = '*' + conversion_src
- (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop),
- prop.unix_name))
- .Append(cpp_util.GenerateCompiledTypeToTypeConversion(
- self._cpp_type_generator.GetReferencedProperty(prop),
- conversion_src,
- prop.unix_name) + ';')
- .Append('value->SetWithoutPathExpansion("%s", %s);' % (
- prop.unix_name,
- self._CreateValueFromProperty(prop, prop.unix_name)))
- )
- if prop.optional:
- c.Eblock('}');
- (c.Append()
- .Append('return value.Pass();')
+ c.Sblock('if (%s.get()) {' % prop.unix_name)
+
+ # ANY is a base::Value which is abstract and cannot be a direct member, so
+ # it will always be a pointer.
+ is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
+ c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
+ prop.name,
+ self._CreateValueFromType(prop.type_,
+ 'this->%s' % prop.unix_name,
+ is_ptr=is_ptr)))
+
+ if prop.optional:
+ c.Eblock('}');
+
+ if type_.additional_properties is not None:
+ if type_.additional_properties.property_type == PropertyType.ANY:
+ c.Append('value->MergeDictionary(&additional_properties);')
+ else:
+ # Non-copyable types will be wrapped in a linked_ptr for inclusion in
+ # maps, so we need to unwrap them.
+ needs_unwrap = (
+ not self._type_helper.IsCopyable(type_.additional_properties))
+ cpp_type = self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)
+ (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' %
+ cpp_util.PadForGenerics(cpp_type))
+ .Append(' additional_properties.begin();')
+ .Append(' it != additional_properties.end(); ++it) {')
+ .Append('value->SetWithoutPathExpansion(it->first, %s);' %
+ self._CreateValueFromType(
+ type_.additional_properties,
+ '%sit->second' % ('*' if needs_unwrap else '')))
+ .Eblock('}')
+ )
+
+ return (c.Append()
+ .Append('return value.Pass();')
+ .Eblock('}'))
+
+ def _GenerateChoiceTypeToValue(self, cpp_namespace, type_):
+ """Generates a function that serializes a choice-representing type
+ into a base::Value.
+ """
+ c = Code()
+ c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace)
+ c.Append('scoped_ptr<base::Value> result;');
+ for choice in type_.choices:
+ choice_var = 'as_%s' % choice.unix_name
+ (c.Sblock('if (%s) {' % choice_var)
+ .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
+ type_.unix_name)
+ .Append('result.reset(%s);' %
+ self._CreateValueFromType(choice, '*%s' % choice_var))
+ .Eblock('}')
+ )
+ (c.Append('DCHECK(result) << "Must set at least one choice for %s";' %
+ type_.unix_name)
+ .Append('return result.Pass();')
.Eblock('}')
)
return c
- def _GenerateFunction(self, cpp_namespace, function):
+ def _GenerateFunction(self, function):
"""Generates the definitions for function structs.
"""
c = Code()
+ # TODO(kalman): use function.unix_name not Classname.
+ function_namespace = cpp_util.Classname(function.name)
+ (c.Append('namespace %s {' % function_namespace)
+ .Append()
+ )
+
# Params::Populate function
if function.params:
- c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params',
- function.params))
- (c.Append('%(cpp_namespace)s::Params::Params() {}')
- .Append('%(cpp_namespace)s::Params::~Params() {}')
- .Append()
- .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function))
+ c.Concat(self._GeneratePropertyFunctions('Params', function.params))
+ (c.Append('Params::Params() {}')
+ .Append('Params::~Params() {}')
.Append()
+ .Cblock(self._GenerateFunctionParamsCreate(function))
)
# Results::Create function
if function.callback:
- c.Concat(self._GenerateCreateCallbackArguments(
- "%s::Results" % cpp_namespace, function.callback))
+ c.Concat(self._GenerateCreateCallbackArguments('Results',
+ function.callback))
- c.Substitute({'cpp_namespace': cpp_namespace})
+ c.Append('} // namespace %s' % function_namespace)
+ return c
+ def _GenerateEvent(self, event):
+ # TODO(kalman): use event.unix_name not Classname.
+ c = Code()
+ event_namespace = cpp_util.Classname(event.name)
+ (c.Append('namespace %s {' % event_namespace)
+ .Append()
+ .Cblock(self._GenerateCreateCallbackArguments(None, event))
+ .Append('} // namespace %s' % event_namespace)
+ )
return c
- def _CreateValueFromProperty(self, prop, var):
- """Creates a base::Value given a property. Generated code passes ownership
+ def _CreateValueFromType(self, type_, var, is_ptr=False):
+ """Creates a base::Value given a type. Generated code passes ownership
to caller.
var: variable or variable*
E.g for std::string, generate base::Value::CreateStringValue(var)
"""
- if prop.type_ == PropertyType.CHOICES:
- return 'Get%sChoiceValue().release()' % cpp_util.Classname(prop.name)
- elif self._IsObjectOrObjectRef(prop):
- if prop.optional:
- return '%s->ToValue().release()' % var
+ underlying_type = self._type_helper.FollowRef(type_)
+ if (underlying_type.property_type == PropertyType.CHOICES or
+ underlying_type.property_type == PropertyType.OBJECT):
+ if is_ptr:
+ return '(%s)->ToValue().release()' % var
else:
- return '%s.ToValue().release()' % var
- elif prop.type_ == PropertyType.ANY:
- return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var)
- elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
- return '%s.DeepCopy()' % var
- elif prop.type_ == PropertyType.FUNCTION:
- if prop.optional:
- vardot = var + '->'
+ return '(%s).ToValue().release()' % var
+ elif (underlying_type.property_type == PropertyType.ANY or
+ underlying_type.property_type == PropertyType.FUNCTION):
+ if is_ptr:
+ vardot = '(%s)->' % var
else:
- vardot = var + '.'
+ vardot = '(%s).' % var
return '%sDeepCopy()' % vardot
- elif self._cpp_type_generator.IsEnumOrEnumRef(prop):
+ elif underlying_type.property_type == PropertyType.ENUM:
return 'base::Value::CreateStringValue(ToString(%s))' % var
- elif prop.type_ == PropertyType.BINARY:
- if prop.optional:
+ elif underlying_type.property_type == PropertyType.BINARY:
+ if is_ptr:
vardot = var + '->'
else:
vardot = var + '.'
return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
(vardot, vardot))
- elif self._IsArrayOrArrayRef(prop):
+ elif underlying_type.property_type == PropertyType.ARRAY:
return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
- self._cpp_type_generator.GetReferencedProperty(prop), var,
- prop.optional)
- elif self._IsFundamentalOrFundamentalRef(prop):
- # If prop.type != prop.compiled_type, then no asterisk is necessary
- # because the target is a local variable and not a dereferenced scoped
- # pointer. The asterisk is instead prepended to conversion_src around line
- # 273.
- if prop.optional and prop.type_ == prop.compiled_type:
- var = '*' + var
- prop = self._cpp_type_generator.GetReferencedProperty(prop);
- return {
- PropertyType.STRING: 'base::Value::CreateStringValue(%s)',
- PropertyType.BOOLEAN: 'base::Value::CreateBooleanValue(%s)',
- PropertyType.INTEGER: 'base::Value::CreateIntegerValue(%s)',
- PropertyType.DOUBLE: 'base::Value::CreateDoubleValue(%s)',
- }[prop.type_] % var
+ underlying_type,
+ var,
+ is_ptr)
+ elif underlying_type.property_type.is_fundamental:
+ if is_ptr:
+ var = '*%s' % var
+ if underlying_type.property_type == PropertyType.STRING:
+ return 'new base::StringValue(%s)' % var
+ else:
+ return 'new base::FundamentalValue(%s)' % var
else:
raise NotImplementedError('Conversion of %s to base::Value not '
- 'implemented' % repr(prop.type_))
+ 'implemented' % repr(type_.type_))
def _GenerateParamsCheck(self, function, var):
"""Generates a check for the correct number of arguments when creating
@@ -405,7 +458,7 @@ class CCGenerator(object):
})
return c
- def _GenerateFunctionParamsCreate(self, cpp_namespace, function):
+ def _GenerateFunctionParamsCreate(self, function):
"""Generate function to create an instance of Params. The generated
function takes a base::ListValue of arguments.
@@ -413,12 +466,11 @@ class CCGenerator(object):
"""
c = Code()
(c.Append('// static')
- .Sblock('scoped_ptr<%(cpp_namespace)s::Params> '
- '%(cpp_namespace)s::Params::Create(const base::ListValue& args) {')
+ .Sblock('scoped_ptr<Params> '
+ 'Params::Create(const base::ListValue& args) {')
.Concat(self._GenerateParamsCheck(function, 'args'))
.Append('scoped_ptr<Params> params(new Params());')
)
- c.Substitute({'cpp_namespace': cpp_namespace})
for param in function.params:
c.Concat(self._InitializePropertyToDefault(param, 'params'))
@@ -432,9 +484,8 @@ class CCGenerator(object):
c.Append()
value_var = param.unix_name + '_value'
(c.Append('const base::Value* %(value_var)s = NULL;')
- .Append('if (args.Get(%(i)s, &%(value_var)s) &&\n'
- ' !%(value_var)s->IsType(base::Value::TYPE_NULL))')
- .Sblock('{')
+ .Append('if (args.Get(%(i)s, &%(value_var)s) &&')
+ .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {')
.Concat(self._GeneratePopulatePropertyFromValue(
param, value_var, 'params', failure_value))
.Eblock('}')
@@ -453,466 +504,291 @@ class CCGenerator(object):
return c
- def _GeneratePopulatePropertyFromValue(
- self, prop, value_var, dst, failure_value, check_type=True):
- """Generates code to populate a model.Property given a base::Value*. The
- existence of data inside the base::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 base::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|
- check_type: if true, will check if |value_var| is the correct
- base::Value::Type
+ def _GeneratePopulatePropertyFromValue(self,
+ prop,
+ src_var,
+ dst_class_var,
+ failure_value):
+ """Generates code to populate property |prop| of |dst_class_var| (a
+ pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for
+ semantics.
+ """
+ return self._GeneratePopulateVariableFromValue(prop.type_,
+ src_var,
+ '%s->%s' % (dst_class_var,
+ prop.unix_name),
+ failure_value,
+ is_ptr=prop.optional)
+
+ def _GeneratePopulateVariableFromValue(self,
+ type_,
+ src_var,
+ dst_var,
+ failure_value,
+ is_ptr=False):
+ """Generates code to populate a variable |dst_var| of type |type_| from a
+ Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated
+ code, if |dst_var| fails to be populated then Populate will return
+ |failure_value|.
"""
c = Code()
c.Sblock('{')
- if self._IsFundamentalOrFundamentalRef(prop):
- self._GenerateFundamentalOrFundamentalRefPopulate(c, prop, value_var, dst)
- elif self._IsObjectOrObjectRef(prop):
- self._GenerateObjectOrObjectRefPopulate(c, prop)
- elif prop.type_ == PropertyType.FUNCTION:
- self._GenerateFunctionPopulate(c, prop)
- elif prop.type_ == PropertyType.ANY:
- self._GenerateAnyPopulate(c, prop, value_var, dst)
- elif self._IsArrayOrArrayRef(prop):
- self._GenerateArrayOrArrayRefPopulate(c, prop, dst)
- elif prop.type_ == PropertyType.CHOICES:
- self._GenerateChoicePopulate(c, prop, value_var, dst, failure_value)
- elif self._cpp_type_generator.IsEnumOrEnumRef(prop):
- self._GenerateEnumPopulate(c, prop, value_var)
- elif prop.type_ == PropertyType.BINARY:
- self._GenerateBinaryPopulate(c, prop)
- else:
- raise NotImplementedError(prop.type_)
- c.Eblock('}')
- sub = {
- 'value_var': value_var,
- 'name': prop.unix_name,
- 'dst': dst,
- 'failure_value': failure_value,
- }
- if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
- sub['ctype'] = self._cpp_type_generator.GetType(prop)
- sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop)
- sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator
- .GetReferencedProperty(prop).type_)
- c.Substitute(sub)
- return c
+ underlying_type = self._type_helper.FollowRef(type_)
- def _GenerateFundamentalOrFundamentalRefPopulate(self,
- c,
- prop,
- value_var,
- dst):
- if prop.optional:
- (c.Append('%(ctype)s temp;')
- .Append('if (!%s)' %
- cpp_util.GetAsFundamentalValue(
- self._cpp_type_generator.GetReferencedProperty(prop),
- value_var,
- '&temp'))
- .Append(' return %(failure_value)s;')
- )
- if prop.type_ != prop.compiled_type:
- (c.Append('%(compiled_ctype)s temp2;')
- .Append('if (!%s)' %
- cpp_util.GenerateTypeToCompiledTypeConversion(
- self._cpp_type_generator.GetReferencedProperty(prop),
- 'temp',
- 'temp2'))
+ if underlying_type.property_type.is_fundamental:
+ if is_ptr:
+ (c.Append('%(cpp_type)s temp;')
+ .Append('if (!%s)' % cpp_util.GetAsFundamentalValue(
+ self._type_helper.FollowRef(type_), src_var, '&temp'))
.Append(' return %(failure_value)s;')
- .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));')
+ .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));')
)
else:
- c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));')
-
- else:
- if prop.type_ == prop.compiled_type:
- assignment_target = '&%s->%s' % (dst, prop.unix_name)
+ (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue(
+ self._type_helper.FollowRef(type_),
+ src_var,
+ '&%s' % dst_var))
+ .Append(' return %(failure_value)s;')
+ )
+ elif underlying_type.property_type == PropertyType.OBJECT:
+ if is_ptr:
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))')
+ .Append(' return %(failure_value)s;')
+ .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
+ .Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))')
+ .Append(' return %(failure_value)s;')
+ .Append('%(dst_var)s = temp.Pass();')
+ )
else:
- c.Append('%(ctype)s temp;')
- assignment_target = '&temp'
- (c.Append('if (!%s)' %
- cpp_util.GetAsFundamentalValue(
- self._cpp_type_generator.GetReferencedProperty(prop),
- value_var,
- assignment_target))
- .Append(' return %(failure_value)s;')
- )
- if prop.type_ != prop.compiled_type:
- (c.Append('if (!%s)' %
- cpp_util.GenerateTypeToCompiledTypeConversion(
- self._cpp_type_generator.GetReferencedProperty(prop),
- 'temp',
- '%s->%s' % (dst, prop.unix_name)))
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))')
+ .Append(' return %(failure_value)s;')
+ .Append('if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))')
.Append(' return %(failure_value)s;')
)
-
- def _GenerateObjectOrObjectRefPopulate(self, c, prop):
- if prop.optional:
- (c.Append('const base::DictionaryValue* dictionary = NULL;')
- .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
- .Append(' return %(failure_value)s;')
- .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());')
- .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))')
- .Append(' return %(failure_value)s;')
- .Append('%(dst)s->%(name)s = temp.Pass();')
- )
- else:
- (c.Append('const base::DictionaryValue* dictionary = NULL;')
- .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
- .Append(' return %(failure_value)s;')
- .Append(
- 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))')
- .Append(' return %(failure_value)s;')
- )
-
- def _GenerateFunctionPopulate(self, c, prop):
- if prop.optional:
- c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());')
-
- def _GenerateAnyPopulate(self, c, prop, value_var, dst):
- if prop.optional:
- c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());')
- c.Append(self._any_helper.Init(prop, value_var, dst) + ';')
-
- def _GenerateArrayOrArrayRefPopulate(self, c, prop, dst):
- # util_cc_helper deals with optional and required arrays
- (c.Append('const base::ListValue* list = NULL;')
- .Append('if (!%(value_var)s->GetAsList(&list))')
- .Append(' return %(failure_value)s;'))
- if prop.item_type.type_ == PropertyType.ENUM:
- self._GenerateListValueToEnumArrayConversion(c, prop)
- else:
- (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
- self._cpp_type_generator.GetReferencedProperty(prop), 'list',
- dst + '->' + prop.unix_name, prop.optional))
+ elif underlying_type.property_type == PropertyType.FUNCTION:
+ if is_ptr:
+ c.Append('%(dst_var)s.reset(new base::DictionaryValue());')
+ elif underlying_type.property_type == PropertyType.ANY:
+ c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
+ elif underlying_type.property_type == PropertyType.ARRAY:
+ # util_cc_helper deals with optional and required arrays
+ (c.Append('const base::ListValue* list = NULL;')
+ .Append('if (!%(src_var)s->GetAsList(&list))')
+ .Append(' return %(failure_value)s;'))
+ item_type = underlying_type.item_type
+ if item_type.property_type == PropertyType.ENUM:
+ c.Concat(self._GenerateListValueToEnumArrayConversion(
+ item_type,
+ 'list',
+ dst_var,
+ failure_value,
+ is_ptr=is_ptr))
+ else:
+ (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
+ underlying_type,
+ 'list',
+ dst_var,
+ is_ptr))
+ .Append(' return %(failure_value)s;')
+ )
+ elif underlying_type.property_type == PropertyType.CHOICES:
+ if is_ptr:
+ (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
+ .Append('if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))')
+ .Append(' return %(failure_value)s;')
+ .Append('%(dst_var)s = temp.Pass();')
+ )
+ else:
+ (c.Append('if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))')
+ .Append(' return %(failure_value)s;')
+ )
+ elif underlying_type.property_type == PropertyType.ENUM:
+ c.Concat(self._GenerateStringToEnumConversion(type_,
+ src_var,
+ dst_var,
+ failure_value))
+ elif underlying_type.property_type == PropertyType.BINARY:
+ (c.Append('if (!%(src_var)s->IsType(%(value_type)s))')
.Append(' return %(failure_value)s;')
- )
-
- def _GenerateChoicePopulate(self, c, 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.ExpandParams([prop]):
- (c.Sblock('case %s: {' % cpp_util.GetValueType(
- self._cpp_type_generator.GetReferencedProperty(choice).type_))
- .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('}')
-
- def _GenerateEnumPopulate(self, c, prop, value_var):
- c.Sblock('{')
- self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp')
- c.Append('%(dst)s->%(name)s = enum_temp;')
- c.Eblock('}')
-
- def _GenerateBinaryPopulate(self, c, prop):
- (c.Append('if (!%(value_var)s->IsType(%(value_type)s))')
- .Append(' return %(failure_value)s;')
- .Append('const base::BinaryValue* binary_value =')
- .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);')
- )
- if prop.optional:
- (c.Append('%(dst)s->%(name)s.reset(')
- .Append(' new std::string(binary_value->GetBuffer(),')
- .Append(' binary_value->GetSize()));')
+ .Append('const base::BinaryValue* binary_value =')
+ .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);')
)
+ if is_ptr:
+ (c.Append('%(dst_var)s.reset(')
+ .Append(' new std::string(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize()));')
+ )
+ else:
+ (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize());')
+ )
else:
- (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),')
- .Append(' binary_value->GetSize());')
- )
+ raise NotImplementedError(type_)
- def _GenerateListValueToEnumArrayConversion(self, c, prop):
- """Appends code that converts a ListValue of string contstants to
- an array of enums in dst.
- Leaves dst, name, and failure_value unsubstituted.
+ sub = {
+ 'cpp_type': self._type_helper.GetCppType(type_),
+ 'src_var': src_var,
+ 'dst_var': dst_var,
+ 'failure_value': failure_value,
+ }
- c: the Code object that is being appended to.
- prop: the property that the code is populating.
+ if underlying_type.property_type not in (PropertyType.ANY,
+ PropertyType.CHOICES):
+ sub['value_type'] = cpp_util.GetValueType(underlying_type)
+
+ return c.Eblock('}').Substitute(sub)
+
+ def _GenerateListValueToEnumArrayConversion(self,
+ item_type,
+ src_var,
+ dst_var,
+ failure_value,
+ is_ptr=False):
+ """Returns Code that converts a ListValue of string constants from
+ |src_var| into an array of enums of |type_| in |dst_var|. On failure,
+ returns |failure_value|.
"""
+ c = Code()
accessor = '.'
- if prop.optional:
- c.Append('%(dst)s->%(name)s.reset(new std::vector<' + (
- self._cpp_type_generator.GetType(prop.item_type) + '>);'))
+ if is_ptr:
accessor = '->'
- c.Sblock('for (ListValue::const_iterator it = list->begin(); '
- 'it != list->end(); ++it) {')
- self._GenerateStringToEnumConversion(
- c, prop.item_type, '(*it)', 'enum_temp')
- c.Append('%(dst)s->%(name)s' + accessor + 'push_back(enum_temp);')
- c.Eblock('}')
-
- def _GenerateStringToEnumConversion(self, c, prop, value_var, enum_temp):
- """Appends code that converts a string to an enum.
- Leaves failure_value unsubstituted.
-
- c: the code that is appended to.
- prop: the property that the code is populating.
- value_var: the string value that is being converted.
- enum_temp: the name used to store the temporary enum value.
- """
- (c.Append('std::string enum_as_string;')
- .Append('if (!%s->GetAsString(&enum_as_string))' % value_var)
- .Append(' return %(failure_value)s;')
- .Append('%(type)s %(enum)s = From%(type)sString(enum_as_string);' % {
- 'type': self._cpp_type_generator.GetCompiledType(prop),
- 'enum': enum_temp
- })
- .Append('if (%s == %s)' %
- (enum_temp, self._cpp_type_generator.GetEnumNoneValue(prop)))
- .Append(' return %(failure_value)s;'))
-
- def _GeneratePropertyFunctions(self, param_namespace, params):
- """Generate the functions for structures generated by a property such as
- CreateEnumValue for ENUMs and Populate/ToValue for Params/Results objects.
+ cpp_type = self._type_helper.GetCppType(item_type, is_in_container=True)
+ c.Append('%s.reset(new std::vector<%s>);' %
+ (dst_var, cpp_util.PadForGenerics(cpp_type)))
+ (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); '
+ 'it != %s->end(); ++it) {' % (src_var, src_var))
+ .Append('%s tmp;' % self._type_helper.GetCppType(item_type))
+ .Concat(self._GenerateStringToEnumConversion(item_type,
+ '(*it)',
+ 'tmp',
+ failure_value))
+ .Append('%s%spush_back(tmp);' % (dst_var, accessor))
+ .Eblock('}')
+ )
+ return c
+
+ def _GenerateStringToEnumConversion(self,
+ type_,
+ src_var,
+ dst_var,
+ failure_value):
+ """Returns Code that converts a string type in |src_var| to an enum with
+ type |type_| in |dst_var|. In the generated code, if |src_var| is not
+ a valid enum name then the function will return |failure_value|.
"""
c = Code()
- 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.ARRAY:
- c.Concat(self._GeneratePropertyFunctions(
- param_namespace, [param.item_type]))
- 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))
- .Append()
- .Concat(self._GenerateEnumFromString(param_namespace,
- param,
- use_namespace=True))
- .Append()
- .Concat(self._GenerateEnumToString(param_namespace,
- param,
- use_namespace=True))
- .Append())
+ enum_as_string = '%s_as_string' % type_.unix_name
+ (c.Append('std::string %s;' % enum_as_string)
+ .Append('if (!%s->GetAsString(&%s))' % (src_var, enum_as_string))
+ .Append(' return %s;' % failure_value)
+ .Append('%s = Parse%s(%s);' % (dst_var,
+ self._type_helper.GetCppType(type_),
+ enum_as_string))
+ .Append('if (%s == %s)' % (dst_var,
+ self._type_helper.GetEnumNoneValue(type_)))
+ .Append(' return %s;' % failure_value)
+ )
return c
- def _GenerateGetChoiceValue(self, cpp_namespace, prop):
- """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value>
- representing the choice value.
+ def _GeneratePropertyFunctions(self, namespace, params):
+ """Generates the member functions for a list of parameters.
"""
- c = Code()
- (c.Sblock('scoped_ptr<base::Value> '
- '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {')
- .Sblock('switch (%s_type) {' % prop.unix_name)
- .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('return scoped_ptr<base::Value>();')
- .Eblock('}')
- .Append()
- .Substitute({
- 'cpp_namespace': cpp_namespace,
- 'choice': cpp_util.Classname(prop.name)
- })
- )
- return c
+ return self._GenerateTypes(namespace, (param.type_ for param in params))
- def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop):
- """Generates CreateEnumValue() that returns the base::StringValue
- representation of an enum type.
+ def _GenerateTypes(self, namespace, types):
+ """Generates the member functions for a list of types.
"""
c = Code()
- classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name))
- (c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' %
- (classname, classname.lower()))
- .Append('std::string enum_temp = ToString(%s);' % classname.lower())
- .Append('if (enum_temp.empty())')
- .Append(' return scoped_ptr<base::Value>();')
- .Append('return scoped_ptr<base::Value>('
- 'base::Value::CreateStringValue(enum_temp));')
- .Eblock('}'))
+ for type_ in types:
+ c.Cblock(self._GenerateType(namespace, type_))
return c
- def _GenerateEnumToString(self, cpp_namespace, prop, use_namespace=False):
+ def _GenerateEnumToString(self, cpp_namespace, type_):
"""Generates ToString() which gets the string representation of an enum.
"""
c = Code()
- classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name))
- if use_namespace:
- namespace = '%s::' % cpp_namespace
- else:
- namespace = ''
+ classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
- (c.Append('// static')
- .Sblock('std::string %(namespace)sToString(%(class)s enum_param) {'))
- enum_prop = self._cpp_type_generator.GetReferencedProperty(prop)
+ if cpp_namespace is not None:
+ c.Append('// static')
+ maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
+
+ c.Sblock('std::string %sToString(%s enum_param) {' %
+ (maybe_namespace, classname))
c.Sblock('switch (enum_param) {')
- for enum_value in enum_prop.enum_values:
- c.Concat(self._GenerateReturnCase(
- self._cpp_type_generator.GetEnumValue(prop, enum_value),
- '"%s"' % enum_value))
- (c.Append('case %s:' % self._cpp_type_generator.GetEnumNoneValue(prop))
+ for enum_value in self._type_helper.FollowRef(type_).enum_values:
+ (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value))
+ .Append(' return "%s";' % enum_value))
+ (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_))
.Append(' return "";')
.Eblock('}')
+ .Append('NOTREACHED();')
.Append('return "";')
.Eblock('}')
- .Substitute({
- 'namespace': namespace,
- 'class': classname
- }))
+ )
return c
- def _GenerateEnumFromString(self, cpp_namespace, prop, use_namespace=False):
+ def _GenerateEnumFromString(self, cpp_namespace, type_):
"""Generates FromClassNameString() which gets an enum from its string
representation.
"""
c = Code()
- classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name))
- if use_namespace:
- namespace = '%s::' % cpp_namespace
- else:
- namespace = ''
+ classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
- (c.Append('// static')
- .Sblock('%(namespace)s%(class)s'
- ' %(namespace)sFrom%(class)sString('
- 'const std::string& enum_string) {'))
- enum_prop = self._cpp_type_generator.GetReferencedProperty(prop)
+ if cpp_namespace is not None:
+ c.Append('// static')
+ maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
+
+ c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' %
+ (maybe_namespace, classname, maybe_namespace, classname))
for i, enum_value in enumerate(
- self._cpp_type_generator.GetReferencedProperty(prop).enum_values):
+ self._type_helper.FollowRef(type_).enum_values):
# This is broken up into all ifs with no else ifs because we get
# "fatal error C1061: compiler limit : blocks nested too deeply"
# on Windows.
(c.Append('if (enum_string == "%s")' % enum_value)
.Append(' return %s;' %
- self._cpp_type_generator.GetEnumValue(prop, enum_value)))
- (c.Append('return %s;' %
- self._cpp_type_generator.GetEnumNoneValue(prop))
+ self._type_helper.GetEnumValue(type_, enum_value)))
+ (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_))
.Eblock('}')
- .Substitute({
- 'namespace': namespace,
- 'class': classname
- }))
- return c
-
- # TODO(chebert): This is basically the same as GenerateCreateEnumTypeValue().
- # The plan is to phase out the old-style enums, and make all enums into REF
- # types.
- def _GenerateCreateEnumValue(self, cpp_namespace, prop):
- """Generates CreateEnumValue() that returns the base::StringValue
- representation of an enum.
- """
- c = Code()
- (c.Append('// static')
- .Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue('
- '%(arg)s) {')
- .Append('std::string enum_temp = ToString(%s);' % prop.unix_name)
- .Append('if (enum_temp.empty())')
- .Append(' return scoped_ptr<base::Value>();')
- .Append('return scoped_ptr<base::Value>('
- 'base::Value::CreateStringValue(enum_temp));')
- .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_to_json=False):
+ def _GenerateCreateCallbackArguments(self, function_scope, callback):
"""Generate all functions to create Value parameters for a callback.
E.g for function "Bar", generate Bar::Results::Create
E.g for event "Baz", generate Baz::Create
function_scope: the function scope path, e.g. Foo::Bar for the function
- Foo::Bar::Baz().
+ Foo::Bar::Baz(). May be None if there is no function scope.
callback: the Function object we are creating callback arguments for.
- generate_to_json: Generate a ToJson method.
"""
c = Code()
params = callback.params
- expanded_params = self._cpp_type_generator.ExpandParams(params)
- c.Concat(self._GeneratePropertyFunctions(function_scope, expanded_params))
-
- param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params)
- for param_list in param_lists:
- (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::'
- 'Create(%(declaration_list)s) {')
- .Append('scoped_ptr<base::ListValue> create_results('
- 'new base::ListValue());')
- )
- declaration_list = []
- for param in param_list:
- # 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
- declaration_list.append("const %s" % cpp_util.GetParameterDeclaration(
- param_copy, self._cpp_type_generator.GetCompiledType(param_copy)))
- param_name = param_copy.unix_name
- if param_copy.type_ != param_copy.compiled_type:
- param_name = 'temp_' + param_name
- (c.Append('%s %s;' % (self._cpp_type_generator.GetType(param_copy),
- param_name))
- .Append(cpp_util.GenerateCompiledTypeToTypeConversion(
- param_copy,
- param_copy.unix_name,
- param_name) + ';')
- )
- c.Append('create_results->Append(%s);' %
- self._CreateValueFromProperty(param_copy, param_name))
-
- c.Append('return create_results.Pass();')
- c.Eblock('}')
- if generate_to_json:
- c.Append()
- (c.Sblock('std::string %(function_scope)s::'
- 'ToJson(%(declaration_list)s) {')
- .Append('scoped_ptr<base::ListValue> create_results = '
- '%(function_scope)s::Create(%(param_list)s);')
- .Append('std::string json;')
- .Append('base::JSONWriter::Write(create_results.get(), &json);')
- .Append('return json;')
- )
- c.Eblock('}')
-
- c.Substitute({
- 'function_scope': function_scope,
- 'declaration_list': ', '.join(declaration_list),
- 'param_list': ', '.join(param.unix_name for param in param_list)
- })
+ c.Concat(self._GeneratePropertyFunctions(function_scope, params))
+ (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
+ 'Create(%(declaration_list)s) {')
+ .Append('scoped_ptr<base::ListValue> create_results('
+ 'new base::ListValue());')
+ )
+ declaration_list = []
+ for param in params:
+ declaration_list.append(cpp_util.GetParameterDeclaration(
+ param, self._type_helper.GetCppType(param.type_)))
+ c.Append('create_results->Append(%s);' %
+ self._CreateValueFromType(param.type_, param.unix_name))
+ c.Append('return create_results.Pass();')
+ c.Eblock('}')
+ c.Substitute({
+ 'function_scope': ('%s::' % function_scope) if function_scope else '',
+ 'declaration_list': ', '.join(declaration_list),
+ 'param_names': ', '.join(param.unix_name for param in params)
+ })
return c
def _InitializePropertyToDefault(self, prop, dst):
@@ -923,33 +799,11 @@ class CCGenerator(object):
dst: Type*
"""
c = Code()
- if (self._cpp_type_generator.IsEnumOrEnumRef(prop) or
- prop.type_ == PropertyType.CHOICES):
- if prop.optional:
- prop_name = prop.unix_name
- if prop.type_ == PropertyType.CHOICES:
- prop_name = prop.unix_name + '_type'
- c.Append('%s->%s = %s;' % (
- dst,
- prop_name,
- self._cpp_type_generator.GetEnumNoneValue(prop)))
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if (underlying_type.property_type == PropertyType.ENUM and
+ prop.optional):
+ c.Append('%s->%s = %s;' % (
+ dst,
+ prop.unix_name,
+ self._type_helper.GetEnumNoneValue(prop.type_)))
return c
-
- def _IsObjectOrObjectRef(self, prop):
- """Determines if this property is an Object or is a ref to an Object.
- """
- return (self._cpp_type_generator.GetReferencedProperty(prop).type_ ==
- PropertyType.OBJECT)
-
- def _IsArrayOrArrayRef(self, prop):
- """Determines if this property is an Array or is a ref to an Array.
- """
- return (self._cpp_type_generator.GetReferencedProperty(prop).type_ ==
- PropertyType.ARRAY)
-
- def _IsFundamentalOrFundamentalRef(self, prop):
- """Determines if this property is a Fundamental type or is a ref to a
- Fundamental type.
- """
- return (self._cpp_type_generator.GetReferencedProperty(prop).type_.
- is_fundamental)
diff --git a/tools/json_schema_compiler/code.py b/tools/json_schema_compiler/code.py
index e4326d4..009eb12 100644
--- a/tools/json_schema_compiler/code.py
+++ b/tools/json_schema_compiler/code.py
@@ -56,6 +56,13 @@ class Code(object):
return self
+ def Cblock(self, code):
+ """Concatenates another Code object |code| onto this one followed by a
+ blank line, if |code| is non-empty."""
+ if not code.IsEmpty():
+ self.Concat(code).Append()
+ return self
+
def Sblock(self, line=''):
"""Starts a code block.
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index deade36..296eb41 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -3,8 +3,7 @@
# found in the LICENSE file.
from code import Code
-from model import PropertyType
-import any_helper
+from model import Namespace, PropertyType, Type
import cpp_util
import operator
import schema_util
@@ -24,42 +23,22 @@ class CppTypeGenerator(object):
if namespace and cpp_namespace:
self._namespace = namespace
self.AddNamespace(namespace, cpp_namespace)
+ else:
+ self._namespace = None
def AddNamespace(self, namespace, cpp_namespace):
"""Maps a model.Namespace to its C++ namespace name. All mappings are
beneath the root namespace.
"""
- for type_ in namespace.types:
- if type_ in self._type_namespaces:
- raise ValueError('Type %s is declared in both %s and %s' %
- (type_, namespace.name, self._type_namespaces[type_].name))
- self._type_namespaces[type_] = namespace
self._cpp_namespaces[namespace] = cpp_namespace
-
- def ExpandParams(self, params):
- """Returns the given parameters with PropertyType.CHOICES parameters
- expanded so that each choice is a separate parameter.
- """
- expanded = []
- for param in params:
- if param.type_ == PropertyType.CHOICES:
- for choice in param.choices.values():
- expanded.append(choice)
- else:
- expanded.append(param)
- return expanded
-
- def GetAllPossibleParameterLists(self, params):
- """Returns all possible parameter lists for the given set of parameters.
- Every combination of arguments passed to any of the PropertyType.CHOICES
- parameters will have a corresponding parameter list returned here.
- """
- if not params:
- return [[]]
- partial_parameter_lists = self.GetAllPossibleParameterLists(params[1:])
- return [[param] + partial_list
- for param in self.ExpandParams(params[:1])
- for partial_list in partial_parameter_lists]
+ for type_name in namespace.types:
+ # Allow $refs to refer to just 'Type' within namespaces. Otherwise they
+ # must be qualified with 'namespace.Type'.
+ type_aliases = ['%s.%s' % (namespace.name, type_name)]
+ if namespace is self._namespace:
+ type_aliases.append(type_name)
+ for alias in type_aliases:
+ self._type_namespaces[alias] = namespace
def GetCppNamespaceName(self, namespace):
"""Gets the mapped C++ namespace name for the given namespace relative to
@@ -95,106 +74,89 @@ class CppTypeGenerator(object):
return Code().Append('} // %s' %
self.GetCppNamespaceName(self._namespace))
- def GetEnumNoneValue(self, prop):
+ def GetEnumNoneValue(self, type_):
"""Gets the enum value in the given model.Property indicating no value has
been set.
"""
- return '%s_NONE' % self.GetReferencedProperty(prop).unix_name.upper()
+ return '%s_NONE' % self.FollowRef(type_).unix_name.upper()
- def GetEnumValue(self, prop, enum_value):
+ def GetEnumValue(self, type_, enum_value):
"""Gets the enum value of the given model.Property of the given type.
e.g VAR_STRING
"""
- return '%s_%s' % (self.GetReferencedProperty(prop).unix_name.upper(),
+ return '%s_%s' % (self.FollowRef(type_).unix_name.upper(),
cpp_util.Classname(enum_value.upper()))
- def GetChoicesEnumType(self, prop):
- """Gets the type of the enum for the given model.Property.
-
- e.g VarType
- """
- return cpp_util.Classname(prop.name) + 'Type'
-
- def GetType(self, prop, pad_for_generics=False, wrap_optional=False):
- return self._GetTypeHelper(prop, pad_for_generics, wrap_optional)
-
- def GetCompiledType(self, prop, pad_for_generics=False, wrap_optional=False):
- return self._GetTypeHelper(prop, pad_for_generics, wrap_optional,
- use_compiled_type=True)
-
- def _GetTypeHelper(self, prop, pad_for_generics=False, wrap_optional=False,
- use_compiled_type=False):
- """Translates a model.Property into its C++ type.
+ def GetCppType(self, type_, is_ptr=False, is_in_container=False):
+ """Translates a model.Property or model.Type into its C++ type.
If REF types from different namespaces are referenced, will resolve
using self._type_namespaces.
- Use pad_for_generics when using as a generic to avoid operator ambiguity.
+ Use |is_ptr| if the type is optional. This will wrap the type in a
+ scoped_ptr if possible (it is not possible to wrap an enum).
- Use wrap_optional to wrap the type in a scoped_ptr<T> if the Property is
- optional.
-
- Use use_compiled_type when converting from prop.type_ to prop.compiled_type.
+ Use |is_in_container| if the type is appearing in a collection, e.g. a
+ std::vector or std::map. This will wrap it in the correct type with spacing.
"""
cpp_type = None
- type_ = prop.type_ if not use_compiled_type else prop.compiled_type
-
- if type_ == PropertyType.REF:
- dependency_namespace = self._ResolveTypeNamespace(prop.ref_type)
+ if type_.property_type == PropertyType.REF:
+ ref = type_.ref_type
+ dependency_namespace = self._ResolveTypeNamespace(ref)
if not dependency_namespace:
- raise KeyError('Cannot find referenced type: %s' % prop.ref_type)
+ raise KeyError('Cannot find referenced type: %s' % ref)
if self._namespace != dependency_namespace:
cpp_type = '%s::%s' % (self._cpp_namespaces[dependency_namespace],
- schema_util.StripSchemaNamespace(prop.ref_type))
+ schema_util.StripSchemaNamespace(ref))
else:
- cpp_type = schema_util.StripSchemaNamespace(prop.ref_type)
- elif type_ == PropertyType.BOOLEAN:
+ cpp_type = schema_util.StripSchemaNamespace(ref)
+ elif type_.property_type == PropertyType.BOOLEAN:
cpp_type = 'bool'
- elif type_ == PropertyType.INTEGER:
+ elif type_.property_type == PropertyType.INTEGER:
cpp_type = 'int'
- elif type_ == PropertyType.INT64:
+ elif type_.property_type == PropertyType.INT64:
cpp_type = 'int64'
- elif type_ == PropertyType.DOUBLE:
+ elif type_.property_type == PropertyType.DOUBLE:
cpp_type = 'double'
- elif type_ == PropertyType.STRING:
+ elif type_.property_type == PropertyType.STRING:
cpp_type = 'std::string'
- elif type_ == PropertyType.ENUM:
- cpp_type = cpp_util.Classname(prop.name)
- elif type_ == PropertyType.ADDITIONAL_PROPERTIES:
- cpp_type = 'base::DictionaryValue'
- elif type_ == PropertyType.ANY:
- cpp_type = any_helper.ANY_CLASS
- elif type_ == PropertyType.OBJECT:
- cpp_type = cpp_util.Classname(prop.name)
- elif type_ == PropertyType.FUNCTION:
+ elif type_.property_type == PropertyType.ENUM:
+ cpp_type = cpp_util.Classname(type_.name)
+ elif type_.property_type == PropertyType.ANY:
+ cpp_type = 'base::Value'
+ elif (type_.property_type == PropertyType.OBJECT or
+ type_.property_type == PropertyType.CHOICES):
+ cpp_type = cpp_util.Classname(type_.name)
+ elif type_.property_type == PropertyType.FUNCTION:
# Functions come into the json schema compiler as empty objects. We can
- # record these as empty DictionaryValue's so that we know if the function
+ # record these as empty DictionaryValues so that we know if the function
# was passed in or not.
cpp_type = 'base::DictionaryValue'
- elif type_ == PropertyType.ARRAY:
- item_type = prop.item_type
- if item_type.type_ == PropertyType.REF:
- item_type = self.GetReferencedProperty(item_type)
- if item_type.type_ in (
- PropertyType.REF, PropertyType.ANY, PropertyType.OBJECT):
- cpp_type = 'std::vector<linked_ptr<%s> > '
- else:
- cpp_type = 'std::vector<%s> '
- cpp_type = cpp_type % self.GetType(
- prop.item_type, pad_for_generics=True)
- elif type_ == PropertyType.BINARY:
+ elif type_.property_type == PropertyType.ARRAY:
+ item_cpp_type = self.GetCppType(type_.item_type, is_in_container=True)
+ cpp_type = 'std::vector<%s>' % cpp_util.PadForGenerics(item_cpp_type)
+ elif type_.property_type == PropertyType.BINARY:
cpp_type = 'std::string'
else:
- raise NotImplementedError(type_)
+ raise NotImplementedError('Cannot get type of %s' % type_.property_type)
+
+ # HACK: optional ENUM is represented elsewhere with a _NONE value, so it
+ # never needs to be wrapped in pointer shenanigans.
+ # TODO(kalman): change this - but it's an exceedingly far-reaching change.
+ if not self.FollowRef(type_).property_type == PropertyType.ENUM:
+ if is_in_container and (is_ptr or not self.IsCopyable(type_)):
+ cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
+ elif is_ptr:
+ cpp_type = 'scoped_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
- # Enums aren't wrapped because C++ won't allow it. Optional enums have a
- # NONE value generated instead.
- if wrap_optional and prop.optional and not self.IsEnumOrEnumRef(prop):
- cpp_type = 'scoped_ptr<%s> ' % cpp_type
- if pad_for_generics:
- return cpp_type
- return cpp_type.strip()
+ return cpp_type
+
+ def IsCopyable(self, type_):
+ return not (self.FollowRef(type_).property_type in (PropertyType.ANY,
+ PropertyType.ARRAY,
+ PropertyType.OBJECT,
+ PropertyType.CHOICES))
def GenerateForwardDeclarations(self):
"""Returns the forward declarations for self._namespace.
@@ -207,24 +169,17 @@ class CppTypeGenerator(object):
for namespace in sorted(namespace_type_dependencies.keys(),
key=operator.attrgetter('name')):
c.Append('namespace %s {' % namespace.name)
- for type_ in sorted(namespace_type_dependencies[namespace],
- key=schema_util.StripSchemaNamespace):
- type_name = schema_util.StripSchemaNamespace(type_)
- if namespace.types[type_].type_ == PropertyType.STRING:
- c.Append('typedef std::string %s;' % type_name)
- elif namespace.types[type_].type_ == PropertyType.ARRAY:
- c.Append('typedef std::vector<%(item_type)s> %(name)s;')
- c.Substitute({
- 'name': type_name,
- 'item_type': self.GetType(namespace.types[type_].item_type,
- wrap_optional=True)})
- # Enums cannot be forward declared.
- elif namespace.types[type_].type_ != PropertyType.ENUM:
- c.Append('struct %s;' % type_name)
+ for type_name in sorted(namespace_type_dependencies[namespace],
+ key=schema_util.StripSchemaNamespace):
+ simple_type_name = schema_util.StripSchemaNamespace(type_name)
+ type_ = namespace.types[simple_type_name]
+ # Add more ways to forward declare things as necessary.
+ if type_.property_type == PropertyType.OBJECT:
+ c.Append('struct %s;' % simple_type_name)
c.Append('}')
c.Concat(self.GetNamespaceStart())
for (name, type_) in self._namespace.types.items():
- if not type_.functions and type_.type_ == PropertyType.OBJECT:
+ if not type_.functions and type_.property_type == PropertyType.OBJECT:
c.Append('struct %s;' % schema_util.StripSchemaNamespace(name))
c.Concat(self.GetNamespaceEnd())
return c
@@ -244,37 +199,32 @@ class CppTypeGenerator(object):
c.Append('#include "base/json/json_writer.h"')
return c
- def _ResolveTypeNamespace(self, ref_type):
+ def _ResolveTypeNamespace(self, qualified_name):
"""Resolves a type, which must be explicitly qualified, to its enclosing
namespace.
"""
- if ref_type in self._type_namespaces:
- return self._type_namespaces[ref_type]
- raise KeyError('Cannot resolve type: %s. Maybe it needs a namespace prefix '
- 'if it comes from another namespace?' % ref_type)
- return None
+ namespace = self._type_namespaces.get(qualified_name, None)
+ if namespace is None:
+ raise KeyError('Cannot resolve type %s. Maybe it needs a prefix '
+ 'if it comes from another namespace?' % qualified_type)
+ return namespace
- def GetReferencedProperty(self, prop):
- """Returns the property a property of type REF is referring to.
+ def FollowRef(self, type_):
+ """Follows $ref link of types to resolve the concrete type a ref refers to.
If the property passed in is not of type PropertyType.REF, it will be
returned unchanged.
"""
- if prop.type_ != PropertyType.REF:
- return prop
- return self._ResolveTypeNamespace(prop.ref_type).types.get(prop.ref_type,
- None)
+ if not type_.property_type == PropertyType.REF:
+ return type_
+ ref = type_.ref_type
- def IsEnumOrEnumRef(self, prop):
- """Returns true if the property is an ENUM or a reference to an ENUM.
- """
- return self.GetReferencedProperty(prop).type_ == PropertyType.ENUM
+ without_namespace = ref
+ if '.' in ref:
+ without_namespace = ref.split('.', 1)[1]
- def IsEnumRef(self, prop):
- """Returns true if the property is a reference to an ENUM.
- """
- return (prop.type_ == PropertyType.REF and
- self.GetReferencedProperty(prop).type_ == PropertyType.ENUM)
+ # TODO(kalman): Do we need to keep on resolving?
+ return self._ResolveTypeNamespace(ref).types[without_namespace]
def _NamespaceTypeDependencies(self):
"""Returns a dict containing a mapping of model.Namespace to the C++ type
@@ -283,16 +233,16 @@ class CppTypeGenerator(object):
dependencies = set()
for function in self._namespace.functions.values():
for param in function.params:
- dependencies |= self._PropertyTypeDependencies(param)
+ dependencies |= self._TypeDependencies(param.type_)
if function.callback:
for param in function.callback.params:
- dependencies |= self._PropertyTypeDependencies(param)
+ dependencies |= self._TypeDependencies(param.type_)
for type_ in self._namespace.types.values():
for prop in type_.properties.values():
- dependencies |= self._PropertyTypeDependencies(prop)
+ dependencies |= self._TypeDependencies(prop.type_)
for event in self._namespace.events.values():
for param in event.params:
- dependencies |= self._PropertyTypeDependencies(param)
+ dependencies |= self._TypeDependencies(param.type_)
dependency_namespaces = dict()
for dependency in dependencies:
@@ -302,18 +252,17 @@ class CppTypeGenerator(object):
dependency_namespaces[namespace].append(dependency)
return dependency_namespaces
- def _PropertyTypeDependencies(self, prop):
+ def _TypeDependencies(self, type_):
"""Recursively gets all the type dependencies of a property.
"""
deps = set()
- if prop:
- if prop.type_ == PropertyType.REF:
- deps.add(prop.ref_type)
- elif prop.type_ == PropertyType.ARRAY:
- deps = self._PropertyTypeDependencies(prop.item_type)
- elif prop.type_ == PropertyType.OBJECT:
- for p in prop.properties.values():
- deps |= self._PropertyTypeDependencies(p)
+ if type_.property_type == PropertyType.REF:
+ deps.add(type_.ref_type)
+ elif type_.property_type == PropertyType.ARRAY:
+ deps = self._TypeDependencies(type_.item_type)
+ elif type_.property_type == PropertyType.OBJECT:
+ for p in type_.properties.values():
+ deps |= self._TypeDependencies(p.type_)
return deps
def GeneratePropertyValues(self, property, line, nodoc=False):
@@ -323,20 +272,19 @@ class CppTypeGenerator(object):
if not nodoc:
c.Comment(property.description)
- if property.has_value:
+ if property.value is not None:
c.Append(line % {
- "type": self._GetPrimitiveType(property.type_),
+ "type": self.GetCppType(property.type_),
"name": property.name,
"value": property.value
})
else:
has_child_code = False
c.Sblock('namespace %s {' % property.name)
- for child_property in property.properties.values():
- child_code = self.GeneratePropertyValues(
- child_property,
- line,
- nodoc=nodoc)
+ for child_property in property.type_.properties.values():
+ child_code = self.GeneratePropertyValues(child_property,
+ line,
+ nodoc=nodoc)
if child_code:
has_child_code = True
c.Concat(child_code)
@@ -344,16 +292,3 @@ class CppTypeGenerator(object):
if not has_child_code:
c = None
return c
-
- def _GetPrimitiveType(self, type_):
- """Like |GetType| but only accepts and returns C++ primitive types.
- """
- if type_ == PropertyType.BOOLEAN:
- return 'bool'
- elif type_ == PropertyType.INTEGER:
- return 'int'
- elif type_ == PropertyType.DOUBLE:
- return 'double'
- elif type_ == PropertyType.STRING:
- return 'char*'
- raise Exception(type_ + ' is not primitive')
diff --git a/tools/json_schema_compiler/cpp_type_generator_test.py b/tools/json_schema_compiler/cpp_type_generator_test.py
index 4bfa507..2317a02 100755
--- a/tools/json_schema_compiler/cpp_type_generator_test.py
+++ b/tools/json_schema_compiler/cpp_type_generator_test.py
@@ -71,33 +71,6 @@ class CppTypeGeneratorTest(unittest.TestCase):
self.assertEquals('#include "base/string_number_conversions.h"',
manager.GenerateIncludes().Render())
-
- def testGenerateIncludesAndForwardDeclarationsMultipleTypes(self):
- m = model.Model()
- self.tabs_json[0]['types'].append(self.permissions_json[0]['types'][0])
- self.windows_json[0]['functions'].append(
- self.permissions_json[0]['functions'][1])
- # Insert 'windows' before 'tabs' in order to test that they are sorted
- # properly.
- windows = m.AddNamespace(self.windows_json[0],
- 'path/to/windows.json')
- tabs_namespace = m.AddNamespace(self.tabs_json[0],
- 'path/to/tabs.json')
- manager = CppTypeGenerator('', windows, self.windows.unix_name)
- manager.AddNamespace(tabs_namespace, self.tabs.unix_name)
- self.assertEquals('#include "path/to/tabs.h"\n'
- '#include "base/string_number_conversions.h"\n'
- '#include "base/json/json_writer.h"',
- manager.GenerateIncludes().Render())
- self.assertEquals('namespace tabs {\n'
- 'struct Permissions;\n'
- 'struct Tab;\n'
- '}\n'
- 'namespace windows {\n'
- 'struct Window;\n'
- '} // windows',
- manager.GenerateForwardDeclarations().Render())
-
def testGenerateIncludesAndForwardDeclarationsDependencies(self):
m = model.Model()
# Insert 'font_settings' before 'browser_action' in order to test that
@@ -117,98 +90,79 @@ class CppTypeGeneratorTest(unittest.TestCase):
'#include "base/string_number_conversions.h"',
manager.GenerateIncludes().Render())
self.assertEquals('namespace browserAction {\n'
- 'typedef std::vector<int> ColorArray;\n'
'}\n'
'namespace fontSettings {\n'
- 'typedef std::string FakeStringType;\n'
'}\n'
'namespace dependency_tester {\n'
'} // dependency_tester',
manager.GenerateForwardDeclarations().Render())
- def testChoicesEnum(self):
- manager = CppTypeGenerator('', self.tabs, self.tabs.unix_name)
- prop = self.tabs.functions['move'].params[0]
- self.assertEquals('TAB_IDS_ARRAY',
- manager.GetEnumValue(prop, model.PropertyType.ARRAY.name))
- self.assertEquals(
- 'TAB_IDS_INTEGER',
- manager.GetEnumValue(prop, model.PropertyType.INTEGER.name))
- self.assertEquals('TabIdsType',
- manager.GetChoicesEnumType(prop))
-
- def testGetTypeSimple(self):
+ def testGetCppTypeSimple(self):
manager = CppTypeGenerator('', self.tabs, self.tabs.unix_name)
self.assertEquals(
'int',
- manager.GetType(self.tabs.types['tabs.Tab'].properties['id']))
+ manager.GetCppType(self.tabs.types['Tab'].properties['id'].type_))
self.assertEquals(
'std::string',
- manager.GetType(self.tabs.types['tabs.Tab'].properties['status']))
+ manager.GetCppType(self.tabs.types['Tab'].properties['status'].type_))
self.assertEquals(
'bool',
- manager.GetType(self.tabs.types['tabs.Tab'].properties['selected']))
+ manager.GetCppType(self.tabs.types['Tab'].properties['selected'].type_))
def testStringAsType(self):
manager = CppTypeGenerator('', self.font_settings,
self.font_settings.unix_name)
self.assertEquals(
'std::string',
- manager.GetType(
- self.font_settings.types['fontSettings.FakeStringType']))
+ manager.GetCppType(self.font_settings.types['FakeStringType']))
def testArrayAsType(self):
manager = CppTypeGenerator('', self.browser_action,
self.browser_action.unix_name)
self.assertEquals(
'std::vector<int>',
- manager.GetType(self.browser_action.types['browserAction.ColorArray']))
+ manager.GetCppType(self.browser_action.types['ColorArray']))
- def testGetTypeArray(self):
+ def testGetCppTypeArray(self):
manager = CppTypeGenerator('', self.windows, self.windows.unix_name)
self.assertEquals(
'std::vector<linked_ptr<Window> >',
- manager.GetType(self.windows.functions['getAll'].callback.params[0]))
+ manager.GetCppType(
+ self.windows.functions['getAll'].callback.params[0].type_))
manager = CppTypeGenerator('', self.permissions, self.permissions.unix_name)
- self.assertEquals('std::vector<std::string>', manager.GetType(
- self.permissions.types['permissions.Permissions'].properties['origins']))
+ self.assertEquals(
+ 'std::vector<std::string>',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_))
- def testGetTypeLocalRef(self):
+ def testGetCppTypeLocalRef(self):
manager = CppTypeGenerator('', self.tabs, self.tabs.unix_name)
self.assertEquals(
'Tab',
- manager.GetType(self.tabs.functions['get'].callback.params[0]))
+ manager.GetCppType(self.tabs.functions['get'].callback.params[0].type_))
- def testGetTypeIncludedRef(self):
+ def testGetCppTypeIncludedRef(self):
manager = CppTypeGenerator('', self.windows, self.windows.unix_name)
manager.AddNamespace(self.tabs, self.tabs.unix_name)
self.assertEquals(
'std::vector<linked_ptr<tabs::Tab> >',
- manager.GetType(
- self.windows.types['windows.Window'].properties['tabs']))
+ manager.GetCppType(
+ self.windows.types['Window'].properties['tabs'].type_))
- def testGetTypeNotfound(self):
- prop = self.windows.types['windows.Window'].properties['tabs'].item_type
- prop.ref_type = 'Something'
- manager = CppTypeGenerator('', self.windows, self.windows.unix_name)
- self.assertRaises(KeyError, manager.GetType, prop)
-
- def testGetTypeNotimplemented(self):
- prop = self.windows.types['windows.Window'].properties['tabs'].item_type
- prop.type_ = 10
- manager = CppTypeGenerator('', self.windows, self.windows.unix_name)
- self.assertRaises(NotImplementedError, manager.GetType, prop)
-
- def testGetTypeWithPadForGeneric(self):
+ def testGetCppTypeWithPadForGeneric(self):
manager = CppTypeGenerator('', self.permissions, self.permissions.unix_name)
- self.assertEquals('std::vector<std::string> ',
- manager.GetType(
- self.permissions.types['permissions.Permissions'].properties['origins'],
- pad_for_generics=True))
+ self.assertEquals('std::vector<std::string>',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_,
+ is_in_container=False))
+ self.assertEquals('linked_ptr<std::vector<std::string> >',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_,
+ is_in_container=True))
self.assertEquals('bool',
- manager.GetType(
- self.permissions.functions['contains'].callback.params[0],
- pad_for_generics=True))
+ manager.GetCppType(
+ self.permissions.functions['contains'].callback.params[0].type_,
+ is_in_container=True))
def testNamespaceDeclaration(self):
manager = CppTypeGenerator('extensions', self.permissions,
@@ -231,33 +185,5 @@ class CppTypeGeneratorTest(unittest.TestCase):
'} // extensions',
manager.GetRootNamespaceEnd().Render())
- def testExpandParams(self):
- manager = CppTypeGenerator('extensions', self.tabs,
- self.tabs.unix_name)
- props = self.tabs.functions['move'].params
- self.assertEquals(2, len(props))
- self.assertEquals(['move_properties', 'tab_ids_array', 'tab_ids_integer'],
- sorted([x.unix_name for x in manager.ExpandParams(props)])
- )
-
- def testGetAllPossibleParameterLists(self):
- manager = CppTypeGenerator('extensions', self.tabs,
- self.tabs.unix_name)
- props = self.forbidden.functions['forbiddenParameters'].params
- self.assertEquals(4, len(props))
- param_lists = manager.GetAllPossibleParameterLists(props)
- expected_lists = [
- ['first_choice_array', 'first_string',
- 'second_choice_array', 'second_string'],
- ['first_choice_array', 'first_string',
- 'second_choice_integer', 'second_string'],
- ['first_choice_integer', 'first_string',
- 'second_choice_array', 'second_string'],
- ['first_choice_integer', 'first_string',
- 'second_choice_integer', 'second_string']]
- result_lists = sorted([[param.unix_name for param in param_list]
- for param_list in param_lists])
- self.assertEquals(expected_lists, result_lists)
-
if __name__ == '__main__':
unittest.main()
diff --git a/tools/json_schema_compiler/cpp_util.py b/tools/json_schema_compiler/cpp_util.py
index 96a5cd3..9ce14ca 100644
--- a/tools/json_schema_compiler/cpp_util.py
+++ b/tools/json_schema_compiler/cpp_util.py
@@ -1,11 +1,12 @@
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+
"""Utilies and constants specific to Chromium C++ code.
"""
from datetime import datetime
-from model import PropertyType
+from model import Property, PropertyType, Type
import os
CHROMIUM_LICENSE = (
@@ -31,7 +32,7 @@ def Classname(s):
"""
return '_'.join([x[0].upper() + x[1:] for x in s.split('.')])
-def GetAsFundamentalValue(prop, src, dst):
+def GetAsFundamentalValue(type_, src, dst):
"""Returns the C++ code for retrieving a fundamental type from a
Value into a variable.
@@ -43,7 +44,7 @@ def GetAsFundamentalValue(prop, src, dst):
PropertyType.BOOLEAN: '%s->GetAsBoolean(%s)',
PropertyType.INTEGER: '%s->GetAsInteger(%s)',
PropertyType.DOUBLE: '%s->GetAsDouble(%s)',
- }[prop.type_] % (src, dst)
+ }[type_.property_type] % (src, dst)
def GetValueType(type_):
"""Returns the Value::Type corresponding to the model.PropertyType.
@@ -58,15 +59,18 @@ def GetValueType(type_):
PropertyType.FUNCTION: 'Value::TYPE_DICTIONARY',
PropertyType.ARRAY: 'Value::TYPE_LIST',
PropertyType.BINARY: 'Value::TYPE_BINARY',
- }[type_]
+ }[type_.property_type]
def GetParameterDeclaration(param, type_):
"""Gets a parameter declaration of a given model.Property and its C++
type.
"""
- if param.type_ in (PropertyType.REF, PropertyType.OBJECT, PropertyType.ARRAY,
- PropertyType.STRING, PropertyType.ANY):
- arg = '%(type)s& %(name)s'
+ if param.type_.property_type in (PropertyType.REF,
+ PropertyType.OBJECT,
+ PropertyType.ARRAY,
+ PropertyType.STRING,
+ PropertyType.ANY):
+ arg = 'const %(type)s& %(name)s'
else:
arg = '%(type)s %(name)s'
return arg % {
@@ -82,40 +86,8 @@ def GenerateIfndefName(path, filename):
return (('%s_%s_H__' % (path, filename))
.upper().replace(os.sep, '_').replace('/', '_'))
-def GenerateTypeToCompiledTypeConversion(prop, from_, to):
- try:
- return _GenerateTypeConversionHelper(prop.type_, prop.compiled_type, from_,
- to)
- except KeyError:
- raise NotImplementedError('Conversion from %s to %s in %s not supported' %
- (prop.type_, prop.compiled_type, prop.name))
-
-def GenerateCompiledTypeToTypeConversion(prop, from_, to):
- try:
- return _GenerateTypeConversionHelper(prop.compiled_type, prop.type_, from_,
- to)
- except KeyError:
- raise NotImplementedError('Conversion from %s to %s in %s not supported' %
- (prop.compiled_type, prop.type_, prop.name))
-
-def _GenerateTypeConversionHelper(from_type, to_type, from_, to):
- """Converts from PropertyType from_type to PropertyType to_type.
-
- from_type: The PropertyType to be converted from.
- to_type: The PropertyType to be converted to.
- from_: The variable name of the type to be converted from.
- to: The variable name of the type to be converted to.
+def PadForGenerics(var):
+ """Appends a space to |var| if it ends with a >, so that it can be compiled
+ within generic types.
"""
- # TODO(mwrosen): Add support for more from/to combinations as necessary.
- return {
- PropertyType.STRING: {
- PropertyType.INTEGER: 'base::StringToInt(%(from)s, &%(to)s)',
- PropertyType.INT64: 'base::StringToInt64(%(from)s, &%(to)s)',
- },
- PropertyType.INTEGER: {
- PropertyType.STRING: '%(to)s = base::IntToString(%(from)s)',
- },
- PropertyType.INT64: {
- PropertyType.STRING: '%(to)s = base::Int64ToString(%(from)s)',
- }
- }[from_type][to_type] % {'from': from_, 'to': to}
+ return ('%s ' % var) if var.endswith('>') else var
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 05a0241..0bc44b7 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -3,7 +3,7 @@
# found in the LICENSE file.
from code import Code
-from model import PropertyType
+from model import PropertyType, Type
import cpp_util
import schema_util
@@ -11,10 +11,10 @@ class HGenerator(object):
"""A .h generator for a namespace.
"""
def __init__(self, namespace, cpp_type_generator):
- self._cpp_type_generator = cpp_type_generator
+ self._type_helper = cpp_type_generator
self._namespace = namespace
self._target_namespace = (
- self._cpp_type_generator.GetCppNamespaceName(self._namespace))
+ self._type_helper.GetCppNamespaceName(self._namespace))
def Generate(self):
"""Generates a Code object with the .h for a single namespace.
@@ -31,6 +31,7 @@ class HGenerator(object):
(c.Append('#ifndef %s' % ifndef_name)
.Append('#define %s' % ifndef_name)
.Append()
+ .Append('#include <map>')
.Append('#include <string>')
.Append('#include <vector>')
.Append()
@@ -39,24 +40,22 @@ class HGenerator(object):
.Append('#include "base/memory/linked_ptr.h"')
.Append('#include "base/memory/scoped_ptr.h"')
.Append('#include "base/values.h"')
- .Append('#include "tools/json_schema_compiler/any.h"')
.Append()
)
- c.Concat(self._cpp_type_generator.GetRootNamespaceStart())
+ c.Concat(self._type_helper.GetRootNamespaceStart())
# TODO(calamity): These forward declarations should be #includes to allow
# $ref types from other files to be used as required params. This requires
# some detangling of windows and tabs which will currently lead to circular
# #includes.
forward_declarations = (
- self._cpp_type_generator.GenerateForwardDeclarations())
+ self._type_helper.GenerateForwardDeclarations())
if not forward_declarations.IsEmpty():
(c.Append()
- .Concat(forward_declarations)
- .Append()
+ .Cblock(forward_declarations)
)
- c.Concat(self._cpp_type_generator.GetNamespaceStart())
+ c.Concat(self._type_helper.GetNamespaceStart())
c.Append()
if self._namespace.properties:
(c.Append('//')
@@ -65,21 +64,20 @@ class HGenerator(object):
.Append()
)
for property in self._namespace.properties.values():
- property_code = self._cpp_type_generator.GeneratePropertyValues(
+ property_code = self._type_helper.GeneratePropertyValues(
property,
'extern const %(type)s %(name)s;')
if property_code:
- c.Concat(property_code).Append()
+ c.Cblock(property_code)
if self._namespace.types:
(c.Append('//')
.Append('// Types')
.Append('//')
.Append()
+ .Cblock(self._GenerateTypes(self._FieldDependencyOrder(),
+ is_toplevel=True,
+ generate_typedefs=True))
)
- for type_ in self._FieldDependencyOrder():
- (c.Concat(self._GenerateType(type_))
- .Append()
- )
if self._namespace.functions:
(c.Append('//')
.Append('// Functions')
@@ -87,9 +85,7 @@ class HGenerator(object):
.Append()
)
for function in self._namespace.functions.values():
- (c.Concat(self._GenerateFunction(function))
- .Append()
- )
+ c.Cblock(self._GenerateFunction(function))
if self._namespace.events:
(c.Append('//')
.Append('// Events')
@@ -97,12 +93,9 @@ class HGenerator(object):
.Append()
)
for event in self._namespace.events.values():
- (c.Concat(self._GenerateEvent(event))
- .Append()
- )
- (c.Concat(self._cpp_type_generator.GetNamespaceEnd())
- .Concat(self._cpp_type_generator.GetRootNamespaceEnd())
- .Append()
+ c.Cblock(self._GenerateEvent(event))
+ (c.Concat(self._type_helper.GetNamespaceEnd())
+ .Cblock(self._type_helper.GetRootNamespaceEnd())
.Append('#endif // %s' % ifndef_name)
.Append()
)
@@ -129,113 +122,158 @@ class HGenerator(object):
ExpandType([], type_)
return dependency_order
- def _GenerateEnumDeclaration(self, enum_name, prop, values):
- """Generate the declaration of a C++ enum for the given property and
- values.
+ def _GenerateEnumDeclaration(self, enum_name, type_):
+ """Generate the declaration of a C++ enum.
"""
c = Code()
c.Sblock('enum %s {' % enum_name)
- c.Append(self._cpp_type_generator.GetEnumNoneValue(prop) + ',')
- for value in values:
- c.Append(self._cpp_type_generator.GetEnumValue(prop, value) + ',')
- (c.Eblock('};')
- .Append()
- )
- return c
+ c.Append(self._type_helper.GetEnumNoneValue(type_) + ',')
+ for value in type_.enum_values:
+ c.Append(self._type_helper.GetEnumValue(type_, value) + ',')
+ return c.Eblock('};')
def _GenerateFields(self, props):
"""Generates the field declarations when declaring a type.
"""
c = Code()
- # Generate the enums needed for any fields with "choices"
+ needs_blank_line = False
for prop in props:
- if prop.type_ == PropertyType.CHOICES:
- enum_name = self._cpp_type_generator.GetChoicesEnumType(prop)
- c.Append('%s %s_type;' % (enum_name, prop.unix_name))
+ if needs_blank_line:
c.Append()
-
- for prop in self._cpp_type_generator.ExpandParams(props):
+ needs_blank_line = True
if prop.description:
c.Comment(prop.description)
+ # ANY is a base::Value which is abstract and cannot be a direct member, so
+ # we always need to wrap it in a scoped_ptr.
+ is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
(c.Append('%s %s;' % (
- self._cpp_type_generator.GetCompiledType(prop, wrap_optional=True),
+ self._type_helper.GetCppType(prop.type_, is_ptr=is_ptr),
prop.unix_name))
- .Append()
)
return c
- def _GenerateType(self, type_):
- """Generates a struct for a type.
+ def _GenerateType(self, type_, is_toplevel=False, generate_typedefs=False):
+ """Generates a struct for |type_|.
+
+ |is_toplevel| implies that the type was declared in the "types" field
+ of an API schema. This determines the correct function
+ modifier(s).
+ |generate_typedefs| controls whether primitive types should be generated as
+ a typedef. This may not always be desired. If false,
+ primitive types are ignored.
"""
classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name))
c = Code()
if type_.functions:
- c.Sblock('namespace %(classname)s {')
+ # Wrap functions within types in the type's namespace.
+ (c.Append('namespace %s {' % classname)
+ .Append()
+ )
for function in type_.functions.values():
- (c.Concat(self._GenerateFunction(function))
- .Append()
- )
- c.Eblock('}')
- elif type_.type_ == PropertyType.ARRAY:
- if type_.description:
+ c.Cblock(self._GenerateFunction(function))
+ c.Append('} // namespace %s' % classname)
+ elif type_.property_type == PropertyType.ARRAY:
+ if generate_typedefs and type_.description:
c.Comment(type_.description)
- c.Append('typedef std::vector<%(item_type)s> %(classname)s;')
- c.Substitute({'classname': classname, 'item_type':
- self._cpp_type_generator.GetCompiledType(type_.item_type,
- wrap_optional=True)})
- elif type_.type_ == PropertyType.STRING:
- if type_.description:
- c.Comment(type_.description)
- c.Append('typedef std::string %(classname)s;')
- elif type_.type_ == PropertyType.ENUM:
+ c.Cblock(self._GenerateType(type_.item_type))
+ if generate_typedefs:
+ (c.Append('typedef std::vector<%s > %s;' % (
+ self._type_helper.GetCppType(type_.item_type),
+ classname))
+ )
+ elif type_.property_type == PropertyType.STRING:
+ if generate_typedefs:
+ if type_.description:
+ c.Comment(type_.description)
+ c.Append('typedef std::string %(classname)s;')
+ elif type_.property_type == PropertyType.ENUM:
if type_.description:
c.Comment(type_.description)
c.Sblock('enum %(classname)s {')
- c.Append('%s,' % self._cpp_type_generator.GetEnumNoneValue(type_))
+ c.Append('%s,' % self._type_helper.GetEnumNoneValue(type_))
for value in type_.enum_values:
- c.Append('%s,' % self._cpp_type_generator.GetEnumValue(type_, value))
+ c.Append('%s,' % self._type_helper.GetEnumValue(type_, value))
+ # Top level enums are in a namespace scope so the methods shouldn't be
+ # static. On the other hand, those declared inline (e.g. in an object) do.
+ maybe_static = '' if is_toplevel else 'static '
(c.Eblock('};')
.Append()
- .Append('scoped_ptr<base::Value> CreateEnumValue(%s %s);' %
- (classname, classname.lower()))
- .Append('std::string ToString(%s enum_param);' % classname)
- .Append('%s From%sString(const std::string& enum_string);' %
- (classname, classname))
+ .Append('%sstd::string ToString(%s as_enum);' %
+ (maybe_static, classname))
+ .Append('%s%s Parse%s(const std::string& as_string);' %
+ (maybe_static, classname, classname))
)
- else:
+ elif type_.property_type == PropertyType.OBJECT:
if type_.description:
c.Comment(type_.description)
(c.Sblock('struct %(classname)s {')
- .Append('~%(classname)s();')
.Append('%(classname)s();')
- .Append()
- .Concat(self._GeneratePropertyStructures(type_.properties.values()))
- .Concat(self._GenerateFields(type_.properties.values()))
+ .Append('~%(classname)s();')
)
- if type_.from_json:
- (c.Comment('Populates a %s object from a base::Value. Returns'
+ if type_.origin.from_json:
+ (c.Append()
+ .Comment('Populates a %s object from a base::Value. Returns'
' whether |out| was successfully populated.' % classname)
.Append('static bool Populate(const base::Value& value, '
'%(classname)s* out);')
- .Append()
)
-
- if type_.from_client:
- (c.Comment('Returns a new base::DictionaryValue representing the'
- ' serialized form of this %s object. Passes '
- 'ownership to caller.' % classname)
+ if type_.origin.from_client:
+ (c.Append()
+ .Comment('Returns a new base::DictionaryValue representing the'
+ ' serialized form of this %s object.' % classname)
.Append('scoped_ptr<base::DictionaryValue> ToValue() const;')
)
-
+ properties = type_.properties.values()
+ (c.Append()
+ .Cblock(self._GenerateTypes(p.type_ for p in properties))
+ .Cblock(self._GenerateFields(properties)))
+ if type_.additional_properties is not None:
+ # Most additionalProperties actually have type "any", which is better
+ # modelled as a DictionaryValue rather than a map of string -> Value.
+ if type_.additional_properties.property_type == PropertyType.ANY:
+ c.Append('base::DictionaryValue additional_properties;')
+ else:
+ (c.Cblock(self._GenerateType(type_.additional_properties))
+ .Append('std::map<std::string, %s> additional_properties;' %
+ cpp_util.PadForGenerics(
+ self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)))
+ )
(c.Eblock()
.Sblock(' private:')
- .Concat(self._GeneratePrivatePropertyStructures(
- type_.properties.values()))
- .Append()
.Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
.Eblock('};')
)
+ elif type_.property_type == PropertyType.CHOICES:
+ if type_.description:
+ c.Comment(type_.description)
+ # Choices are modelled with optional fields for each choice. Exactly one
+ # field of the choice is guaranteed to be set by the compiler.
+ (c.Sblock('struct %(classname)s {')
+ .Append('%(classname)s();')
+ .Append('~%(classname)s();')
+ .Append())
+ c.Cblock(self._GenerateTypes(type_.choices))
+ if type_.origin.from_json:
+ (c.Comment('Populates a %s object from a base::Value. Returns'
+ ' whether |out| was successfully populated.' % classname)
+ .Append('static bool Populate(const base::Value& value, '
+ '%(classname)s* out);')
+ .Append()
+ )
+ if type_.origin.from_client:
+ (c.Comment('Returns a new base::Value representing the'
+ ' serialized form of this %s object.' % classname)
+ .Append('scoped_ptr<base::Value> ToValue() const;')
+ .Append()
+ )
+ c.Append('// Choices:')
+ for choice_type in type_.choices:
+ c.Append('%s as_%s;' % (
+ self._type_helper.GetCppType(choice_type, is_ptr=True),
+ choice_type.unix_name))
+ c.Eblock('};')
c.Substitute({'classname': classname})
return c
@@ -243,10 +281,12 @@ class HGenerator(object):
"""Generates the namespaces for an event.
"""
c = Code()
- (c.Sblock('namespace %s {' % cpp_util.Classname(event.name))
- .Concat(self._GenerateCreateCallbackArguments(event,
- generate_to_json=True))
- .Eblock('};')
+ # TODO(kalman): use event.unix_name not Classname.
+ event_namespace = cpp_util.Classname(event.name)
+ (c.Append('namespace %s {' % event_namespace)
+ .Append()
+ .Concat(self._GenerateCreateCallbackArguments(event))
+ .Eblock('} // namespace %s' % event_namespace)
)
return c
@@ -254,125 +294,74 @@ class HGenerator(object):
"""Generates the namespaces and structs for a function.
"""
c = Code()
- (c.Sblock('namespace %s {' % cpp_util.Classname(function.name))
- .Concat(self._GenerateFunctionParams(function))
- .Append()
+ # TODO(kalman): Use function.unix_name not Classname here.
+ function_namespace = cpp_util.Classname(function.name)
+ (c.Append('namespace %s {' % function_namespace)
+ .Append()
+ .Cblock(self._GenerateFunctionParams(function))
)
if function.callback:
- (c.Concat(self._GenerateFunctionResults(function.callback))
- .Append()
- )
- c.Eblock('};')
-
+ c.Cblock(self._GenerateFunctionResults(function.callback))
+ c.Append('} // namespace %s' % function_namespace)
return c
def _GenerateFunctionParams(self, function):
"""Generates the struct for passing parameters from JSON to a function.
"""
- c = Code()
-
- if function.params:
- (c.Sblock('struct Params {')
- .Concat(self._GeneratePropertyStructures(function.params))
- .Concat(self._GenerateFields(function.params))
- .Append('~Params();')
- .Append()
- .Append('static scoped_ptr<Params> Create('
- 'const base::ListValue& args);')
- .Eblock()
- .Sblock(' private:')
- .Append('Params();')
- .Append()
- .Append('DISALLOW_COPY_AND_ASSIGN(Params);')
- .Eblock('};')
- )
+ if not function.params:
+ return Code()
+ c = Code()
+ (c.Sblock('struct Params {')
+ .Append('static scoped_ptr<Params> Create(const base::ListValue& args);')
+ .Append('~Params();')
+ .Append()
+ .Cblock(self._GenerateTypes(p.type_ for p in function.params))
+ .Cblock(self._GenerateFields(function.params))
+ .Eblock()
+ .Sblock(' private:')
+ .Append('Params();')
+ .Append()
+ .Append('DISALLOW_COPY_AND_ASSIGN(Params);')
+ .Eblock('};')
+ )
return c
- def _GeneratePropertyStructures(self, props):
+ def _GenerateTypes(self, types, is_toplevel=False, generate_typedefs=False):
"""Generate the structures required by a property such as OBJECT classes
and enums.
"""
c = Code()
- for prop in props:
- if prop.type_ == PropertyType.OBJECT:
- c.Concat(self._GenerateType(prop))
- c.Append()
- elif prop.type_ == PropertyType.ARRAY:
- c.Concat(self._GeneratePropertyStructures([prop.item_type]))
- c.Append()
- elif prop.type_ == PropertyType.CHOICES:
- c.Concat(self._GenerateEnumDeclaration(
- self._cpp_type_generator.GetChoicesEnumType(prop),
- prop,
- [choice.type_.name for choice in prop.choices.values()]))
- c.Concat(self._GeneratePropertyStructures(prop.choices.values()))
- elif prop.type_ == PropertyType.ENUM:
- enum_name = self._cpp_type_generator.GetCompiledType(prop)
- c.Concat(self._GenerateEnumDeclaration(
- enum_name,
- prop,
- prop.enum_values))
- create_enum_value = ('scoped_ptr<base::Value> CreateEnumValue(%s %s);' %
- (enum_name, prop.unix_name))
- enum_to_string = 'std::string ToString(%s enum_param);' % enum_name
- enum_from_string = ('%s From%sString(const std::string& enum_string);' %
- (enum_name, enum_name))
- # If the property is from the UI then we're in a struct so this function
- # should be static. If it's from the client, then we're just in a
- # namespace so we can't have the static keyword.
- if prop.from_json:
- create_enum_value = 'static %s' % create_enum_value
- enum_to_string = 'static %s' % enum_to_string
- enum_from_string = 'static %s' % enum_from_string
- (c.Append(create_enum_value)
- .Append(enum_to_string)
- .Append(enum_from_string))
- 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)))
+ for type_ in types:
+ c.Cblock(self._GenerateType(type_,
+ is_toplevel=is_toplevel,
+ generate_typedefs=generate_typedefs))
return c
- def _GenerateCreateCallbackArguments(self, function, generate_to_json=False):
- """Generates functions for passing paramaters to a callback.
+ def _GenerateCreateCallbackArguments(self, function):
+ """Generates functions for passing parameters to a callback.
"""
c = Code()
params = function.params
- c.Concat(self._GeneratePropertyStructures(params))
+ c.Cblock(self._GenerateTypes((p.type_ for p in params), is_toplevel=True))
- param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params)
- for param_list in param_lists:
- declaration_list = []
- for param in param_list:
- if param.description:
- c.Comment(param.description)
- declaration_list.append('const %s' % cpp_util.GetParameterDeclaration(
- param, self._cpp_type_generator.GetCompiledType(param)))
- c.Append('scoped_ptr<base::ListValue> Create(%s);' %
- ', '.join(declaration_list))
- if generate_to_json:
- c.Append('std::string ToJson(%s);' % ', '.join(declaration_list))
+ declaration_list = []
+ for param in params:
+ if param.description:
+ c.Comment(param.description)
+ declaration_list.append(cpp_util.GetParameterDeclaration(
+ param, self._type_helper.GetCppType(param.type_)))
+ c.Append('scoped_ptr<base::ListValue> Create(%s);' %
+ ', '.join(declaration_list))
return c
def _GenerateFunctionResults(self, callback):
"""Generates namespace for passing a function's result back.
"""
c = Code()
- (c.Sblock('namespace Results {')
- .Concat(self._GenerateCreateCallbackArguments(callback))
- .Eblock('};')
+ (c.Append('namespace Results {')
+ .Append()
+ .Concat(self._GenerateCreateCallbackArguments(callback))
+ .Append('} // namespace Results')
)
return c
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py
index 30dad11..907aacf 100644
--- a/tools/json_schema_compiler/idl_schema.py
+++ b/tools/json_schema_compiler/idl_schema.py
@@ -352,7 +352,6 @@ class IDLSchema(object):
continue
else:
sys.exit('Did not process %s %s' % (node.cls, node))
- schema_util.PrefixSchemasWithNamespace(namespaces)
return namespaces
def Load(filename):
diff --git a/tools/json_schema_compiler/idl_schema_test.py b/tools/json_schema_compiler/idl_schema_test.py
index a4fd0d8..873333b 100755
--- a/tools/json_schema_compiler/idl_schema_test.py
+++ b/tools/json_schema_compiler/idl_schema_test.py
@@ -38,14 +38,14 @@ class IdlSchemaTest(unittest.TestCase):
self.assertEquals(expected, getParams(schema, 'function5'))
expected = [{'type':'function', 'name':'cb',
- 'parameters':[{'name':'arg', '$ref':'idl_basics.MyType1'}]}]
+ 'parameters':[{'name':'arg', '$ref':'MyType1'}]}]
self.assertEquals(expected, getParams(schema, 'function6'))
def testCallbackWithArrayArgument(self):
schema = self.idl_basics
expected = [{'type':'function', 'name':'cb',
'parameters':[{'name':'arg', 'type':'array',
- 'items':{'$ref':'idl_basics.MyType2'}}]}]
+ 'items':{'$ref':'MyType2'}}]}]
self.assertEquals(expected, getParams(schema, 'function12'))
@@ -61,20 +61,20 @@ class IdlSchemaTest(unittest.TestCase):
'x': {'name': 'x', 'type': 'integer', 'enum': [1,2],
'description': 'This comment tests "double-quotes".'},
'y': {'name': 'y', 'type': 'string'}},
- getType(self.idl_basics, 'idl_basics.MyType1')['properties'])
+ getType(self.idl_basics, 'MyType1')['properties'])
def testEnum(self):
schema = self.idl_basics
expected = {'enum': ['name1', 'name2'], 'description': 'Enum description',
- 'type': 'string', 'id': 'idl_basics.EnumType'}
+ 'type': 'string', 'id': 'EnumType'}
self.assertEquals(expected, getType(schema, expected['id']))
- expected = [{'name':'type', '$ref':'idl_basics.EnumType'},
+ expected = [{'name':'type', '$ref':'EnumType'},
{'type':'function', 'name':'cb',
- 'parameters':[{'name':'type', '$ref':'idl_basics.EnumType'}]}]
+ 'parameters':[{'name':'type', '$ref':'EnumType'}]}]
self.assertEquals(expected, getParams(schema, 'function13'))
- expected = [{'items': {'$ref': 'idl_basics.EnumType'}, 'name': 'types',
+ expected = [{'items': {'$ref': 'EnumType'}, 'name': 'types',
'type': 'array'}]
self.assertEquals(expected, getParams(schema, 'function14'))
@@ -114,7 +114,7 @@ class IdlSchemaTest(unittest.TestCase):
[{'description': ('So should this comment about the argument. '
'<em>HTML</em> is fine too.'),
'name': 'arg',
- '$ref': 'idl_basics.MyType1'}],
+ '$ref': 'MyType1'}],
func['parameters'])
func = getFunction(schema, 'function4')
self.assertEquals(('This tests if "double-quotes" are escaped correctly.'
@@ -124,21 +124,21 @@ class IdlSchemaTest(unittest.TestCase):
def testReservedWords(self):
schema = idl_schema.Load('test/idl_reserved_words.idl')[0]
- foo_type = getType(schema, 'reserved_words.Foo')
+ foo_type = getType(schema, 'Foo')
self.assertEquals(['float', 'DOMString'], foo_type['enum'])
- enum_type = getType(schema, 'reserved_words.enum')
+ enum_type = getType(schema, 'enum')
self.assertEquals(['callback', 'namespace'], enum_type['enum'])
- dictionary = getType(schema, 'reserved_words.dictionary');
+ dictionary = getType(schema, 'dictionary');
self.assertEquals('integer', dictionary['properties']['long']['type'])
- mytype = getType(schema, 'reserved_words.MyType')
+ mytype = getType(schema, 'MyType')
self.assertEquals('string', mytype['properties']['interface']['type'])
params = getParams(schema, 'static')
- self.assertEquals('reserved_words.Foo', params[0]['$ref'])
- self.assertEquals('reserved_words.enum', params[1]['$ref'])
+ self.assertEquals('Foo', params[0]['$ref'])
+ self.assertEquals('enum', params[1]['$ref'])
if __name__ == '__main__':
unittest.main()
diff --git a/tools/json_schema_compiler/json_schema.py b/tools/json_schema_compiler/json_schema.py
index 370bc9b..8ee53a8 100644
--- a/tools/json_schema_compiler/json_schema.py
+++ b/tools/json_schema_compiler/json_schema.py
@@ -31,7 +31,6 @@ def DeleteNocompileNodes(item):
def Load(filename):
with open(filename, 'r') as handle:
schemas = json_parse.Parse(handle.read())
- schema_util.PrefixSchemasWithNamespace(schemas)
return schemas
# A dictionary mapping |filename| to the object resulting from loading the JSON
diff --git a/tools/json_schema_compiler/model.py b/tools/json_schema_compiler/model.py
index 36be5a3..63794279 100644
--- a/tools/json_schema_compiler/model.py
+++ b/tools/json_schema_compiler/model.py
@@ -60,76 +60,129 @@ class Namespace(object):
self.source_file_dir, self.source_file_filename = os.path.split(source_file)
self.parent = None
self.platforms = _GetPlatforms(json)
- _AddTypes(self, json, self)
- _AddFunctions(self, json, self)
- _AddEvents(self, json, self)
- _AddProperties(self, json, self)
+ toplevel_origin = Origin(from_client=True, from_json=True)
+ self.types = _GetTypes(self, json, self, toplevel_origin)
+ self.functions = _GetFunctions(self, json, self)
+ self.events = _GetEvents(self, json, self)
+ self.properties = _GetProperties(self, json, self, toplevel_origin)
if include_compiler_options:
self.compiler_options = json.get('compiler_options', {})
+class Origin(object):
+ """Stores the possible origin of model object as a pair of bools. These are:
+
+ |from_client| indicating that instances can originate from users of
+ generated code (for example, function results), or
+ |from_json| indicating that instances can originate from the JSON (for
+ example, function parameters)
+
+ It is possible for model objects to originate from both the client and json,
+ for example Types defined in the top-level schema, in which case both
+ |from_client| and |from_json| would be True.
+ """
+ def __init__(self, from_client=False, from_json=False):
+ if not from_client and not from_json:
+ raise ValueError('One of from_client or from_json must be true')
+ self.from_client = from_client
+ self.from_json = from_json
+
class Type(object):
"""A Type defined in the json.
Properties:
- |name| the type name
+ - |namespace| the Type's namespace
- |description| the description of the type (if provided)
- |properties| a map of property unix_names to their model.Property
- |functions| a map of function names to their model.Function
- |events| a map of event names to their model.Event
- - |from_client| indicates that instances of the Type can originate from the
- users of generated code, such as top-level types and function results
- - |from_json| indicates that instances of the Type can originate from the
- JSON (as described by the schema), such as top-level types and function
- parameters
- - |type_| the PropertyType of this Type
+ - |origin| the Origin of the type
+ - |property_type| the PropertyType of this Type
- |item_type| if this is an array, the type of items in the array
- |simple_name| the name of this Type without a namespace
+ - |additional_properties| the type of the additional properties, if any is
+ specified
"""
- def __init__(self, parent, name, json, namespace):
- if json.get('type') == 'array':
- self.type_ = PropertyType.ARRAY
- self.item_type = Property(self,
- name + "Element",
- json['items'],
- namespace,
- from_json=True,
- from_client=True)
- elif 'enum' in json:
- self.enum_values = []
- for value in json['enum']:
- self.enum_values.append(value)
- self.type_ = PropertyType.ENUM
- elif json.get('type') == 'string':
- self.type_ = PropertyType.STRING
- else:
+ def __init__(self,
+ parent,
+ name,
+ json,
+ namespace,
+ origin):
+ self.name = name
+ self.namespace = namespace
+ self.simple_name = _StripNamespace(self.name, namespace)
+ self.unix_name = UnixName(self.name)
+ self.description = json.get('description', None)
+ self.origin = origin
+ self.parent = parent
+ self.instance_of = json.get('isInstanceOf', None)
+
+ # TODO(kalman): Only objects need functions/events/properties, but callers
+ # assume that all types have them. Fix this.
+ self.functions = _GetFunctions(self, json, namespace)
+ self.events = _GetEvents(self, json, namespace)
+ self.properties = _GetProperties(self, json, namespace, origin)
+
+ json_type = json.get('type', None)
+ if json_type == 'array':
+ self.property_type = PropertyType.ARRAY
+ self.item_type = Type(
+ self, '%sType' % name, json['items'], namespace, origin)
+ elif '$ref' in json:
+ self.property_type = PropertyType.REF
+ self.ref_type = json['$ref']
+ elif 'enum' in json and json_type == 'string':
+ self.property_type = PropertyType.ENUM
+ self.enum_values = [value for value in json['enum']]
+ elif json_type == 'any':
+ self.property_type = PropertyType.ANY
+ elif json_type == 'binary':
+ self.property_type = PropertyType.BINARY
+ elif json_type == 'boolean':
+ self.property_type = PropertyType.BOOLEAN
+ elif json_type == 'integer':
+ self.property_type = PropertyType.INTEGER
+ elif (json_type == 'double' or
+ json_type == 'number'):
+ self.property_type = PropertyType.DOUBLE
+ elif json_type == 'string':
+ self.property_type = PropertyType.STRING
+ elif 'choices' in json:
+ self.property_type = PropertyType.CHOICES
+ self.choices = [Type(self,
+ # The name of the choice type - there had better be
+ # either a type or a $ref specified for the choice.
+ json.get('type', json.get('$ref')),
+ json,
+ namespace,
+ origin)
+ for json in json['choices']]
+ elif json_type == 'object':
if not (
'properties' in json or
'additionalProperties' in json or
'functions' in json or
'events' in json):
raise ParseException(self, name + " has no properties or functions")
- self.type_ = PropertyType.OBJECT
- self.name = name
- self.simple_name = _StripNamespace(self.name, namespace)
- self.unix_name = UnixName(self.name)
- self.description = json.get('description')
- self.from_json = True
- self.from_client = True
- self.parent = parent
- self.instance_of = json.get('isInstanceOf', None)
- _AddFunctions(self, json, namespace)
- _AddEvents(self, json, namespace)
- _AddProperties(self, json, namespace, from_json=True, from_client=True)
-
- additional_properties_key = 'additionalProperties'
- additional_properties = json.get(additional_properties_key)
- if additional_properties:
- self.properties[additional_properties_key] = Property(
- self,
- additional_properties_key,
- additional_properties,
- namespace,
- is_additional_properties=True)
+ self.property_type = PropertyType.OBJECT
+ additional_properties_json = json.get('additionalProperties', None)
+ if additional_properties_json is not None:
+ self.additional_properties = Type(self,
+ 'additionalProperties',
+ additional_properties_json,
+ namespace,
+ origin)
+ else:
+ self.additional_properties = None
+ elif json_type == 'function':
+ self.property_type = PropertyType.FUNCTION
+ # Sometimes we might have an unnamed function, e.g. if it's a property
+ # of an object. Use the name of the property in that case.
+ function_name = json.get('name', name)
+ self.function = Function(self, function_name, json, namespace, origin)
+ else:
+ raise ParseException(self, 'Unsupported JSON type %s' % json_type)
class Function(object):
"""A Function defined in the API.
@@ -149,11 +202,11 @@ class Function(object):
"""
def __init__(self,
parent,
+ name,
json,
namespace,
- from_json=False,
- from_client=False):
- self.name = json['name']
+ origin):
+ self.name = name
self.simple_name = _StripNamespace(self.name, namespace)
self.platforms = _GetPlatforms(json)
self.params = []
@@ -167,18 +220,14 @@ class Function(object):
self.actions = options.get('actions', [])
self.supports_listeners = options.get('supportsListeners', True)
self.supports_rules = options.get('supportsRules', False)
+
def GeneratePropertyFromParam(p):
- return Property(self,
- p['name'], p,
- namespace,
- from_json=from_json,
- from_client=from_client)
+ return Property.FromJSON(self, p['name'], p, namespace, origin)
self.filters = [GeneratePropertyFromParam(filter)
for filter in json.get('filters', [])]
callback_param = None
for param in json.get('parameters', []):
-
if param.get('type') == 'function':
if callback_param:
# No ParseException because the webstore has this.
@@ -190,153 +239,97 @@ class Function(object):
if callback_param:
self.callback = Function(self,
+ callback_param['name'],
callback_param,
namespace,
- from_client=True)
+ Origin(from_client=True))
self.returns = None
if 'returns' in json:
- self.returns = Property(self, 'return', json['returns'], namespace)
+ self.returns = Property.FromJSON(
+ self, 'return', json['returns'], namespace, origin)
class Property(object):
"""A property of a type OR a parameter to a function.
-
Properties:
- |name| name of the property as in the json. This shouldn't change since
it is the key used to access DictionaryValues
- |unix_name| the unix_style_name of the property. Used as variable name
- |optional| a boolean representing whether the property is optional
- |description| a description of the property (if provided)
- - |type_| the model.PropertyType of this property
- - |compiled_type| the model.PropertyType that this property should be
- compiled to from the JSON. Defaults to |type_|.
- - |ref_type| the type that the REF property is referencing. Can be used to
- map to its model.Type
- - |item_type| a model.Property representing the type of each element in an
- ARRAY
- - |properties| the properties of an OBJECT parameter
- - |from_client| indicates that instances of the Type can originate from the
- users of generated code, such as top-level types and function results
- - |from_json| indicates that instances of the Type can originate from the
- JSON (as described by the schema), such as top-level types and function
- parameters
+ - |type_| the model.Type of this property
- |simple_name| the name of this Property without a namespace
"""
+ @staticmethod
+ def FromJSON(parent, name, json, namespace, origin):
+ """Creates a Property from JSON.
+ """
+ opt_args = {}
+ if 'description' in json:
+ opt_args['description'] = json['description']
+ if 'optional' in json:
+ opt_args['optional'] = json.get('optional')
+ if 'isInstanceOf' in json:
+ opt_args['instance_of'] = json.get('isInstanceOf')
+
+ # HACK: only support very specific value types.
+ is_allowed_value = (
+ '$ref' not in json and
+ ('type' not in json or json['type'] == 'integer'
+ or json['type'] == 'string'))
+
+ if 'value' in json and is_allowed_value:
+ value = json['value']
+ opt_args['value'] = value
+ if 'type' not in json:
+ # Sometimes the type of the value is left out, and we need to figure
+ # it out for ourselves.
+ if isinstance(value, int):
+ json['type'] = 'integer'
+ elif isinstance(value, basestring):
+ json['type'] = 'string'
+ else:
+ # TODO(kalman): support more types as necessary.
+ raise ParseException(
+ parent, '"%s" is not a supported type for "value"' % type(value))
+
+ type_ = Type(parent, name, json, namespace, origin)
+ return Property(parent,
+ name,
+ namespace,
+ type_,
+ origin,
+ **opt_args);
+
def __init__(self,
parent,
name,
- json,
namespace,
- is_additional_properties=False,
- from_json=False,
- from_client=False):
+ type_,
+ origin,
+ description=None,
+ optional=False,
+ returns=None,
+ instance_of=None,
+ value=None):
+ """Directly initializes the fields of the Property.
+ """
self.name = name
self.simple_name = _StripNamespace(self.name, namespace)
self._unix_name = UnixName(self.name)
self._unix_name_used = False
- self.optional = json.get('optional', False)
- self.functions = OrderedDict()
- self.has_value = False
- self.description = json.get('description')
+ self.optional = optional
+ self.description = description
self.parent = parent
- self.from_json = from_json
- self.from_client = from_client
- self.instance_of = json.get('isInstanceOf', None)
- self.params = []
- self.returns = None
- _AddProperties(self, json, namespace)
- if is_additional_properties:
- self.type_ = PropertyType.ADDITIONAL_PROPERTIES
- elif '$ref' in json:
- self.ref_type = json['$ref']
- self.type_ = PropertyType.REF
- elif 'enum' in json and json.get('type') == 'string':
- # Non-string enums (as in the case of [legalValues=(1,2)]) should fall
- # through to the next elif.
- self.enum_values = []
- for value in json['enum']:
- self.enum_values.append(value)
- self.type_ = PropertyType.ENUM
- elif 'type' in json:
- self.type_ = self._JsonTypeToPropertyType(json['type'])
- if self.type_ == PropertyType.ARRAY:
- self.item_type = Property(self,
- name + "Element",
- json['items'],
- namespace,
- from_json=from_json,
- from_client=from_client)
- elif self.type_ == PropertyType.OBJECT:
- # These members are read when this OBJECT Property is used as a Type
- type_ = Type(self, self.name, json, namespace)
- # self.properties will already have some value from |_AddProperties|.
- self.properties.update(type_.properties)
- self.functions = type_.functions
- elif self.type_ == PropertyType.FUNCTION:
- for p in json.get('parameters', []):
- self.params.append(Property(self,
- p['name'],
- p,
- namespace,
- from_json=from_json,
- from_client=from_client))
- if 'returns' in json:
- self.returns = Property(self, 'return', json['returns'], namespace)
- elif 'choices' in json:
- if not json['choices'] or len(json['choices']) == 0:
- raise ParseException(self, 'Choices has no choices')
- self.choices = {}
- self.type_ = PropertyType.CHOICES
- self.compiled_type = self.type_
- for choice_json in json['choices']:
- choice = Property(self,
- self.name,
- choice_json,
- namespace,
- from_json=from_json,
- from_client=from_client)
- choice.unix_name = UnixName(self.name + choice.type_.name)
- # The existence of any single choice is optional
- choice.optional = True
- self.choices[choice.type_] = choice
- elif 'value' in json:
- self.has_value = True
- self.value = json['value']
- if type(self.value) == int:
- self.type_ = PropertyType.INTEGER
- self.compiled_type = self.type_
- else:
- # TODO(kalman): support more types as necessary.
- raise ParseException(
- self, '"%s" is not a supported type' % type(self.value))
- else:
- raise ParseException(
- self, 'Property has no type, $ref, choices, or value')
- if 'compiled_type' in json:
- if 'type' in json:
- self.compiled_type = self._JsonTypeToPropertyType(json['compiled_type'])
- else:
- raise ParseException(self, 'Property has compiled_type but no type')
- else:
- self.compiled_type = self.type_
-
- def _JsonTypeToPropertyType(self, json_type):
- try:
- return {
- 'any': PropertyType.ANY,
- 'array': PropertyType.ARRAY,
- 'binary': PropertyType.BINARY,
- 'boolean': PropertyType.BOOLEAN,
- 'integer': PropertyType.INTEGER,
- 'int64': PropertyType.INT64,
- 'function': PropertyType.FUNCTION,
- 'number': PropertyType.DOUBLE,
- 'object': PropertyType.OBJECT,
- 'string': PropertyType.STRING,
- }[json_type]
- except KeyError:
- raise NotImplementedError('Type %s not recognized' % json_type)
+ self.origin = origin
+ if not isinstance(type_, Type):
+ raise ValueError("not Type: %s" % type_)
+ self.type_ = type_
+ self.returns = returns
+ if instance_of is not None:
+ self.instance_of = instance_of
+ self.value = value
def GetUnixName(self):
"""Gets the property's unix_name. Raises AttributeError if not set.
@@ -359,14 +352,6 @@ class Property(object):
(self.name, self._unix_name))
self._unix_name = unix_name
- def Copy(self):
- """Makes a copy of this model.Property object and allow the unix_name to be
- set again.
- """
- property_copy = copy.copy(self)
- property_copy._unix_name_used = False
- return property_copy
-
unix_name = property(GetUnixName, SetUnixName)
class _Enum(object):
@@ -403,20 +388,19 @@ class _PropertyTypeInfo(_Enum):
class PropertyType(object):
"""Enum of different types of properties/parameters.
"""
- INTEGER = _PropertyTypeInfo(True, "INTEGER")
- INT64 = _PropertyTypeInfo(True, "INT64")
- DOUBLE = _PropertyTypeInfo(True, "DOUBLE")
- BOOLEAN = _PropertyTypeInfo(True, "BOOLEAN")
- STRING = _PropertyTypeInfo(True, "STRING")
- ENUM = _PropertyTypeInfo(False, "ENUM")
- ARRAY = _PropertyTypeInfo(False, "ARRAY")
- REF = _PropertyTypeInfo(False, "REF")
- CHOICES = _PropertyTypeInfo(False, "CHOICES")
- OBJECT = _PropertyTypeInfo(False, "OBJECT")
- FUNCTION = _PropertyTypeInfo(False, "FUNCTION")
- BINARY = _PropertyTypeInfo(False, "BINARY")
- ANY = _PropertyTypeInfo(False, "ANY")
- ADDITIONAL_PROPERTIES = _PropertyTypeInfo(False, "ADDITIONAL_PROPERTIES")
+ INTEGER = _PropertyTypeInfo(True, "integer")
+ INT64 = _PropertyTypeInfo(True, "int64")
+ DOUBLE = _PropertyTypeInfo(True, "double")
+ BOOLEAN = _PropertyTypeInfo(True, "boolean")
+ STRING = _PropertyTypeInfo(True, "string")
+ ENUM = _PropertyTypeInfo(False, "enum")
+ ARRAY = _PropertyTypeInfo(False, "array")
+ REF = _PropertyTypeInfo(False, "ref")
+ CHOICES = _PropertyTypeInfo(False, "choices")
+ OBJECT = _PropertyTypeInfo(False, "object")
+ FUNCTION = _PropertyTypeInfo(False, "function")
+ BINARY = _PropertyTypeInfo(False, "binary")
+ ANY = _PropertyTypeInfo(False, "any")
def UnixName(name):
"""Returns the unix_style name for a given lowerCamelCase string.
@@ -436,57 +420,57 @@ def _StripNamespace(name, namespace):
def _GetModelHierarchy(entity):
"""Returns the hierarchy of the given model entity."""
hierarchy = []
- while entity:
- try:
- hierarchy.append(entity.name)
- except AttributeError:
- hierarchy.append(repr(entity))
- entity = entity.parent
+ while entity is not None:
+ hierarchy.append(getattr(entity, 'name', repr(entity)))
+ if isinstance(entity, Namespace):
+ hierarchy.insert(0, ' in %s' % entity.source_file)
+ entity = getattr(entity, 'parent', None)
hierarchy.reverse()
return hierarchy
-def _AddTypes(model, json, namespace):
- """Adds Type objects to |model| contained in the 'types' field of |json|.
+def _GetTypes(parent, json, namespace, origin):
+ """Creates Type objects extracted from |json|.
"""
- model.types = OrderedDict()
+ types = OrderedDict()
for type_json in json.get('types', []):
- type_ = Type(model, type_json['id'], type_json, namespace)
- model.types[type_.name] = type_
+ type_ = Type(parent, type_json['id'], type_json, namespace, origin)
+ types[type_.name] = type_
+ return types
-def _AddFunctions(model, json, namespace):
- """Adds Function objects to |model| contained in the 'functions' field of
- |json|.
+def _GetFunctions(parent, json, namespace):
+ """Creates Function objects extracted from |json|.
"""
- model.functions = OrderedDict()
+ functions = OrderedDict()
for function_json in json.get('functions', []):
- function = Function(model, function_json, namespace, from_json=True)
- model.functions[function.name] = function
-
-def _AddEvents(model, json, namespace):
- """Adds Function objects to |model| contained in the 'events' field of |json|.
+ function = Function(parent,
+ function_json['name'],
+ function_json,
+ namespace,
+ Origin(from_json=True))
+ functions[function.name] = function
+ return functions
+
+def _GetEvents(parent, json, namespace):
+ """Creates Function objects generated from the events in |json|.
"""
- model.events = OrderedDict()
+ events = OrderedDict()
for event_json in json.get('events', []):
- event = Function(model, event_json, namespace, from_client=True)
- model.events[event.name] = event
-
-def _AddProperties(model,
- json,
- namespace,
- from_json=False,
- from_client=False):
- """Adds model.Property objects to |model| contained in the 'properties' field
- of |json|.
+ event = Function(parent,
+ event_json['name'],
+ event_json,
+ namespace,
+ Origin(from_client=True))
+ events[event.name] = event
+ return events
+
+def _GetProperties(parent, json, namespace, origin):
+ """Generates Property objects extracted from |json|.
"""
- model.properties = OrderedDict()
+ properties = OrderedDict()
for name, property_json in json.get('properties', {}).items():
- model.properties[name] = Property(
- model,
- name,
- property_json,
- namespace,
- from_json=from_json,
- from_client=from_client)
+ properties[name] = Property.FromJSON(
+ parent, name, property_json, namespace, origin)
+ return properties
class _PlatformInfo(_Enum):
def __init__(self, name):
diff --git a/tools/json_schema_compiler/model_test.py b/tools/json_schema_compiler/model_test.py
index 8cd43e8..e310d5e 100755
--- a/tools/json_schema_compiler/model_test.py
+++ b/tools/json_schema_compiler/model_test.py
@@ -32,41 +32,45 @@ class ModelTest(unittest.TestCase):
sorted(self.permissions.functions.keys()))
def testHasTypes(self):
- self.assertEquals(['tabs.Tab'], self.tabs.types.keys())
- self.assertEquals(['permissions.Permissions'],
- self.permissions.types.keys())
- self.assertEquals(['windows.Window'], self.windows.types.keys())
+ self.assertEquals(['Tab'], self.tabs.types.keys())
+ self.assertEquals(['Permissions'], self.permissions.types.keys())
+ self.assertEquals(['Window'], self.windows.types.keys())
def testHasProperties(self):
self.assertEquals(["active", "favIconUrl", "highlighted", "id",
"incognito", "index", "pinned", "selected", "status", "title", "url",
"windowId"],
- sorted(self.tabs.types['tabs.Tab'].properties.keys()))
+ sorted(self.tabs.types['Tab'].properties.keys()))
def testProperties(self):
- string_prop = self.tabs.types['tabs.Tab'].properties['status']
- self.assertEquals(model.PropertyType.STRING, string_prop.type_)
- integer_prop = self.tabs.types['tabs.Tab'].properties['id']
- self.assertEquals(model.PropertyType.INTEGER, integer_prop.type_)
- array_prop = self.windows.types['windows.Window'].properties['tabs']
- self.assertEquals(model.PropertyType.ARRAY, array_prop.type_)
- self.assertEquals(model.PropertyType.REF, array_prop.item_type.type_)
- self.assertEquals('tabs.Tab', array_prop.item_type.ref_type)
+ string_prop = self.tabs.types['Tab'].properties['status']
+ self.assertEquals(model.PropertyType.STRING,
+ string_prop.type_.property_type)
+ integer_prop = self.tabs.types['Tab'].properties['id']
+ self.assertEquals(model.PropertyType.INTEGER,
+ integer_prop.type_.property_type)
+ array_prop = self.windows.types['Window'].properties['tabs']
+ self.assertEquals(model.PropertyType.ARRAY,
+ array_prop.type_.property_type)
+ self.assertEquals(model.PropertyType.REF,
+ array_prop.type_.item_type.property_type)
+ self.assertEquals('tabs.Tab', array_prop.type_.item_type.ref_type)
object_prop = self.tabs.functions['query'].params[0]
- self.assertEquals(model.PropertyType.OBJECT, object_prop.type_)
+ self.assertEquals(model.PropertyType.OBJECT,
+ object_prop.type_.property_type)
self.assertEquals(
["active", "highlighted", "pinned", "status", "title", "url",
"windowId", "windowType"],
- sorted(object_prop.properties.keys()))
+ sorted(object_prop.type_.properties.keys()))
def testChoices(self):
self.assertEquals(model.PropertyType.CHOICES,
- self.tabs.functions['move'].params[0].type_)
+ self.tabs.functions['move'].params[0].type_.property_type)
def testPropertyNotImplemented(self):
(self.permissions_json[0]['types'][0]
['properties']['permissions']['type']) = 'something'
- self.assertRaises(NotImplementedError, self.model.AddNamespace,
+ self.assertRaises(model.ParseException, self.model.AddNamespace,
self.permissions_json[0], 'path/to/something.json')
def testDescription(self):
@@ -78,12 +82,6 @@ class ModelTest(unittest.TestCase):
def testPropertyUnixName(self):
param = self.tabs.functions['move'].params[0]
self.assertEquals('tab_ids', param.unix_name)
- param.choices[model.PropertyType.INTEGER].unix_name = 'asdf'
- param.choices[model.PropertyType.INTEGER].unix_name = 'tab_ids_integer'
- self.assertEquals('tab_ids_integer',
- param.choices[model.PropertyType.INTEGER].unix_name)
- self.assertRaises(AttributeError,
- param.choices[model.PropertyType.INTEGER].SetUnixName, 'breakage')
def testUnixName(self):
expectations = {
diff --git a/tools/json_schema_compiler/preview.py b/tools/json_schema_compiler/preview.py
index d577715..300983a 100755
--- a/tools/json_schema_compiler/preview.py
+++ b/tools/json_schema_compiler/preview.py
@@ -249,7 +249,7 @@ updateEverything();
except (TypeError, KeyError, AttributeError,
AssertionError, NotImplementedError) as error:
body.Append('<pre>')
- body.Append('compiler error: ' + str(error))
+ body.Append('compiler error: %s' % error)
body.Append('Check server log for more details')
body.Append('</pre>')
raise
diff --git a/tools/json_schema_compiler/schema_util.py b/tools/json_schema_compiler/schema_util.py
index dc84e61..e71be8b 100644
--- a/tools/json_schema_compiler/schema_util.py
+++ b/tools/json_schema_compiler/schema_util.py
@@ -19,32 +19,6 @@ def StripSchemaNamespace(s):
return s[last_dot + 1:]
return s
-def PrefixSchemasWithNamespace(schemas):
- for s in schemas:
- _PrefixWithNamespace(s.get("namespace"), s)
-
-def _MaybePrefixFieldWithNamespace(namespace, schema, key):
- if json_parse.IsDict(schema) and key in schema:
- old_value = schema[key]
- if not "." in old_value:
- schema[key] = namespace + "." + old_value
-
-def _PrefixTypesWithNamespace(namespace, types):
- for t in types:
- _MaybePrefixFieldWithNamespace(namespace, t, "id")
- _MaybePrefixFieldWithNamespace(namespace, t, "customBindings")
-
-def _PrefixWithNamespace(namespace, schema):
- if json_parse.IsDict(schema):
- if "types" in schema:
- _PrefixTypesWithNamespace(namespace, schema.get("types"))
- _MaybePrefixFieldWithNamespace(namespace, schema, "$ref")
- for s in schema:
- _PrefixWithNamespace(namespace, schema[s])
- elif type(schema) == list:
- for s in schema:
- _PrefixWithNamespace(namespace, s)
-
def JsFunctionNameToClassName(namespace_name, function_name):
"""Transform a fully qualified function name like foo.bar.baz into FooBarBaz
diff --git a/tools/json_schema_compiler/schema_util_test.py b/tools/json_schema_compiler/schema_util_test.py
index 1fa1803..4db88f1 100755
--- a/tools/json_schema_compiler/schema_util_test.py
+++ b/tools/json_schema_compiler/schema_util_test.py
@@ -4,7 +4,6 @@
# found in the LICENSE file.
from schema_util import JsFunctionNameToClassName
-from schema_util import PrefixSchemasWithNamespace
from schema_util import StripSchemaNamespace
import unittest
@@ -13,59 +12,6 @@ class SchemaUtilTest(unittest.TestCase):
self.assertEquals('Bar', StripSchemaNamespace('foo.Bar'))
self.assertEquals('Baz', StripSchemaNamespace('Baz'))
- def testPrefixSchemasWithNamespace(self):
- schemas = [
- { 'namespace': 'n1',
- 'types': [
- {
- 'id': 'T1',
- 'customBindings': 'T1',
- 'properties': {
- 'p1': {'$ref': 'T1'},
- 'p2': {'$ref': 'fully.qualified.T'},
- }
- }
- ],
- 'functions': [
- {
- 'parameters': [
- { '$ref': 'T1' },
- { '$ref': 'fully.qualified.T' },
- ],
- 'returns': { '$ref': 'T1' }
- },
- ],
- 'events': [
- {
- 'parameters': [
- { '$ref': 'T1' },
- { '$ref': 'fully.qualified.T' },
- ],
- },
- ],
- },
- ]
- PrefixSchemasWithNamespace(schemas)
- self.assertEquals('n1.T1', schemas[0]['types'][0]['id'])
- self.assertEquals('n1.T1', schemas[0]['types'][0]['customBindings'])
- self.assertEquals('n1.T1',
- schemas[0]['types'][0]['properties']['p1']['$ref'])
- self.assertEquals('fully.qualified.T',
- schemas[0]['types'][0]['properties']['p2']['$ref'])
-
- self.assertEquals('n1.T1',
- schemas[0]['functions'][0]['parameters'][0]['$ref'])
- self.assertEquals('fully.qualified.T',
- schemas[0]['functions'][0]['parameters'][1]['$ref'])
- self.assertEquals('n1.T1',
- schemas[0]['functions'][0]['returns']['$ref'])
-
- self.assertEquals('n1.T1',
- schemas[0]['events'][0]['parameters'][0]['$ref'])
- self.assertEquals('fully.qualified.T',
- schemas[0]['events'][0]['parameters'][1]['$ref'])
-
-
def testJsFunctionNameToClassName(self):
self.assertEquals('FooBar', JsFunctionNameToClassName('foo', 'bar'))
self.assertEquals('FooBar',
diff --git a/tools/json_schema_compiler/test/additional_properties.json b/tools/json_schema_compiler/test/additional_properties.json
index 03bbef8..0b800d9 100644
--- a/tools/json_schema_compiler/test/additional_properties.json
+++ b/tools/json_schema_compiler/test/additional_properties.json
@@ -44,7 +44,7 @@
"properties": {
"integer": {"type": "integer"}
},
- "additionalProperties": {"type": "any"}
+ "additionalProperties": {"type": "string"}
}
]
}
diff --git a/tools/json_schema_compiler/test/additional_properties_unittest.cc b/tools/json_schema_compiler/test/additional_properties_unittest.cc
index 4c3d720..5e08d5e 100644
--- a/tools/json_schema_compiler/test/additional_properties_unittest.cc
+++ b/tools/json_schema_compiler/test/additional_properties_unittest.cc
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "tools/json_schema_compiler/test/additional_properties.h"
-
#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/json_schema_compiler/test/additional_properties.h"
using namespace test::api::additional_properties;
@@ -19,9 +18,7 @@ TEST(JsonSchemaCompilerAdditionalPropertiesTest,
type_value->SetInteger("other", 9);
type_value->Set("another", list_value.release());
scoped_ptr<AdditionalPropertiesType> type(new AdditionalPropertiesType());
- EXPECT_TRUE(AdditionalPropertiesType::Populate(*type_value, type.get()));
- EXPECT_EQ("value", type->string);
- EXPECT_TRUE(type_value->Remove("string", NULL));
+ ASSERT_TRUE(AdditionalPropertiesType::Populate(*type_value, type.get()));
EXPECT_TRUE(type->additional_properties.Equals(type_value.get()));
}
{
@@ -48,22 +45,19 @@ TEST(JsonSchemaCompilerAdditionalPropertiesTest,
TEST(JsonSchemaCompilerAdditionalPropertiesTest,
ReturnAdditionalPropertiesResultCreate) {
- DictionaryValue additional;
- additional.SetString("key", "value");
ReturnAdditionalProperties::Results::ResultObject result_object;
result_object.integer = 5;
- result_object.additional_properties.MergeDictionary(&additional);
- scoped_ptr<ListValue> results =
- ReturnAdditionalProperties::Results::Create(result_object);
- DictionaryValue* result_dict = NULL;
- EXPECT_TRUE(results->GetDictionary(0, &result_dict));
+ result_object.additional_properties["key"] = "value";
- Value* int_temp_value_out = NULL;
- int int_temp = 0;
- EXPECT_TRUE(result_dict->Remove("integer", &int_temp_value_out));
- scoped_ptr<Value> int_temp_value(int_temp_value_out);
- EXPECT_TRUE(int_temp_value->GetAsInteger(&int_temp));
- EXPECT_EQ(5, int_temp);
+ ListValue expected;
+ {
+ DictionaryValue* dict = new DictionaryValue();
+ dict->SetInteger("integer", 5);
+ dict->SetString("key", "value");
+ expected.Append(dict);
+ }
- EXPECT_TRUE(result_dict->Equals(&additional));
+ EXPECT_TRUE(Value::Equals(
+ ReturnAdditionalProperties::Results::Create(result_object).get(),
+ &expected));
}
diff --git a/tools/json_schema_compiler/test/any_unittest.cc b/tools/json_schema_compiler/test/any_unittest.cc
index 0780230..81fd681 100644
--- a/tools/json_schema_compiler/test/any_unittest.cc
+++ b/tools/json_schema_compiler/test/any_unittest.cc
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "tools/json_schema_compiler/test/any.h"
-
#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/json_schema_compiler/test/any.h"
using namespace test::api::any;
@@ -41,9 +40,9 @@ TEST(JsonSchemaCompilerAnyTest, OptionalAnyParamsCreate) {
params_value->Append(param->DeepCopy());
scoped_ptr<OptionalAny::Params> params(
OptionalAny::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_TRUE(params->any_name.get());
- EXPECT_TRUE(params->any_name->value().Equals(param.get()));
+ ASSERT_TRUE(params);
+ ASSERT_TRUE(params->any_name);
+ EXPECT_TRUE(params->any_name->Equals(param.get()));
}
{
scoped_ptr<ListValue> params_value(new ListValue());
@@ -51,9 +50,8 @@ TEST(JsonSchemaCompilerAnyTest, OptionalAnyParamsCreate) {
params_value->Append(param->DeepCopy());
scoped_ptr<OptionalAny::Params> params(
OptionalAny::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_TRUE(params->any_name.get());
- EXPECT_TRUE(params->any_name.get());
- EXPECT_TRUE(params->any_name->value().Equals(param.get()));
+ ASSERT_TRUE(params);
+ ASSERT_TRUE(params->any_name);
+ EXPECT_TRUE(params->any_name->Equals(param.get()));
}
}
diff --git a/tools/json_schema_compiler/test/arrays.json b/tools/json_schema_compiler/test/arrays.json
index c5fbe9b..a0edd54 100644
--- a/tools/json_schema_compiler/test/arrays.json
+++ b/tools/json_schema_compiler/test/arrays.json
@@ -116,7 +116,7 @@
"type": "array",
"items": {
"type": "object",
- "additionalProperties": {"type": "any"}
+ "additionalProperties": {"type": "integer"}
}
},
{
@@ -144,6 +144,53 @@
]
},
{
+ "name": "justChoices",
+ "type": "function",
+ "description": "Takes some Choices.",
+ "parameters": [
+ {
+ "name": "choices",
+ "choices": [
+ { "type": "integer" },
+ { "type": "boolean" },
+ { "type": "array",
+ "items": {"$ref": "Item"}
+ }
+ ]
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": []
+ }
+ ]
+ },
+ {
+ "name": "choicesArray",
+ "type": "function",
+ "description": "Takes some Choices.",
+ "parameters": [
+ {
+ "name": "choices",
+ "type": "array",
+ "items": {
+ "choices": [
+ { "type": "integer" },
+ { "type": "boolean" },
+ { "type": "array",
+ "items": {"$ref": "Item"}
+ }
+ ]
+ }
+ },
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": []
+ }
+ ]
+ },
+ {
"name": "returnIntegerArray",
"type": "function",
"description": "Returns some integers.",
diff --git a/tools/json_schema_compiler/test/arrays_unittest.cc b/tools/json_schema_compiler/test/arrays_unittest.cc
index c6d1e06..e480c8e 100644
--- a/tools/json_schema_compiler/test/arrays_unittest.cc
+++ b/tools/json_schema_compiler/test/arrays_unittest.cc
@@ -46,45 +46,47 @@ TEST(JsonSchemaCompilerArrayTest, BasicArrayType) {
{
scoped_ptr<DictionaryValue> value = CreateBasicArrayTypeDictionary();
scoped_ptr<BasicArrayType> basic_array_type(new BasicArrayType());
- EXPECT_TRUE(BasicArrayType::Populate(*value, basic_array_type.get()));
+ ASSERT_TRUE(BasicArrayType::Populate(*value, basic_array_type.get()));
EXPECT_TRUE(value->Equals(basic_array_type->ToValue().get()));
}
}
TEST(JsonSchemaCompilerArrayTest, EnumArrayType) {
- std::vector<EnumArrayType::TypesElement> enums;
- enums.push_back(EnumArrayType::TYPES_ELEMENT_ONE);
- enums.push_back(EnumArrayType::TYPES_ELEMENT_TWO);
- enums.push_back(EnumArrayType::TYPES_ELEMENT_THREE);
+ std::vector<EnumArrayType::TypesType> enums;
+ enums.push_back(EnumArrayType::TYPES_TYPE_ONE);
+ enums.push_back(EnumArrayType::TYPES_TYPE_TWO);
+ enums.push_back(EnumArrayType::TYPES_TYPE_THREE);
scoped_ptr<ListValue> types(new ListValue());
for (size_t i = 0; i < enums.size(); ++i)
- types->Append(EnumArrayType::CreateEnumValue(enums[i]).release());
+ types->Append(new base::StringValue(EnumArrayType::ToString(enums[i])));
DictionaryValue value;
value.Set("types", types.release());
EnumArrayType enum_array_type;
- EXPECT_TRUE(EnumArrayType::Populate(value, &enum_array_type));
+ ASSERT_TRUE(EnumArrayType::Populate(value, &enum_array_type));
EXPECT_EQ(enums, enum_array_type.types);
}
TEST(JsonSchemaCompilerArrayTest, OptionalEnumArrayType) {
{
- std::vector<OptionalEnumArrayType::TypesElement> enums;
- enums.push_back(OptionalEnumArrayType::TYPES_ELEMENT_ONE);
- enums.push_back(OptionalEnumArrayType::TYPES_ELEMENT_TWO);
- enums.push_back(OptionalEnumArrayType::TYPES_ELEMENT_THREE);
+ std::vector<OptionalEnumArrayType::TypesType> enums;
+ enums.push_back(OptionalEnumArrayType::TYPES_TYPE_ONE);
+ enums.push_back(OptionalEnumArrayType::TYPES_TYPE_TWO);
+ enums.push_back(OptionalEnumArrayType::TYPES_TYPE_THREE);
scoped_ptr<ListValue> types(new ListValue());
- for (size_t i = 0; i < enums.size(); ++i)
- types->Append(OptionalEnumArrayType::CreateEnumValue(enums[i]).release());
+ for (size_t i = 0; i < enums.size(); ++i) {
+ types->Append(new base::StringValue(
+ OptionalEnumArrayType::ToString(enums[i])));
+ }
DictionaryValue value;
value.Set("types", types.release());
OptionalEnumArrayType enum_array_type;
- EXPECT_TRUE(OptionalEnumArrayType::Populate(value, &enum_array_type));
+ ASSERT_TRUE(OptionalEnumArrayType::Populate(value, &enum_array_type));
EXPECT_EQ(enums, *enum_array_type.types);
}
{
@@ -94,7 +96,7 @@ TEST(JsonSchemaCompilerArrayTest, OptionalEnumArrayType) {
value.Set("types", enum_array.release());
OptionalEnumArrayType enum_array_type;
- EXPECT_FALSE(OptionalEnumArrayType::Populate(value, &enum_array_type));
+ ASSERT_FALSE(OptionalEnumArrayType::Populate(value, &enum_array_type));
EXPECT_TRUE(enum_array_type.types->empty());
}
}
@@ -153,7 +155,7 @@ TEST(JsonSchemaCompilerArrayTest, AnyArrayParamsCreate) {
EXPECT_TRUE(params.get());
ASSERT_EQ(3u, params->anys.size());
int int_temp = 0;
- EXPECT_TRUE(params->anys[0]->value().GetAsInteger(&int_temp));
+ EXPECT_TRUE(params->anys[0]->GetAsInteger(&int_temp));
EXPECT_EQ(1, int_temp);
}
@@ -167,13 +169,8 @@ TEST(JsonSchemaCompilerArrayTest, ObjectArrayParamsCreate) {
ObjectArray::Params::Create(*params_value));
EXPECT_TRUE(params.get());
ASSERT_EQ(2u, params->objects.size());
- int object_val = 0;
- EXPECT_TRUE(params->objects[0]->additional_properties.GetInteger(
- "val", &object_val));
- EXPECT_EQ(1, object_val);
- EXPECT_TRUE(params->objects[1]->additional_properties.GetInteger(
- "val", &object_val));
- EXPECT_EQ(2, object_val);
+ EXPECT_EQ(1, params->objects[0]->additional_properties["val"]);
+ EXPECT_EQ(2, params->objects[1]->additional_properties["val"]);
}
TEST(JsonSchemaCompilerArrayTest, RefArrayParamsCreate) {
diff --git a/tools/json_schema_compiler/test/choices_unittest.cc b/tools/json_schema_compiler/test/choices_unittest.cc
index b4e76a1..b8bedf4 100644
--- a/tools/json_schema_compiler/test/choices_unittest.cc
+++ b/tools/json_schema_compiler/test/choices_unittest.cc
@@ -22,9 +22,8 @@ TEST(JsonSchemaCompilerChoicesTest, TakesIntegersParamsCreate) {
scoped_ptr<TakesIntegers::Params> params(
TakesIntegers::Params::Create(*params_value));
EXPECT_TRUE(params.get());
- EXPECT_EQ(TakesIntegers::Params::NUMS_INTEGER, params->nums_type);
- EXPECT_FALSE(params->nums_array.get());
- EXPECT_EQ(6, *params->nums_integer);
+ EXPECT_FALSE(params->nums.as_array);
+ EXPECT_EQ(6, *params->nums.as_integer);
}
{
scoped_ptr<ListValue> params_value(new ListValue());
@@ -34,45 +33,41 @@ TEST(JsonSchemaCompilerChoicesTest, TakesIntegersParamsCreate) {
params_value->Append(integers.release());
scoped_ptr<TakesIntegers::Params> params(
TakesIntegers::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(TakesIntegers::Params::NUMS_ARRAY, params->nums_type);
- EXPECT_EQ((size_t) 2, (*params->nums_array).size());
- EXPECT_EQ(6, (*params->nums_array)[0]);
- EXPECT_EQ(8, (*params->nums_array)[1]);
+ ASSERT_TRUE(params);
+ ASSERT_TRUE(params->nums.as_array);
+ EXPECT_EQ((size_t) 2, params->nums.as_array->size());
+ EXPECT_EQ(6, params->nums.as_array->at(0));
+ EXPECT_EQ(8, params->nums.as_array->at(1));
}
}
TEST(JsonSchemaCompilerChoicesTest, ObjectWithChoicesParamsCreate) {
{
scoped_ptr<DictionaryValue> object_param(new DictionaryValue());
- object_param->SetWithoutPathExpansion("strings",
- Value::CreateStringValue("asdf"));
+ object_param->SetString("strings", "asdf");
scoped_ptr<ListValue> params_value(new ListValue());
params_value->Append(object_param.release());
scoped_ptr<ObjectWithChoices::Params> params(
ObjectWithChoices::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(ObjectWithChoices::Params::StringInfo::STRINGS_STRING,
- params->string_info.strings_type);
- EXPECT_EQ("asdf", *params->string_info.strings_string);
+ ASSERT_TRUE(params);
+ EXPECT_FALSE(params->string_info.strings.as_array);
+ EXPECT_EQ("asdf", *params->string_info.strings.as_string);
+ EXPECT_FALSE(params->string_info.integers);
}
{
scoped_ptr<DictionaryValue> object_param(new DictionaryValue());
- object_param->SetWithoutPathExpansion("strings",
- Value::CreateStringValue("asdf"));
- object_param->SetWithoutPathExpansion("integers",
- Value::CreateIntegerValue(6));
+ object_param->SetString("strings", "asdf");
+ object_param->SetInteger("integers", 6);
scoped_ptr<ListValue> params_value(new ListValue());
params_value->Append(object_param.release());
scoped_ptr<ObjectWithChoices::Params> params(
ObjectWithChoices::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(ObjectWithChoices::Params::StringInfo::STRINGS_STRING,
- params->string_info.strings_type);
- EXPECT_EQ("asdf", *params->string_info.strings_string);
- EXPECT_EQ(ObjectWithChoices::Params::StringInfo::INTEGERS_INTEGER,
- params->string_info.integers_type);
- EXPECT_EQ(6, *params->string_info.integers_integer);
+ ASSERT_TRUE(params);
+ EXPECT_FALSE(params->string_info.strings.as_array);
+ EXPECT_EQ("asdf", *params->string_info.strings.as_string);
+ ASSERT_TRUE(params->string_info.integers);
+ EXPECT_FALSE(params->string_info.integers->as_array);
+ EXPECT_EQ(6, *params->string_info.integers->as_integer);
}
}
@@ -127,15 +122,13 @@ TEST(JsonSchemaCompilerChoicesTest, PopulateChoiceType) {
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);
+ ASSERT_TRUE(out.integers.as_integer.get());
+ EXPECT_FALSE(out.integers.as_array.get());
+ EXPECT_EQ(4, *out.integers.as_integer);
+
+ EXPECT_FALSE(out.strings->as_string.get());
+ ASSERT_TRUE(out.strings->as_array.get());
+ EXPECT_EQ(strings, *out.strings->as_array);
}
TEST(JsonSchemaCompilerChoicesTest, ChoiceTypeToValue) {
@@ -156,23 +149,29 @@ TEST(JsonSchemaCompilerChoicesTest, ChoiceTypeToValue) {
TEST(JsonSchemaCompilerChoicesTest, ReturnChoices) {
{
- std::vector<int> integers;
- integers.push_back(1);
- integers.push_back(2);
- scoped_ptr<ListValue> array_results =
- ReturnChoices::Results::Create(integers);
-
- ListValue expected;
- ListValue* expected_argument = new ListValue();
- expected_argument->Append(Value::CreateIntegerValue(1));
- expected_argument->Append(Value::CreateIntegerValue(2));
- expected.Append(expected_argument);
- EXPECT_TRUE(array_results->Equals(&expected));
+ ReturnChoices::Results::Result results;
+ results.as_array.reset(new std::vector<int>());
+ results.as_array->push_back(1);
+ results.as_array->push_back(2);
+
+ scoped_ptr<base::Value> results_value = results.ToValue();
+ ASSERT_TRUE(results_value);
+
+ base::ListValue expected;
+ expected.AppendInteger(1);
+ expected.AppendInteger(2);
+
+ EXPECT_TRUE(expected.Equals(results_value.get()));
}
{
- scoped_ptr<ListValue> integer_results = ReturnChoices::Results::Create(5);
- ListValue expected;
- expected.Append(Value::CreateIntegerValue(5));
- EXPECT_TRUE(integer_results->Equals(&expected));
+ ReturnChoices::Results::Result results;
+ results.as_integer.reset(new int(5));
+
+ scoped_ptr<base::Value> results_value = results.ToValue();
+ ASSERT_TRUE(results_value);
+
+ base::FundamentalValue expected(5);
+
+ EXPECT_TRUE(expected.Equals(results_value.get()));
}
}
diff --git a/tools/json_schema_compiler/test/enums.json b/tools/json_schema_compiler/test/enums.json
index a0bea46..6769b19 100644
--- a/tools/json_schema_compiler/test/enums.json
+++ b/tools/json_schema_compiler/test/enums.json
@@ -4,6 +4,7 @@
"types": [
{
"id": "Enumeration",
+ "type": "string",
"enum": ["one", "two", "three"]
},
{
diff --git a/tools/json_schema_compiler/test/enums_unittest.cc b/tools/json_schema_compiler/test/enums_unittest.cc
index 4604694..81bfe8d 100644
--- a/tools/json_schema_compiler/test/enums_unittest.cc
+++ b/tools/json_schema_compiler/test/enums_unittest.cc
@@ -33,10 +33,10 @@ TEST(JsonSchemaCompilerEnumsTest, EnumsAsTypes) {
scoped_ptr<TakesEnumAsType::Params> params(
TakesEnumAsType::Params::Create(args));
ASSERT_TRUE(params.get());
- EXPECT_EQ(ENUMS_ENUMERATION_ONE, params->enumeration);
+ EXPECT_EQ(ENUMERATION_ONE, params->enumeration);
EXPECT_TRUE(args.Equals(ReturnsEnumAsType::Results::Create(
- ENUMS_ENUMERATION_ONE).get()));
+ ENUMERATION_ONE).get()));
}
{
HasEnumeration enumeration;
@@ -56,7 +56,8 @@ TEST(JsonSchemaCompilerEnumsTest, EnumsAsTypes) {
TEST(JsonSchemaCompilerEnumsTest, ReturnsEnumCreate) {
{
ReturnsEnum::Results::State state = ReturnsEnum::Results::STATE_FOO;
- scoped_ptr<Value> result = ReturnsEnum::Results::CreateEnumValue(state);
+ scoped_ptr<Value> result(
+ new base::StringValue(ReturnsEnum::Results::ToString(state)));
scoped_ptr<Value> expected(Value::CreateStringValue("foo"));
EXPECT_TRUE(result->Equals(expected.get()));
}
@@ -189,7 +190,8 @@ TEST(JsonSchemaCompilerEnumsTest, TakesMultipleOptionalEnumsParamsCreate) {
TEST(JsonSchemaCompilerEnumsTest, OnEnumFiredCreate) {
{
OnEnumFired::SomeEnum some_enum = OnEnumFired::SOME_ENUM_FOO;
- scoped_ptr<Value> result(OnEnumFired::CreateEnumValue(some_enum));
+ scoped_ptr<Value> result(
+ new base::StringValue(OnEnumFired::ToString(some_enum)));
scoped_ptr<Value> expected(Value::CreateStringValue("foo"));
EXPECT_TRUE(result->Equals(expected.get()));
}
diff --git a/tools/json_schema_compiler/test/functions_on_types_unittest.cc b/tools/json_schema_compiler/test/functions_on_types_unittest.cc
index 73a3cf2..6fe4526 100644
--- a/tools/json_schema_compiler/test/functions_on_types_unittest.cc
+++ b/tools/json_schema_compiler/test/functions_on_types_unittest.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "tools/json_schema_compiler/test/functions_on_types.h"
-
+#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/json_schema_compiler/test/functions_on_types.h"
using namespace test::api::functions_on_types;
@@ -13,24 +13,24 @@ TEST(JsonSchemaCompilerFunctionsOnTypesTest, StorageAreaGetParamsCreate) {
scoped_ptr<ListValue> params_value(new ListValue());
scoped_ptr<StorageArea::Get::Params> params(
StorageArea::Get::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(StorageArea::Get::Params::KEYS_NONE, params->keys_type);
+ ASSERT_TRUE(params);
+ EXPECT_FALSE(params->keys);
}
{
scoped_ptr<ListValue> params_value(new ListValue());
params_value->Append(Value::CreateIntegerValue(9));
scoped_ptr<StorageArea::Get::Params> params(
StorageArea::Get::Params::Create(*params_value));
- EXPECT_FALSE(params.get());
+ EXPECT_FALSE(params);
}
{
scoped_ptr<ListValue> params_value(new ListValue());
params_value->Append(Value::CreateStringValue("test"));
scoped_ptr<StorageArea::Get::Params> params(
StorageArea::Get::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(StorageArea::Get::Params::KEYS_STRING, params->keys_type);
- EXPECT_EQ("test", *params->keys_string);
+ ASSERT_TRUE(params);
+ ASSERT_TRUE(params->keys);
+ EXPECT_EQ("test", *params->keys->as_string);
}
{
scoped_ptr<DictionaryValue> keys_object_value(new DictionaryValue());
@@ -40,10 +40,10 @@ TEST(JsonSchemaCompilerFunctionsOnTypesTest, StorageAreaGetParamsCreate) {
params_value->Append(keys_object_value->DeepCopy());
scoped_ptr<StorageArea::Get::Params> params(
StorageArea::Get::Params::Create(*params_value));
- EXPECT_TRUE(params.get());
- EXPECT_EQ(StorageArea::Get::Params::KEYS_OBJECT, params->keys_type);
- EXPECT_TRUE(
- keys_object_value->Equals(&params->keys_object->additional_properties));
+ ASSERT_TRUE(params);
+ ASSERT_TRUE(params->keys);
+ EXPECT_TRUE(keys_object_value->Equals(
+ &params->keys->as_object->additional_properties));
}
}
@@ -53,7 +53,7 @@ TEST(JsonSchemaCompilerFunctionsOnTypesTest, StorageAreaGetResultCreate) {
items.additional_properties.SetString("sdfg", "zxcv");
scoped_ptr<ListValue> results = StorageArea::Get::Results::Create(items);
DictionaryValue* item_result = NULL;
- results->GetDictionary(0, &item_result);
+ ASSERT_TRUE(results->GetDictionary(0, &item_result));
EXPECT_TRUE(item_result->Equals(&items.additional_properties));
}
diff --git a/tools/json_schema_compiler/test/idl_schemas_unittest.cc b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
index 8afb59c..5186be9 100644
--- a/tools/json_schema_compiler/test/idl_schemas_unittest.cc
+++ b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/values.h"
-#include "tools/json_schema_compiler/any.h"
#include "tools/json_schema_compiler/test/idl_basics.h"
#include "tools/json_schema_compiler/test/idl_object_types.h"
@@ -167,13 +166,12 @@ TEST(IdlCompiler, ObjectTypes) {
// Test the BarType type.
BarType b1;
- base::FundamentalValue seven(7);
- b1.x.Init(seven);
+ b1.x.reset(new base::FundamentalValue(7));
scoped_ptr<DictionaryValue> serialized_bar = b1.ToValue();
BarType b2;
EXPECT_TRUE(BarType::Populate(*serialized_bar.get(), &b2));
int tmp_int = 0;
- EXPECT_TRUE(b2.x.value().GetAsInteger(&tmp_int));
+ EXPECT_TRUE(b2.x->GetAsInteger(&tmp_int));
EXPECT_EQ(7, tmp_int);
// Test the params to the ObjectFunction1 function.
diff --git a/tools/json_schema_compiler/test/objects_unittest.cc b/tools/json_schema_compiler/test/objects_unittest.cc
index 3582f4f..5a4248d 100644
--- a/tools/json_schema_compiler/test/objects_unittest.cc
+++ b/tools/json_schema_compiler/test/objects_unittest.cc
@@ -68,9 +68,4 @@ TEST(JsonSchemaCompilerObjectsTest, OnObjectFiredCreate) {
DictionaryValue* result = NULL;
ASSERT_TRUE(results->GetDictionary(0, &result));
ASSERT_TRUE(result->Equals(&expected));
-
- std::string json1 = OnObjectFired::ToJson(object);
- std::string json2;
- base::JSONWriter::Write(results.get(), &json2);
- ASSERT_EQ(json1, json2);
}
diff --git a/tools/json_schema_compiler/util.cc b/tools/json_schema_compiler/util.cc
index ca5c25a..25f908c 100644
--- a/tools/json_schema_compiler/util.cc
+++ b/tools/json_schema_compiler/util.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "tools/json_schema_compiler/any.h"
#include "tools/json_schema_compiler/util.h"
#include "base/values.h"
@@ -26,14 +25,13 @@ bool GetItemFromList(const ListValue& from, int index, std::string* out) {
return from.GetString(index, out);
}
-bool GetItemFromList(const ListValue& from, int index,
- linked_ptr<any::Any>* out) {
- const Value* value = NULL;
+bool GetItemFromList(const ListValue& from,
+ int index,
+ linked_ptr<base::Value>* out) {
+ const base::Value* value = NULL;
if (!from.Get(index, &value))
return false;
- scoped_ptr<any::Any> any_object(new any::Any());
- any_object->Init(*value);
- *out = linked_ptr<any::Any>(any_object.release());
+ *out = make_linked_ptr(value->DeepCopy());
return true;
}
@@ -42,30 +40,35 @@ bool GetItemFromList(const ListValue& from, int index,
const DictionaryValue* dict = NULL;
if (!from.GetDictionary(index, &dict))
return false;
- *out = linked_ptr<DictionaryValue>(dict->DeepCopy());
+ *out = make_linked_ptr(dict->DeepCopy());
return true;
}
void AddItemToList(const int from, base::ListValue* out) {
out->Append(base::Value::CreateIntegerValue(from));
}
+
void AddItemToList(const bool from, base::ListValue* out) {
out->Append(base::Value::CreateBooleanValue(from));
}
+
void AddItemToList(const double from, base::ListValue* out) {
out->Append(base::Value::CreateDoubleValue(from));
}
+
void AddItemToList(const std::string& from, base::ListValue* out) {
out->Append(base::Value::CreateStringValue(from));
}
+
+void AddItemToList(const linked_ptr<base::Value>& from,
+ base::ListValue* out) {
+ out->Append(from->DeepCopy());
+}
+
void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
- base::ListValue* out) {
+ base::ListValue* out) {
out->Append(static_cast<Value*>(from->DeepCopy()));
}
-void AddItemToList(const linked_ptr<any::Any>& from,
- base::ListValue* out) {
- out->Append(from->value().DeepCopy());
-}
} // namespace api_util
} // namespace extensions
diff --git a/tools/json_schema_compiler/util.h b/tools/json_schema_compiler/util.h
index 6943590..425487d 100644
--- a/tools/json_schema_compiler/util.h
+++ b/tools/json_schema_compiler/util.h
@@ -14,10 +14,6 @@
namespace json_schema_compiler {
-namespace any {
-class Any;
-}
-
namespace util {
// Creates a new item at |out| from |from|[|index|]. These are used by template
@@ -26,10 +22,12 @@ bool GetItemFromList(const ListValue& from, int index, int* out);
bool GetItemFromList(const ListValue& from, int index, bool* out);
bool GetItemFromList(const ListValue& from, int index, double* out);
bool GetItemFromList(const ListValue& from, int index, std::string* out);
-bool GetItemFromList(const ListValue& from, int index,
- linked_ptr<base::DictionaryValue>* out);
-bool GetItemFromList(const ListValue& from, int index,
- linked_ptr<any::Any>* out);
+bool GetItemFromList(const ListValue& from,
+ int index,
+ linked_ptr<base::Value>* out);
+bool GetItemFromList(const ListValue& from,
+ int index,
+ linked_ptr<base::DictionaryValue>* out);
// This template is used for types generated by tools/json_schema_compiler.
template<class T>
@@ -134,10 +132,10 @@ void AddItemToList(const int from, base::ListValue* out);
void AddItemToList(const bool from, base::ListValue* out);
void AddItemToList(const double from, base::ListValue* out);
void AddItemToList(const std::string& from, base::ListValue* out);
+void AddItemToList(const linked_ptr<base::Value>& from,
+ base::ListValue* out);
void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
- base::ListValue* out);
-void AddItemToList(const linked_ptr<any::Any>& from,
- base::ListValue* out);
+ base::ListValue* out);
// This template is used for types generated by tools/json_schema_compiler.
template<class T>
@@ -170,8 +168,7 @@ void PopulateListFromOptionalArray(
}
template <class T>
-scoped_ptr<Value> CreateValueFromArray(
- const std::vector<T>& from) {
+scoped_ptr<Value> CreateValueFromArray(const std::vector<T>& from) {
base::ListValue* list = new base::ListValue();
PopulateListFromArray(from, list);
return scoped_ptr<Value>(list);
diff --git a/tools/json_schema_compiler/util_cc_helper.py b/tools/json_schema_compiler/util_cc_helper.py
index bf089dd..8d490ba 100644
--- a/tools/json_schema_compiler/util_cc_helper.py
+++ b/tools/json_schema_compiler/util_cc_helper.py
@@ -25,7 +25,7 @@ class UtilCCHelper(object):
'dst': dst,
}
- sub['type'] = self._type_manager.GetType(prop)
+ sub['type'] = self._type_manager.GetCppType(prop),
if array_prop.optional:
val = ('%(namespace)s::PopulateOptionalArrayFromDictionary'
'(*%(src)s, "%(name)s", &%(dst)s)')
@@ -46,7 +46,7 @@ class UtilCCHelper(object):
'namespace': API_UTIL_NAMESPACE,
'src': src,
'dst': dst,
- 'type': self._type_manager.GetType(prop),
+ 'type': self._type_manager.GetCppType(prop),
}
if optional:
@@ -65,7 +65,7 @@ class UtilCCHelper(object):
sub = {
'namespace': API_UTIL_NAMESPACE,
'src': src,
- 'type': self._type_manager.GetType(prop),
+ 'type': self._type_manager.GetCppType(prop),
}
if optional: