summaryrefslogtreecommitdiffstats
path: root/tools/json_schema_compiler
diff options
context:
space:
mode:
authorrdevlin.cronin <rdevlin.cronin@chromium.org>2016-03-22 15:11:00 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-22 22:13:13 +0000
commit63ef43c0af90ca5f23d0606e2394b0e5f25fc0b5 (patch)
tree14ff1d1b8c8f9aae47fe4456d2bce99ad8f55b60 /tools/json_schema_compiler
parent3a1e77f21225b290585e1e9432f3cdecbf63866d (diff)
downloadchromium_src-63ef43c0af90ca5f23d0606e2394b0e5f25fc0b5.zip
chromium_src-63ef43c0af90ca5f23d0606e2394b0e5f25fc0b5.tar.gz
chromium_src-63ef43c0af90ca5f23d0606e2394b0e5f25fc0b5.tar.bz2
[Extensions] Update generated code to support move operations
Generated extensions code currently uses linked_ptrs for non-copyable types stored in containers. Instead, these types should just be movable. Update the code generator to support move operations for flagged idl files and apply it to the developerPrivate API as a first step/POC. BUG=595949 Review URL: https://codereview.chromium.org/1811413002 Cr-Commit-Position: refs/heads/master@{#382704}
Diffstat (limited to 'tools/json_schema_compiler')
-rw-r--r--tools/json_schema_compiler/cc_generator.py79
-rw-r--r--tools/json_schema_compiler/cpp_type_generator.py7
-rwxr-xr-xtools/json_schema_compiler/cpp_type_generator_test.py13
-rw-r--r--tools/json_schema_compiler/h_generator.py4
-rwxr-xr-xtools/json_schema_compiler/idl_schema.py2
-rw-r--r--tools/json_schema_compiler/test/BUILD.gn1
-rw-r--r--tools/json_schema_compiler/test/json_schema_compiler_tests.gyp1
-rw-r--r--tools/json_schema_compiler/test/objects_movable.idl23
-rw-r--r--tools/json_schema_compiler/test/objects_unittest.cc40
-rw-r--r--tools/json_schema_compiler/util.h25
10 files changed, 188 insertions, 7 deletions
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
index ac1679b..499671f 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -126,8 +126,17 @@ class _Generator(object):
(c.Append('%s::%s()' % (classname_in_namespace, classname))
.Cblock(self._GenerateInitializersAndBody(type_))
.Append('%s::~%s() {}' % (classname_in_namespace, classname))
- .Append()
)
+ if 'use_movable_types' in type_.namespace.compiler_options:
+ # Note: we use 'rhs' because some API objects have a member 'other'.
+ (c.Append('%s::%s(%s&& rhs)' %
+ (classname_in_namespace, classname, classname))
+ .Cblock(self._GenerateMoveCtor(type_))
+ .Append('%s& %s::operator=(%s&& rhs)' %
+ (classname_in_namespace, classname_in_namespace,
+ classname))
+ .Cblock(self._GenerateMoveAssignOperator(type_))
+ )
if type_.origin.from_json:
c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
if cpp_namespace is None: # only generate for top-level types
@@ -178,12 +187,78 @@ class _Generator(object):
raise TypeError(t)
if items:
- s = ': %s' % (', '.join(items))
+ s = ': %s' % (',\n'.join(items))
else:
s = ''
s = s + ' {}'
return Code().Append(s)
+ def _GetMoveProps(self, type_, copy_str, move_str):
+ """Returns a tuple of (props, dicts) for the type.
+
+ |props| is a list of all the copyable or movable properties generated using
+ the copy_str and move_str, and |dicts| is a list of all the dictionary
+ properties by name.
+
+ Properties:
+ - |type_| the Type to get the properties from
+ - |copy_str| the string to use when copying a value; should have two
+ placeholders to take the property name.
+ - |move_str| the string to use when moving a value; should have two
+ placeholders to take the property name.
+ """
+ props = []
+ dicts = []
+ for prop in type_.properties.values():
+ t = prop.type_
+
+ real_t = self._type_helper.FollowRef(t)
+ if (prop.optional or
+ t.property_type == PropertyType.ANY or
+ t.property_type == PropertyType.ARRAY or
+ t.property_type == PropertyType.BINARY or
+ t.property_type == PropertyType.CHOICES or
+ t.property_type == PropertyType.OBJECT or
+ t.property_type == PropertyType.REF or
+ t.property_type == PropertyType.STRING):
+ props.append(move_str % (prop.unix_name, prop.unix_name))
+ elif t.property_type == PropertyType.FUNCTION:
+ dicts.append(prop.unix_name)
+ elif (real_t.property_type == PropertyType.ENUM or
+ t.property_type == PropertyType.INTEGER or
+ t.property_type == PropertyType.DOUBLE or
+ t.property_type == PropertyType.BOOLEAN):
+ props.append(copy_str % (prop.unix_name, prop.unix_name))
+ else:
+ raise TypeError(t)
+
+ return (props, dicts)
+
+ def _GenerateMoveCtor(self, type_):
+ props, dicts = self._GetMoveProps(type_, '%s(rhs.%s)',
+ '%s(std::move(rhs.%s))')
+ s = ''
+ if props:
+ s = s + ': %s' % (',\n'.join(props))
+ s = s + '{'
+ for item in dicts:
+ s = s + ('\n%s.Swap(&rhs.%s);' % (item, item))
+ s = s + '\n}'
+
+ return Code().Append(s)
+
+ def _GenerateMoveAssignOperator(self, type_):
+ props, dicts = self._GetMoveProps(type_, '%s = rhs.%s;',
+ '%s = std::move(rhs.%s);')
+ s = '{\n'
+ if props:
+ s = s + '\n'.join(props)
+ for item in dicts:
+ s = s + ('\n%s.Swap(&rhs.%s);' % (item, item))
+ s = s + '\nreturn *this;\n}'
+
+ return Code().Append(s)
+
def _GenerateTypePopulate(self, cpp_namespace, type_):
"""Generates the function for populating a type given a pointer to it.
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py
index 3d307a9..24cbf61 100644
--- a/tools/json_schema_compiler/cpp_type_generator.py
+++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -121,7 +121,12 @@ class CppTypeGenerator(object):
# 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)
+ # Only wrap the object in a linked_ptr if this API isn't using movable
+ # types. Since base::Values aren't yet movable, wrap them too.
+ # TODO(devlin): Eventually, movable types should be the default.
+ if (not 'use_movable_types' in type_.namespace.compiler_options or
+ cpp_type == 'base::Value' or cpp_type == 'base::DictionaryValue'):
+ cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
elif is_ptr:
cpp_type = 'scoped_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
diff --git a/tools/json_schema_compiler/cpp_type_generator_test.py b/tools/json_schema_compiler/cpp_type_generator_test.py
index 51fcfe9..69d80dc 100755
--- a/tools/json_schema_compiler/cpp_type_generator_test.py
+++ b/tools/json_schema_compiler/cpp_type_generator_test.py
@@ -6,6 +6,7 @@
from cpp_namespace_environment import CppNamespaceEnvironment
from cpp_type_generator import CppTypeGenerator
from json_schema import CachedLoad
+import idl_schema
import model
import unittest
@@ -49,6 +50,10 @@ class CppTypeGeneratorTest(unittest.TestCase):
self.content_settings_json = CachedLoad('test/content_settings.json')
self.content_settings = self.models['content_settings'].AddNamespace(
self.content_settings_json[0], 'path/to/content_settings.json')
+ self.objects_movable_idl = idl_schema.Load('test/objects_movable.idl')
+ self.objects_movable = self.models['objects_movable'].AddNamespace(
+ self.objects_movable_idl[0], 'path/to/objects_movable.idl',
+ include_compiler_options=True)
def testGenerateIncludesAndForwardDeclarations(self):
m = model.Model()
@@ -153,6 +158,14 @@ class CppTypeGeneratorTest(unittest.TestCase):
manager.GetCppType(
self.permissions.types['Permissions'].properties['origins'].type_))
+ manager = CppTypeGenerator(self.models.get('objects_movable'),
+ _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'std::vector<MovablePod>',
+ manager.GetCppType(
+ self.objects_movable.types['MovableParent'].
+ properties['pods'].type_))
+
def testGetCppTypeLocalRef(self):
manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
self.assertEquals(
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py
index 173e549..5452885 100644
--- a/tools/json_schema_compiler/h_generator.py
+++ b/tools/json_schema_compiler/h_generator.py
@@ -228,6 +228,10 @@ class _Generator(object):
.Append('%(classname)s();')
.Append('~%(classname)s();')
)
+ if 'use_movable_types' in type_.namespace.compiler_options:
+ (c.Append('%(classname)s(%(classname)s&& rhs);')
+ .Append('%(classname)s& operator=(%(classname)s&& rhs);')
+ )
if type_.origin.from_json:
(c.Append()
.Comment('Populates a %s object from a base::Value. Returns'
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py
index 58efe28..5fda70e 100755
--- a/tools/json_schema_compiler/idl_schema.py
+++ b/tools/json_schema_compiler/idl_schema.py
@@ -500,6 +500,8 @@ class IDLSchema(object):
compiler_options['implemented_in'] = node.value
elif node.name == 'camel_case_enum_to_string':
compiler_options['camel_case_enum_to_string'] = node.value
+ elif node.name == 'use_movable_types':
+ compiler_options['use_movable_types'] = node.value
elif node.name == 'deprecated':
deprecated = str(node.value)
elif node.name == 'documentation_title':
diff --git a/tools/json_schema_compiler/test/BUILD.gn b/tools/json_schema_compiler/test/BUILD.gn
index 33e6219..e12493f 100644
--- a/tools/json_schema_compiler/test/BUILD.gn
+++ b/tools/json_schema_compiler/test/BUILD.gn
@@ -23,6 +23,7 @@ json_schema_api("api") {
"idl_other_namespace.idl",
"idl_other_namespace_sub_namespace.idl",
"objects.json",
+ "objects_movable.idl",
"simple_api.json",
]
diff --git a/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp b/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
index 404e9b0..a0203dc 100644
--- a/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
+++ b/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
@@ -25,6 +25,7 @@
'idl_other_namespace_sub_namespace.idl',
'idl_object_types.idl',
'objects.json',
+ 'objects_movable.idl',
'simple_api.json',
'error_generation.json'
],
diff --git a/tools/json_schema_compiler/test/objects_movable.idl b/tools/json_schema_compiler/test/objects_movable.idl
new file mode 100644
index 0000000..b09f1a8
--- /dev/null
+++ b/tools/json_schema_compiler/test/objects_movable.idl
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+// Movable Objects.
+[use_movable_types=true] namespace objectsMovable {
+ enum Foo {
+ BAR,
+ BAZ
+ };
+
+ dictionary MovablePod {
+ Foo foo;
+ DOMString str;
+ long num;
+ boolean b;
+ };
+
+ dictionary MovableParent {
+ MovablePod[] pods;
+ DOMString[] strs;
+ };
+};
diff --git a/tools/json_schema_compiler/test/objects_unittest.cc b/tools/json_schema_compiler/test/objects_unittest.cc
index 5e28386..2cb6fc6 100644
--- a/tools/json_schema_compiler/test/objects_unittest.cc
+++ b/tools/json_schema_compiler/test/objects_unittest.cc
@@ -2,14 +2,15 @@
// 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/objects.h"
-
#include <stddef.h>
#include "base/json/json_writer.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/json_schema_compiler/test/objects.h"
+#include "tools/json_schema_compiler/test/objects_movable.h"
using namespace test::api::objects;
+using namespace test::api::objects_movable;
TEST(JsonSchemaCompilerObjectsTest, ObjectParamParamsCreate) {
{
@@ -71,3 +72,38 @@ TEST(JsonSchemaCompilerObjectsTest, OnObjectFiredCreate) {
ASSERT_TRUE(results->GetDictionary(0, &result));
ASSERT_TRUE(result->Equals(&expected));
}
+TEST(JsonSchemaCompilerMovableObjectsTest, MovableObjectsTest) {
+ std::vector<MovablePod> pods;
+ {
+ MovablePod pod;
+ pod.foo = FOO_BAR;
+ pod.str = "str1";
+ pod.num = 42;
+ pod.b = true;
+ pods.push_back(std::move(pod));
+ }
+ {
+ MovablePod pod;
+ pod.foo = FOO_BAZ;
+ pod.str = "str2";
+ pod.num = 45;
+ pod.b = false;
+ pods.push_back(std::move(pod));
+ }
+ MovableParent parent;
+ parent.pods = std::move(pods);
+ parent.strs.push_back("pstr");
+
+ MovableParent parent2(std::move(parent));
+ ASSERT_EQ(2u, parent2.pods.size());
+ EXPECT_EQ(FOO_BAR, parent2.pods[0].foo);
+ EXPECT_EQ("str1", parent2.pods[0].str);
+ EXPECT_EQ(42, parent2.pods[0].num);
+ EXPECT_TRUE(parent2.pods[0].b);
+ EXPECT_EQ(FOO_BAZ, parent2.pods[1].foo);
+ EXPECT_EQ("str2", parent2.pods[1].str);
+ EXPECT_EQ(45, parent2.pods[1].num);
+ EXPECT_FALSE(parent2.pods[1].b);
+ ASSERT_EQ(1u, parent2.strs.size());
+ EXPECT_EQ("pstr", parent2.strs[0]);
+}
diff --git a/tools/json_schema_compiler/util.h b/tools/json_schema_compiler/util.h
index 59d65d0..945f061 100644
--- a/tools/json_schema_compiler/util.h
+++ b/tools/json_schema_compiler/util.h
@@ -57,6 +57,19 @@ bool PopulateItem(const base::Value& from, linked_ptr<T>* out) {
return true;
}
+// This template is used for types generated by tools/json_schema_compiler.
+template <class T>
+bool PopulateItem(const base::Value& from, T* out) {
+ const base::DictionaryValue* dict = nullptr;
+ if (!from.GetAsDictionary(&dict))
+ return false;
+ T obj;
+ if (!T::Populate(*dict, &obj))
+ return false;
+ *out = std::move(obj);
+ return true;
+}
+
// This template is used for types generated by tools/json_schema_compiler with
// error generation enabled.
template <class T>
@@ -82,7 +95,9 @@ bool PopulateArrayFromList(const base::ListValue& list, std::vector<T>* out) {
for (const base::Value* value : list) {
if (!PopulateItem(*value, &item))
return false;
- out->push_back(item);
+ // T might not be movable, but in that case it should be copyable, and this
+ // will still work.
+ out->push_back(std::move(item));
}
return true;
@@ -148,12 +163,18 @@ void AddItemToList(const linked_ptr<T>& from, base::ListValue* out) {
out->Append(from->ToValue().release());
}
+// This template is used for types generated by tools/json_schema_compiler.
+template <class T>
+void AddItemToList(const T& from, base::ListValue* out) {
+ out->Append(from.ToValue());
+}
+
// Set |out| to the the contents of |from|. Requires PopulateItem to be
// implemented for |T|.
template <class T>
void PopulateListFromArray(const std::vector<T>& from, base::ListValue* out) {
out->Clear();
- for (const auto& item : from)
+ for (const T& item : from)
AddItemToList(item, out);
}