diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/json_schema_compiler/cc_generator.py | 79 | ||||
-rw-r--r-- | tools/json_schema_compiler/cpp_type_generator.py | 7 | ||||
-rwxr-xr-x | tools/json_schema_compiler/cpp_type_generator_test.py | 13 | ||||
-rw-r--r-- | tools/json_schema_compiler/h_generator.py | 4 | ||||
-rwxr-xr-x | tools/json_schema_compiler/idl_schema.py | 2 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/BUILD.gn | 1 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/json_schema_compiler_tests.gyp | 1 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/objects_movable.idl | 23 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/objects_unittest.cc | 40 | ||||
-rw-r--r-- | tools/json_schema_compiler/util.h | 25 |
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); } |