Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from code import Code | 5 from code import Code |
| 6 from model import PropertyType | 6 from model import PropertyType, Type |
| 7 import any_helper | |
| 8 import cpp_util | 7 import cpp_util |
| 9 import model | 8 import model |
| 10 import schema_util | 9 import schema_util |
| 11 import sys | 10 import sys |
| 12 import util_cc_helper | 11 import util_cc_helper |
| 13 | 12 |
| 14 class CCGenerator(object): | 13 class CCGenerator(object): |
| 15 """A .cc generator for a namespace. | 14 """A .cc generator for a namespace. |
| 16 """ | 15 """ |
| 17 def __init__(self, namespace, cpp_type_generator): | 16 def __init__(self, namespace, cpp_type_generator): |
| 18 self._cpp_type_generator = cpp_type_generator | 17 self._type_helper = cpp_type_generator |
| 19 self._namespace = namespace | 18 self._namespace = namespace |
| 20 self._target_namespace = ( | 19 self._target_namespace = ( |
| 21 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 20 self._type_helper.GetCppNamespaceName(self._namespace)) |
| 22 self._util_cc_helper = ( | 21 self._util_cc_helper = ( |
| 23 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | 22 util_cc_helper.UtilCCHelper(self._type_helper)) |
| 24 self._any_helper = any_helper.AnyHelper() | |
| 25 | 23 |
| 26 def Generate(self): | 24 def Generate(self): |
| 27 """Generates a Code object with the .cc for a single namespace. | 25 """Generates a Code object with the .cc for a single namespace. |
| 28 """ | 26 """ |
| 29 c = Code() | 27 c = Code() |
| 30 (c.Append(cpp_util.CHROMIUM_LICENSE) | 28 (c.Append(cpp_util.CHROMIUM_LICENSE) |
| 31 .Append() | 29 .Append() |
| 32 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 30 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
| 33 .Append() | 31 .Append() |
| 34 .Append(self._util_cc_helper.GetIncludePath()) | 32 .Append(self._util_cc_helper.GetIncludePath()) |
| 35 .Append('#include "%s/%s.h"' % | 33 .Append('#include "%s/%s.h"' % |
| 36 (self._namespace.source_file_dir, self._namespace.unix_name)) | 34 (self._namespace.source_file_dir, self._namespace.unix_name)) |
| 37 ) | 35 .Append('#include "base/logging.h"') |
| 38 includes = self._cpp_type_generator.GenerateIncludes() | 36 .Cblock(self._type_helper.GenerateIncludes()) |
| 39 if not includes.IsEmpty(): | 37 .Concat(self._type_helper.GetRootNamespaceStart()) |
| 40 (c.Concat(includes) | 38 .Cblock(self._type_helper.GetNamespaceStart()) |
| 41 .Append() | |
| 42 ) | |
| 43 | |
| 44 (c.Append() | |
| 45 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) | |
| 46 .Concat(self._cpp_type_generator.GetNamespaceStart()) | |
| 47 .Append() | |
| 48 ) | 39 ) |
| 49 if self._namespace.properties: | 40 if self._namespace.properties: |
| 50 (c.Append('//') | 41 (c.Append('//') |
| 51 .Append('// Properties') | 42 .Append('// Properties') |
| 52 .Append('//') | 43 .Append('//') |
| 53 .Append() | 44 .Append() |
| 54 ) | 45 ) |
| 55 for property in self._namespace.properties.values(): | 46 for property in self._namespace.properties.values(): |
| 56 property_code = self._cpp_type_generator.GeneratePropertyValues( | 47 property_code = self._type_helper.GeneratePropertyValues( |
| 57 property, | 48 property, |
| 58 'const %(type)s %(name)s = %(value)s;', | 49 'const %(type)s %(name)s = %(value)s;', |
| 59 nodoc=True) | 50 nodoc=True) |
| 60 if property_code: | 51 if property_code: |
| 61 c.Concat(property_code).Append() | 52 c.Cblock(property_code) |
| 62 if self._namespace.types: | 53 if self._namespace.types: |
| 63 (c.Append('//') | 54 (c.Append('//') |
| 64 .Append('// Types') | 55 .Append('// Types') |
| 65 .Append('//') | 56 .Append('//') |
| 66 .Append() | 57 .Append() |
| 67 ) | 58 .Cblock(self._GenerateTypes(None, self._namespace.types.values())) |
| 68 for type_ in self._namespace.types.values(): | |
| 69 (c.Concat(self._GenerateType( | |
| 70 schema_util.StripSchemaNamespace(type_.name), type_)).Append() | |
| 71 ) | 59 ) |
| 72 if self._namespace.functions: | 60 if self._namespace.functions: |
| 73 (c.Append('//') | 61 (c.Append('//') |
| 74 .Append('// Functions') | 62 .Append('// Functions') |
| 75 .Append('//') | 63 .Append('//') |
| 76 .Append() | 64 .Append() |
| 77 ) | 65 ) |
| 78 for function in self._namespace.functions.values(): | 66 for function in self._namespace.functions.values(): |
| 79 (c.Concat(self._GenerateFunction( | 67 c.Cblock(self._GenerateFunction(function)) |
| 80 cpp_util.Classname(function.name), function)) | |
| 81 .Append() | |
| 82 ) | |
| 83 if self._namespace.events: | 68 if self._namespace.events: |
| 84 (c.Append('//') | 69 (c.Append('//') |
| 85 .Append('// Events') | 70 .Append('// Events') |
| 86 .Append('//') | 71 .Append('//') |
| 87 .Append() | 72 .Append() |
| 88 ) | 73 ) |
| 89 for event in self._namespace.events.values(): | 74 for event in self._namespace.events.values(): |
| 90 (c.Concat(self._GenerateCreateCallbackArguments( | 75 c.Cblock(self._GenerateEvent(event)) |
| 91 cpp_util.Classname(event.name), event, generate_to_json=True)) | 76 (c.Concat(self._type_helper.GetNamespaceEnd()) |
| 92 .Append() | 77 .Cblock(self._type_helper.GetRootNamespaceEnd()) |
| 93 ) | |
| 94 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) | |
| 95 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | |
| 96 .Append() | |
| 97 ) | 78 ) |
| 98 return c | 79 return c |
| 99 | 80 |
| 100 def _GenerateType(self, cpp_namespace, type_): | 81 def _GenerateType(self, cpp_namespace, type_): |
| 101 """Generates the function definitions for a type. | 82 """Generates the function definitions for a type. |
| 102 """ | 83 """ |
| 103 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 84 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 104 c = Code() | 85 c = Code() |
| 105 | 86 |
| 106 if type_.functions: | 87 if type_.functions: |
| 88 # Wrap functions within types in the type's namespace. | |
| 89 (c.Append('namespace %s {' % classname) | |
| 90 .Append()) | |
| 107 for function in type_.functions.values(): | 91 for function in type_.functions.values(): |
| 108 (c.Concat( | 92 c.Cblock(self._GenerateFunction(function)) |
| 109 self._GenerateFunction( | 93 c.Append('} // namespace %s' % classname) |
| 110 cpp_namespace + '::' + cpp_util.Classname(function.name), | 94 elif type_.property_type == PropertyType.ARRAY: |
| 111 function)) | 95 c.Cblock(self._GenerateType(cpp_namespace, type_.item_type)) |
| 112 .Append()) | 96 elif (type_.property_type == PropertyType.OBJECT or |
| 113 elif type_.type_ == PropertyType.OBJECT: | 97 type_.property_type == PropertyType.CHOICES): |
| 114 (c.Concat(self._GeneratePropertyFunctions( | 98 if cpp_namespace is None: |
| 115 cpp_namespace, type_.properties.values())) | 99 classname_in_namespace = classname |
| 116 .Sblock('%(namespace)s::%(classname)s()') | 100 else: |
| 117 .Concat(self._GenerateInitializersAndBody(type_)) | 101 classname_in_namespace = '%s::%s' % (cpp_namespace, classname) |
| 118 .Eblock('%(namespace)s::~%(classname)s() {}') | 102 |
| 119 .Append()) | 103 if type_.property_type == PropertyType.OBJECT: |
| 120 if type_.from_json: | 104 c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace, |
| 121 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | 105 type_.properties.values())) |
| 122 .Append()) | 106 else: |
| 123 if type_.from_client: | 107 c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices)) |
| 124 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | 108 |
| 125 .Append()) | 109 (c.Append('%s::%s()' % (classname_in_namespace, classname)) |
| 126 elif self._cpp_type_generator.IsEnumOrEnumRef(type_): | 110 .Cblock(self._GenerateInitializersAndBody(type_)) |
| 127 (c.Concat(self._GenerateCreateEnumTypeValue(cpp_namespace, type_)) | 111 .Append('%s::~%s() {}' % (classname_in_namespace, classname)) |
| 128 .Append() | 112 .Append() |
| 129 .Concat(self._GenerateEnumFromString(cpp_namespace, type_)) | 113 ) |
| 130 .Append() | 114 if type_.origin.from_json: |
| 131 .Concat(self._GenerateEnumToString(cpp_namespace, type_)) | 115 c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_)) |
| 132 .Append()) | 116 if type_.origin.from_client: |
| 133 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) | 117 c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_)) |
| 118 elif type_.property_type == PropertyType.ENUM: | |
| 119 (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) | |
| 120 .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) | |
| 121 ) | |
| 134 | 122 |
| 135 return c | 123 return c |
| 136 | 124 |
| 137 def _GenerateInitializersAndBody(self, type_): | 125 def _GenerateInitializersAndBody(self, type_): |
| 138 items = [] | 126 items = [] |
| 139 for prop in type_.properties.values(): | 127 for prop in type_.properties.values(): |
| 140 if prop.optional: | 128 if prop.optional: |
| 141 continue | 129 continue |
| 142 | 130 |
| 143 t = prop.type_ | 131 t = prop.type_ |
| 144 if t == PropertyType.INTEGER: | 132 if t.property_type == PropertyType.INTEGER: |
| 145 items.append('%s(0)' % prop.unix_name) | 133 items.append('%s(0)' % prop.unix_name) |
| 146 elif t == PropertyType.DOUBLE: | 134 elif t.property_type == PropertyType.DOUBLE: |
| 147 items.append('%s(0.0)' % prop.unix_name) | 135 items.append('%s(0.0)' % prop.unix_name) |
| 148 elif t == PropertyType.BOOLEAN: | 136 elif t.property_type == PropertyType.BOOLEAN: |
| 149 items.append('%s(false)' % prop.unix_name) | 137 items.append('%s(false)' % prop.unix_name) |
| 150 elif t == PropertyType.BINARY: | 138 elif t.property_type == PropertyType.BINARY: |
| 151 items.append('%s(NULL)' % prop.unix_name) | 139 items.append('%s(NULL)' % prop.unix_name) |
| 152 elif (t == PropertyType.ADDITIONAL_PROPERTIES or | 140 elif (t.property_type == PropertyType.ANY or |
| 153 t == PropertyType.ANY or | 141 t.property_type == PropertyType.ARRAY or |
| 154 t == PropertyType.ARRAY or | 142 t.property_type == PropertyType.CHOICES or |
| 155 t == PropertyType.CHOICES or | 143 t.property_type == PropertyType.ENUM or |
| 156 t == PropertyType.ENUM or | 144 t.property_type == PropertyType.OBJECT or |
| 157 t == PropertyType.OBJECT or | 145 t.property_type == PropertyType.FUNCTION or |
| 158 t == PropertyType.FUNCTION or | 146 t.property_type == PropertyType.REF or |
| 159 t == PropertyType.REF or | 147 t.property_type == PropertyType.STRING): |
| 160 t == PropertyType.STRING): | |
| 161 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we | 148 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we |
| 162 # don't presently have the semantics to indicate which one of a set | 149 # don't presently have the semantics to indicate which one of a set |
| 163 # should be the default. | 150 # should be the default. |
| 164 continue | 151 continue |
| 165 else: | 152 else: |
| 166 sys.exit("Unhandled PropertyType: %s" % t) | 153 raise TypeError(type(t)) |
|
Yoyo Zhou
2013/01/15 01:49:25
type(t)?
not at google - send to devlin
2013/01/15 21:47:27
I presume you mean this should be just "t" not "ty
Yoyo Zhou
2013/01/16 23:14:39
Well I didn't understand what the type(t) was for.
| |
| 167 | 154 |
| 168 if items: | 155 if items: |
| 169 s = ': %s' % (', '.join(items)) | 156 s = ': %s' % (', '.join(items)) |
| 170 else: | 157 else: |
| 171 s = '' | 158 s = '' |
| 172 s = s + ' {}' | 159 s = s + ' {}' |
| 173 return Code().Append(s) | 160 return Code().Append(s) |
| 174 | 161 |
| 175 def _GenerateTypePopulate(self, cpp_namespace, type_): | 162 def _GenerateTypePopulate(self, cpp_namespace, type_): |
| 176 """Generates the function for populating a type given a pointer to it. | 163 """Generates the function for populating a type given a pointer to it. |
| 177 | 164 |
| 178 E.g for type "Foo", generates Foo::Populate() | 165 E.g for type "Foo", generates Foo::Populate() |
| 179 """ | 166 """ |
| 180 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 167 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 181 c = Code() | 168 c = Code() |
| 182 (c.Append('// static') | 169 (c.Append('// static') |
| 183 .Sblock('bool %(namespace)s::Populate' | 170 .Sblock('bool %(namespace)s::Populate(' |
| 184 '(const base::Value& value, %(name)s* out) {') | 171 'const base::Value& value, %(name)s* out) {') |
|
Yoyo Zhou
2013/01/15 01:49:25
nit: this indent looks worse than before
not at google - send to devlin
2013/01/15 21:47:27
It's so that it matches up with how you'd usually
Yoyo Zhou
2013/01/16 23:14:39
I think it gives you the false sense that the line
not at google - send to devlin
2013/01/17 00:11:49
Done.
| |
| 185 .Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') | 172 ) |
| 173 if type_.property_type == PropertyType.CHOICES: | |
| 174 for choice in type_.choices: | |
| 175 value_type = cpp_util.GetValueType(self._type_helper.FollowRef(choice)) | |
| 176 (c.Sblock('if (value.IsType(%s)) {' % value_type) | |
| 177 .Concat(self._GeneratePopulateVariableFromValue( | |
| 178 choice, | |
| 179 '(&value)', | |
| 180 'out->as_%s' % choice.unix_name, | |
| 181 'false', | |
| 182 # Choices fields are scoped_ptrs, so pretend they're optional. | |
| 183 is_optional=True)) | |
|
Yoyo Zhou
2013/01/15 01:49:25
Is it worth it to rename this (because optionality
not at google - send to devlin
2013/01/15 21:47:27
Done. I did it throughout the compiler, since what
| |
| 184 .Append('return true;') | |
| 185 .Eblock('}') | |
| 186 ) | |
| 187 c.Append('return false;') | |
| 188 elif type_.property_type == PropertyType.OBJECT: | |
| 189 (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') | |
| 186 .Append(' return false;') | 190 .Append(' return false;') |
| 187 ) | |
| 188 if type_.properties: | |
| 189 (c.Append('const base::DictionaryValue* dict = ' | |
| 190 'static_cast<const base::DictionaryValue*>(&value);') | |
| 191 .Append() | |
| 192 ) | 191 ) |
| 192 if type_.properties or type_.additional_properties is not None: | |
| 193 c.Append('const base::DictionaryValue* dict = ' | |
| 194 'static_cast<const base::DictionaryValue*>(&value);') | |
| 193 for prop in type_.properties.values(): | 195 for prop in type_.properties.values(): |
| 194 c.Concat(self._InitializePropertyToDefault(prop, 'out')) | 196 c.Concat(self._InitializePropertyToDefault(prop, 'out')) |
| 195 for prop in type_.properties.values(): | 197 for prop in type_.properties.values(): |
| 196 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 198 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
| 197 c.Append('out->additional_properties.MergeDictionary(dict);') | 199 if type_.additional_properties is not None: |
| 198 # remove all keys that are actual properties | 200 cpp_type = self._type_helper.GetCppType(type_.additional_properties, |
| 199 for cur_prop in type_.properties.values(): | 201 is_in_container=True) |
| 200 if prop != cur_prop: | 202 (c.Append('for (base::DictionaryValue::Iterator it(*dict);') |
| 201 c.Append('out->additional_properties' | 203 .Sblock(' it.HasNext(); it.Advance()) {') |
| 202 '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name) | 204 .Append('%s tmp;' % cpp_type.strip()) |
|
Yoyo Zhou
2013/01/15 01:49:25
why do you need both is_in_container=True and stri
not at google - send to devlin
2013/01/15 21:47:27
Added comment.
Yoyo Zhou
2013/01/16 23:14:39
But why do we need is_in_container?
not at google - send to devlin
2013/01/17 00:11:49
So that GetCppType knows that if it's a pointer or
| |
| 203 c.Append() | 205 .Concat(self._GeneratePopulateVariableFromValue( |
| 204 else: | 206 type_.additional_properties, |
| 205 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | 207 '(&it.value())', |
| 206 (c.Append('return true;') | 208 'tmp', |
| 207 .Eblock('}') | 209 'false')) |
| 208 ) | 210 .Append('out->additional_properties[it.key()] = tmp;') |
| 209 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | 211 .Eblock('}') |
| 212 ) | |
| 213 c.Append('return true;') | |
| 214 (c.Eblock('}') | |
| 215 .Substitute({'namespace': cpp_namespace, 'name': classname})) | |
| 210 return c | 216 return c |
| 211 | 217 |
| 212 def _GenerateTypePopulateProperty(self, prop, src, dst): | 218 def _GenerateTypePopulateProperty(self, prop, src, dst): |
| 213 """Generate the code to populate a single property in a type. | 219 """Generate the code to populate a single property in a type. |
| 214 | 220 |
| 215 src: base::DictionaryValue* | 221 src: base::DictionaryValue* |
| 216 dst: Type* | 222 dst: Type* |
| 217 """ | 223 """ |
| 218 c = Code() | 224 c = Code() |
| 219 value_var = prop.unix_name + '_value' | 225 value_var = prop.unix_name + '_value' |
| 220 c.Append('const base::Value* %(value_var)s = NULL;') | 226 c.Append('const base::Value* %(value_var)s = NULL;') |
| 221 if prop.optional: | 227 if prop.optional: |
| 222 (c.Sblock( | 228 (c.Sblock( |
| 223 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') | 229 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') |
| 224 .Concat(self._GeneratePopulatePropertyFromValue( | 230 .Concat(self._GeneratePopulatePropertyFromValue( |
| 225 prop, value_var, dst, 'false'))) | 231 prop, value_var, dst, 'false'))) |
| 226 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 232 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 233 if underlying_type.property_type == PropertyType.ENUM: | |
| 227 (c.Append('} else {') | 234 (c.Append('} else {') |
| 228 .Append('%%(dst)s->%%(name)s = %s;' % | 235 .Append('%%(dst)s->%%(name)s = %s;' % |
| 229 self._cpp_type_generator.GetEnumNoneValue(prop))) | 236 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 230 c.Eblock('}') | 237 c.Eblock('}') |
| 231 else: | 238 else: |
| 232 (c.Append( | 239 (c.Append( |
| 233 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') | 240 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') |
| 234 .Append(' return false;') | 241 .Append(' return false;') |
| 235 .Concat(self._GeneratePopulatePropertyFromValue( | 242 .Concat(self._GeneratePopulatePropertyFromValue( |
| 236 prop, value_var, dst, 'false')) | 243 prop, value_var, dst, 'false')) |
| 237 ) | 244 ) |
| 238 c.Append() | 245 c.Append() |
| 239 c.Substitute({ | 246 c.Substitute({ |
| 240 'value_var': value_var, | 247 'value_var': value_var, |
| 241 'key': prop.name, | 248 'key': prop.name, |
| 242 'src': src, | 249 'src': src, |
| 243 'dst': dst, | 250 'dst': dst, |
| 244 'name': prop.unix_name | 251 'name': prop.unix_name |
| 245 }) | 252 }) |
| 246 return c | 253 return c |
| 247 | 254 |
| 248 def _GenerateTypeToValue(self, cpp_namespace, type_): | 255 def _GenerateTypeToValue(self, cpp_namespace, type_): |
| 249 """Generates a function that serializes the type into a | 256 """Generates a function that serializes the type into a base::Value. |
| 250 |base::DictionaryValue|. | 257 E.g. for type "Foo" generates Foo::ToValue() |
| 258 """ | |
| 259 if type_.property_type == PropertyType.OBJECT: | |
| 260 return self._GenerateObjectTypeToValue(cpp_namespace, type_) | |
| 261 elif type_.property_type == PropertyType.CHOICES: | |
| 262 return self._GenerateChoiceTypeToValue(cpp_namespace, type_) | |
| 263 else: | |
| 264 raise ValueError("Unsupported propety type %s" % type_.type_) | |
|
Yoyo Zhou
2013/01/15 01:49:25
typo: property
not at google - send to devlin
2013/01/15 21:47:27
Done.
| |
| 251 | 265 |
| 252 E.g. for type "Foo" generates Foo::ToValue() | 266 def _GenerateObjectTypeToValue(self, cpp_namespace, type_): |
| 267 """Generates a function that serializes an object-representing type | |
| 268 into a base::DictionaryValue. | |
| 253 """ | 269 """ |
| 254 c = Code() | 270 c = Code() |
| 255 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % | 271 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % |
| 256 cpp_namespace) | 272 cpp_namespace) |
| 257 .Append('scoped_ptr<base::DictionaryValue> value(' | 273 .Append('scoped_ptr<base::DictionaryValue> value(' |
| 258 'new base::DictionaryValue());') | 274 'new base::DictionaryValue());') |
| 259 .Append() | 275 .Append() |
| 260 ) | 276 ) |
| 277 | |
| 261 for prop in type_.properties.values(): | 278 for prop in type_.properties.values(): |
| 262 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 279 if prop.optional: |
| 263 c.Append('value->MergeDictionary(&%s);' % prop.unix_name) | 280 # Optional enum values are generated with a NONE enum value. |
| 264 else: | 281 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 265 if prop.optional: | 282 if underlying_type.property_type == PropertyType.ENUM: |
| 266 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 283 c.Sblock('if (%s != %s) {' % |
| 267 c.Sblock('if (%s != %s) {' % | 284 (prop.unix_name, |
| 268 (prop.unix_name, | 285 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 269 self._cpp_type_generator.GetEnumNoneValue(prop))) | 286 else: |
| 270 elif prop.type_ == PropertyType.CHOICES: | 287 c.Sblock('if (%s.get()) {' % prop.unix_name) |
| 271 c.Sblock('if (%s_type != %s) {' % | |
| 272 (prop.unix_name, | |
| 273 self._cpp_type_generator.GetEnumNoneValue(prop))) | |
| 274 else: | |
| 275 c.Sblock('if (%s.get()) {' % prop.unix_name) | |
| 276 | 288 |
| 277 if prop.type_ == prop.compiled_type: | 289 # ANY is a base::Value which is abstract and cannot be a direct member, so |
| 278 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 290 # we always need to wrap it in a scoped_ptr. |
| 279 prop.name, | 291 is_optional_for_value = (prop.optional or |
| 280 self._CreateValueFromProperty(prop, 'this->' + prop.unix_name))) | 292 prop.type_.property_type == PropertyType.ANY) |
| 281 else: | 293 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( |
| 282 conversion_src = 'this->' + prop.unix_name | 294 prop.name, |
| 283 if prop.optional: | 295 self._CreateValueFromType(prop.type_, |
| 284 conversion_src = '*' + conversion_src | 296 'this->%s' % prop.unix_name, |
| 285 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop), | 297 is_optional=is_optional_for_value))) |
| 286 prop.unix_name)) | 298 |
| 287 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | 299 if prop.optional: |
| 288 self._cpp_type_generator.GetReferencedProperty(prop), | 300 c.Eblock('}'); |
| 289 conversion_src, | 301 |
| 290 prop.unix_name) + ';') | 302 if type_.additional_properties is not None: |
| 291 .Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 303 # Non-copyable types will be wrapped in a linked_ptr for inclusion in |
| 292 prop.unix_name, | 304 # maps, so we need to unwrap them. |
|
Yoyo Zhou
2013/01/15 01:49:25
Do you have to worry about enums or optionality he
not at google - send to devlin
2013/01/15 21:47:27
Optionality isn't an issue since this is a type, n
| |
| 293 self._CreateValueFromProperty(prop, prop.unix_name))) | 305 needs_unwrap = ( |
| 294 ) | 306 not self._type_helper.IsCopyable(type_.additional_properties)) |
| 295 if prop.optional: | 307 |
| 296 c.Eblock('}'); | 308 (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' % |
| 297 (c.Append() | 309 (self._type_helper.GetCppType(type_.additional_properties, |
| 298 .Append('return value.Pass();') | 310 is_in_container=True))) |
| 311 .Append(' additional_properties.begin();') | |
| 312 .Append(' it != additional_properties.end(); ++it) {') | |
| 313 .Append('value->SetWithoutPathExpansion(it->first, %s);' % | |
| 314 self._CreateValueFromType( | |
| 315 type_.additional_properties, | |
| 316 '%sit->second' % ('*' if needs_unwrap else '',))) | |
|
Yoyo Zhou
2013/01/15 01:49:25
nit: don't need the ,
not at google - send to devlin
2013/01/15 21:47:27
Done. I swear there was a day when if you put pare
| |
| 317 .Eblock('}') | |
| 318 ) | |
| 319 | |
| 320 return (c.Append() | |
| 321 .Append('return value.Pass();') | |
| 322 .Eblock('}')) | |
| 323 | |
| 324 def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): | |
| 325 """Generates a function that serializes a choice-representing type | |
| 326 into a base::Value. | |
| 327 """ | |
| 328 c = Code() | |
| 329 c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) | |
| 330 for choice in type_.choices: | |
| 331 choice_var = 'as_%s' % choice.unix_name | |
| 332 (c.Sblock('if (%s) {' % choice_var) | |
| 333 .Append('return scoped_ptr<base::Value>(%s);' % | |
| 334 self._CreateValueFromType(choice, '*%s' % choice_var)) | |
| 335 .Eblock('}') | |
| 336 ) | |
| 337 (c.Append('NOTREACHED() << "%s has no choices";' % type_.unix_name) | |
|
Yoyo Zhou
2013/01/15 01:49:25
This message is confusing because it could mean mu
not at google - send to devlin
2013/01/15 21:47:27
Done.
| |
| 338 .Append('return scoped_ptr<base::Value>();') | |
| 299 .Eblock('}') | 339 .Eblock('}') |
| 300 ) | 340 ) |
| 301 return c | 341 return c |
| 302 | 342 |
| 303 def _GenerateFunction(self, cpp_namespace, function): | 343 def _GenerateFunction(self, function): |
| 304 """Generates the definitions for function structs. | 344 """Generates the definitions for function structs. |
| 305 """ | 345 """ |
| 306 c = Code() | 346 c = Code() |
| 307 | 347 |
| 348 # TODO(kalman): use function.unix_name not Classname. | |
| 349 function_namespace = cpp_util.Classname(function.name) | |
| 350 (c.Append('namespace %s {' % function_namespace) | |
| 351 .Append() | |
| 352 ) | |
| 353 | |
| 308 # Params::Populate function | 354 # Params::Populate function |
| 309 if function.params: | 355 if function.params: |
| 310 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params', | 356 c.Concat(self._GeneratePropertyFunctions('Params', function.params)) |
| 311 function.params)) | 357 (c.Append('Params::Params() {}') |
| 312 (c.Append('%(cpp_namespace)s::Params::Params() {}') | 358 .Append('Params::~Params() {}') |
| 313 .Append('%(cpp_namespace)s::Params::~Params() {}') | |
| 314 .Append() | 359 .Append() |
| 315 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function)) | 360 .Cblock(self._GenerateFunctionParamsCreate(function)) |
| 316 .Append() | |
| 317 ) | 361 ) |
| 318 | 362 |
| 319 # Results::Create function | 363 # Results::Create function |
| 320 if function.callback: | 364 if function.callback: |
| 321 c.Concat(self._GenerateCreateCallbackArguments( | 365 c.Concat(self._GenerateCreateCallbackArguments('Results', |
| 322 "%s::Results" % cpp_namespace, function.callback)) | 366 function.callback)) |
| 323 | 367 |
| 324 c.Substitute({'cpp_namespace': cpp_namespace}) | 368 c.Append('} // namespace %s' % function_namespace) |
| 325 | |
| 326 return c | 369 return c |
| 327 | 370 |
| 328 def _CreateValueFromProperty(self, prop, var): | 371 def _GenerateEvent(self, event): |
| 329 """Creates a base::Value given a property. Generated code passes ownership | 372 # TODO(kalman): use event.unix_name not Classname. |
| 373 c = Code() | |
| 374 event_namespace = cpp_util.Classname(event.name) | |
| 375 (c.Append('namespace %s {' % event_namespace) | |
| 376 .Append() | |
| 377 .Cblock(self._GenerateCreateCallbackArguments(None, event)) | |
| 378 .Append('} // namespace %s' % event_namespace) | |
| 379 ) | |
| 380 return c | |
| 381 | |
| 382 def _CreateValueFromType(self, type_, var, is_optional=False): | |
| 383 """Creates a base::Value given a type. Generated code passes ownership | |
| 330 to caller. | 384 to caller. |
| 331 | 385 |
| 332 var: variable or variable* | 386 var: variable or variable* |
| 333 | 387 |
| 334 E.g for std::string, generate base::Value::CreateStringValue(var) | 388 E.g for std::string, generate base::Value::CreateStringValue(var) |
| 335 """ | 389 """ |
| 336 if prop.type_ == PropertyType.CHOICES: | 390 underlying_type = self._type_helper.FollowRef(type_) |
| 337 return 'Get%sChoiceValue().release()' % cpp_util.Classname(prop.name) | 391 if (underlying_type.property_type == PropertyType.CHOICES or |
| 338 elif self._IsObjectOrObjectRef(prop): | 392 underlying_type.property_type == PropertyType.OBJECT): |
| 339 if prop.optional: | 393 if is_optional: |
| 340 return '%s->ToValue().release()' % var | 394 return '(%s)->ToValue().release()' % var |
| 341 else: | 395 else: |
| 342 return '%s.ToValue().release()' % var | 396 return '(%s).ToValue().release()' % var |
| 343 elif prop.type_ == PropertyType.ANY: | 397 elif (underlying_type.property_type == PropertyType.ANY or |
| 344 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var) | 398 underlying_type.property_type == PropertyType.FUNCTION): |
| 345 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 399 if is_optional: |
| 346 return '%s.DeepCopy()' % var | 400 vardot = '(%s)->' % var |
| 347 elif prop.type_ == PropertyType.FUNCTION: | |
| 348 if prop.optional: | |
| 349 vardot = var + '->' | |
| 350 else: | 401 else: |
| 351 vardot = var + '.' | 402 vardot = '(%s).' % var |
| 352 return '%sDeepCopy()' % vardot | 403 return '%sDeepCopy()' % vardot |
| 353 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 404 elif underlying_type.property_type == PropertyType.ENUM: |
| 354 return 'base::Value::CreateStringValue(ToString(%s))' % var | 405 return 'base::Value::CreateStringValue(ToString(%s))' % var |
| 355 elif prop.type_ == PropertyType.BINARY: | 406 elif underlying_type.property_type == PropertyType.BINARY: |
| 356 if prop.optional: | 407 if is_optional: |
| 357 vardot = var + '->' | 408 vardot = var + '->' |
| 358 else: | 409 else: |
| 359 vardot = var + '.' | 410 vardot = var + '.' |
| 360 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % | 411 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % |
| 361 (vardot, vardot)) | 412 (vardot, vardot)) |
| 362 elif self._IsArrayOrArrayRef(prop): | 413 elif underlying_type.property_type == PropertyType.ARRAY: |
| 363 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( | 414 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( |
| 364 self._cpp_type_generator.GetReferencedProperty(prop), var, | 415 underlying_type, |
| 365 prop.optional) | 416 var, |
| 366 elif self._IsFundamentalOrFundamentalRef(prop): | 417 is_optional) |
| 367 # If prop.type != prop.compiled_type, then no asterisk is necessary | 418 elif underlying_type.property_type.is_fundamental: |
| 368 # because the target is a local variable and not a dereferenced scoped | 419 if is_optional: |
| 369 # pointer. The asterisk is instead prepended to conversion_src around line | 420 var = '*%s' % var |
| 370 # 273. | 421 if underlying_type.property_type == PropertyType.STRING: |
| 371 if prop.optional and prop.type_ == prop.compiled_type: | 422 return 'new base::StringValue(%s)' % var |
| 372 var = '*' + var | 423 else: |
| 373 prop = self._cpp_type_generator.GetReferencedProperty(prop); | 424 return 'new base::FundamentalValue(%s)' % var |
| 374 return { | |
| 375 PropertyType.STRING: 'base::Value::CreateStringValue(%s)', | |
| 376 PropertyType.BOOLEAN: 'base::Value::CreateBooleanValue(%s)', | |
| 377 PropertyType.INTEGER: 'base::Value::CreateIntegerValue(%s)', | |
| 378 PropertyType.DOUBLE: 'base::Value::CreateDoubleValue(%s)', | |
| 379 }[prop.type_] % var | |
| 380 else: | 425 else: |
| 381 raise NotImplementedError('Conversion of %s to base::Value not ' | 426 raise NotImplementedError('Conversion of %s to base::Value not ' |
| 382 'implemented' % repr(prop.type_)) | 427 'implemented' % repr(type_.type_)) |
| 383 | 428 |
| 384 def _GenerateParamsCheck(self, function, var): | 429 def _GenerateParamsCheck(self, function, var): |
| 385 """Generates a check for the correct number of arguments when creating | 430 """Generates a check for the correct number of arguments when creating |
| 386 Params. | 431 Params. |
| 387 """ | 432 """ |
| 388 c = Code() | 433 c = Code() |
| 389 num_required = 0 | 434 num_required = 0 |
| 390 for param in function.params: | 435 for param in function.params: |
| 391 if not param.optional: | 436 if not param.optional: |
| 392 num_required += 1 | 437 num_required += 1 |
| 393 if num_required == len(function.params): | 438 if num_required == len(function.params): |
| 394 c.Append('if (%(var)s.GetSize() != %(total)d)') | 439 c.Append('if (%(var)s.GetSize() != %(total)d)') |
| 395 elif not num_required: | 440 elif not num_required: |
| 396 c.Append('if (%(var)s.GetSize() > %(total)d)') | 441 c.Append('if (%(var)s.GetSize() > %(total)d)') |
| 397 else: | 442 else: |
| 398 c.Append('if (%(var)s.GetSize() < %(required)d' | 443 c.Append('if (%(var)s.GetSize() < %(required)d' |
| 399 ' || %(var)s.GetSize() > %(total)d)') | 444 ' || %(var)s.GetSize() > %(total)d)') |
| 400 c.Append(' return scoped_ptr<Params>();') | 445 c.Append(' return scoped_ptr<Params>();') |
| 401 c.Substitute({ | 446 c.Substitute({ |
| 402 'var': var, | 447 'var': var, |
| 403 'required': num_required, | 448 'required': num_required, |
| 404 'total': len(function.params), | 449 'total': len(function.params), |
| 405 }) | 450 }) |
| 406 return c | 451 return c |
| 407 | 452 |
| 408 def _GenerateFunctionParamsCreate(self, cpp_namespace, function): | 453 def _GenerateFunctionParamsCreate(self, function): |
| 409 """Generate function to create an instance of Params. The generated | 454 """Generate function to create an instance of Params. The generated |
| 410 function takes a base::ListValue of arguments. | 455 function takes a base::ListValue of arguments. |
| 411 | 456 |
| 412 E.g for function "Bar", generate Bar::Params::Create() | 457 E.g for function "Bar", generate Bar::Params::Create() |
| 413 """ | 458 """ |
| 414 c = Code() | 459 c = Code() |
| 415 (c.Append('// static') | 460 (c.Append('// static') |
| 416 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' | 461 .Sblock('scoped_ptr<Params> ' |
| 417 '%(cpp_namespace)s::Params::Create(const base::ListValue& args) {') | 462 'Params::Create(const base::ListValue& args) {') |
| 418 .Concat(self._GenerateParamsCheck(function, 'args')) | 463 .Concat(self._GenerateParamsCheck(function, 'args')) |
| 419 .Append('scoped_ptr<Params> params(new Params());') | 464 .Append('scoped_ptr<Params> params(new Params());') |
| 420 ) | 465 ) |
| 421 c.Substitute({'cpp_namespace': cpp_namespace}) | |
| 422 | 466 |
| 423 for param in function.params: | 467 for param in function.params: |
| 424 c.Concat(self._InitializePropertyToDefault(param, 'params')) | 468 c.Concat(self._InitializePropertyToDefault(param, 'params')) |
| 425 | 469 |
| 426 for i, param in enumerate(function.params): | 470 for i, param in enumerate(function.params): |
| 427 # Any failure will cause this function to return. If any argument is | 471 # Any failure will cause this function to return. If any argument is |
| 428 # incorrect or missing, those following it are not processed. Note that | 472 # incorrect or missing, those following it are not processed. Note that |
| 429 # for optional arguments, we allow missing arguments and proceed because | 473 # for optional arguments, we allow missing arguments and proceed because |
| 430 # there may be other arguments following it. | 474 # there may be other arguments following it. |
| 431 failure_value = 'scoped_ptr<Params>()' | 475 failure_value = 'scoped_ptr<Params>()' |
| 432 c.Append() | 476 c.Append() |
| 433 value_var = param.unix_name + '_value' | 477 value_var = param.unix_name + '_value' |
| 434 (c.Append('const base::Value* %(value_var)s = NULL;') | 478 (c.Append('const base::Value* %(value_var)s = NULL;') |
| 435 .Append('if (args.Get(%(i)s, &%(value_var)s) &&\n' | 479 .Append('if (args.Get(%(i)s, &%(value_var)s) &&') |
| 436 ' !%(value_var)s->IsType(base::Value::TYPE_NULL))') | 480 .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {') |
| 437 .Sblock('{') | |
| 438 .Concat(self._GeneratePopulatePropertyFromValue( | 481 .Concat(self._GeneratePopulatePropertyFromValue( |
| 439 param, value_var, 'params', failure_value)) | 482 param, value_var, 'params', failure_value)) |
| 440 .Eblock('}') | 483 .Eblock('}') |
| 441 ) | 484 ) |
| 442 if not param.optional: | 485 if not param.optional: |
| 443 (c.Sblock('else {') | 486 (c.Sblock('else {') |
| 444 .Append('return %s;' % failure_value) | 487 .Append('return %s;' % failure_value) |
| 445 .Eblock('}') | 488 .Eblock('}') |
| 446 ) | 489 ) |
| 447 c.Substitute({'value_var': value_var, 'i': i}) | 490 c.Substitute({'value_var': value_var, 'i': i}) |
| 448 (c.Append() | 491 (c.Append() |
| 449 .Append('return params.Pass();') | 492 .Append('return params.Pass();') |
| 450 .Eblock('}') | 493 .Eblock('}') |
| 451 .Append() | 494 .Append() |
| 452 ) | 495 ) |
| 453 | 496 |
| 454 return c | 497 return c |
| 455 | 498 |
| 456 def _GeneratePopulatePropertyFromValue( | 499 def _GeneratePopulatePropertyFromValue(self, |
| 457 self, prop, value_var, dst, failure_value, check_type=True): | 500 prop, |
| 458 """Generates code to populate a model.Property given a base::Value*. The | 501 src_var, |
| 459 existence of data inside the base::Value* is assumed so checks for existence | 502 dst_class_var, |
| 460 should be performed before the code this generates. | 503 failure_value): |
| 461 | 504 """Generates code to populate property |prop| of |dst_class_var| (a |
| 462 prop: the property the code is populating. | 505 pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for |
| 463 value_var: a base::Value* that should represent |prop|. | 506 semantics. |
| 464 dst: the object with |prop| as a member. | 507 """ |
| 465 failure_value: the value to return if |prop| cannot be extracted from | 508 return self._GeneratePopulateVariableFromValue(prop.type_, |
| 466 |value_var| | 509 src_var, |
| 467 check_type: if true, will check if |value_var| is the correct | 510 '%s->%s' % (dst_class_var, |
| 468 base::Value::Type | 511 prop.unix_name), |
| 512 failure_value, | |
| 513 is_optional=prop.optional) | |
| 514 | |
| 515 def _GeneratePopulateVariableFromValue(self, | |
| 516 type_, | |
| 517 src_var, | |
| 518 dst_var, | |
| 519 failure_value, | |
| 520 is_optional=False): | |
| 521 """Generates code to populate a variable |dst_var| of type |type_| from a | |
| 522 Value* at |src_var|. The Value* is assumed to be non-NULL. Generates a | |
| 523 failure return type of |failure_value|. | |
|
Yoyo Zhou
2013/01/15 01:49:25
Explain what the failure condition is.
not at google - send to devlin
2013/01/15 21:47:27
Done.
| |
| 469 """ | 524 """ |
| 470 c = Code() | 525 c = Code() |
| 471 c.Sblock('{') | 526 c.Sblock('{') |
| 472 | 527 |
| 473 if self._IsFundamentalOrFundamentalRef(prop): | 528 underlying_type = self._type_helper.FollowRef(type_) |
| 474 self._GenerateFundamentalOrFundamentalRefPopulate(c, prop, value_var, dst) | 529 |
| 475 elif self._IsObjectOrObjectRef(prop): | 530 if underlying_type.property_type.is_fundamental: |
| 476 self._GenerateObjectOrObjectRefPopulate(c, prop) | 531 if is_optional: |
| 477 elif prop.type_ == PropertyType.FUNCTION: | 532 (c.Append('%(cpp_type)s temp;') |
| 478 self._GenerateFunctionPopulate(c, prop) | 533 .Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
| 479 elif prop.type_ == PropertyType.ANY: | 534 self._type_helper.FollowRef(type_), src_var, '&temp')) |
| 480 self._GenerateAnyPopulate(c, prop, value_var, dst) | 535 .Append(' return %(failure_value)s;') |
| 481 elif self._IsArrayOrArrayRef(prop): | 536 .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));') |
| 482 self._GenerateArrayOrArrayRefPopulate(c, prop, dst) | 537 ) |
| 483 elif prop.type_ == PropertyType.CHOICES: | 538 else: |
| 484 self._GenerateChoicePopulate(c, prop, value_var, dst, failure_value) | 539 (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
| 485 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 540 self._type_helper.FollowRef(type_), |
| 486 self._GenerateEnumPopulate(c, prop, value_var) | 541 src_var, |
| 487 elif prop.type_ == PropertyType.BINARY: | 542 '&%s' % dst_var)) |
| 488 self._GenerateBinaryPopulate(c, prop) | 543 .Append(' return %(failure_value)s;') |
| 544 ) | |
| 545 elif underlying_type.property_type == PropertyType.OBJECT: | |
| 546 if is_optional: | |
| 547 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 548 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') | |
| 549 .Append(' return %(failure_value)s;') | |
| 550 .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') | |
| 551 .Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))') | |
| 552 .Append(' return %(failure_value)s;') | |
| 553 .Append('%(dst_var)s = temp.Pass();') | |
| 554 ) | |
| 555 else: | |
| 556 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 557 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') | |
| 558 .Append(' return %(failure_value)s;') | |
| 559 .Append('if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))') | |
| 560 .Append(' return %(failure_value)s;') | |
| 561 ) | |
| 562 elif underlying_type.property_type == PropertyType.FUNCTION: | |
| 563 if is_optional: | |
| 564 c.Append('%(dst_var)s.reset(new base::DictionaryValue());') | |
| 565 elif underlying_type.property_type == PropertyType.ANY: | |
| 566 c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());') | |
| 567 elif underlying_type.property_type == PropertyType.ARRAY: | |
| 568 # util_cc_helper deals with optional and required arrays | |
| 569 (c.Append('const base::ListValue* list = NULL;') | |
| 570 .Append('if (!%(src_var)s->GetAsList(&list))') | |
| 571 .Append(' return %(failure_value)s;')) | |
| 572 item_type = underlying_type.item_type | |
| 573 if item_type.property_type == PropertyType.ENUM: | |
| 574 c.Concat(self._GenerateListValueToEnumArrayConversion( | |
| 575 item_type, | |
| 576 'list', | |
| 577 dst_var, | |
| 578 failure_value, | |
| 579 is_optional=is_optional)) | |
| 580 else: | |
| 581 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | |
| 582 underlying_type, | |
| 583 'list', | |
| 584 dst_var, | |
| 585 is_optional)) | |
| 586 .Append(' return %(failure_value)s;') | |
| 587 ) | |
| 588 elif underlying_type.property_type == PropertyType.CHOICES: | |
| 589 if is_optional: | |
| 590 (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') | |
| 591 .Append('if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))') | |
| 592 .Append(' return %(failure_value)s;') | |
| 593 .Append('%(dst_var)s = temp.Pass();') | |
| 594 ) | |
| 595 else: | |
| 596 (c.Append('if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))') | |
| 597 .Append(' return %(failure_value)s;') | |
| 598 ) | |
| 599 elif underlying_type.property_type == PropertyType.ENUM: | |
| 600 c.Concat(self._GenerateStringToEnumConversion(type_, | |
| 601 src_var, | |
| 602 dst_var, | |
| 603 failure_value)) | |
| 604 elif underlying_type.property_type == PropertyType.BINARY: | |
| 605 (c.Append('if (!%(src_var)s->IsType(%(value_type)s))') | |
| 606 .Append(' return %(failure_value)s;') | |
| 607 .Append('const base::BinaryValue* binary_value =') | |
| 608 .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);') | |
| 609 ) | |
| 610 if is_optional: | |
| 611 (c.Append('%(dst_var)s.reset(') | |
| 612 .Append(' new std::string(binary_value->GetBuffer(),') | |
| 613 .Append(' binary_value->GetSize()));') | |
| 614 ) | |
| 615 else: | |
| 616 (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),') | |
| 617 .Append(' binary_value->GetSize());') | |
| 618 ) | |
| 489 else: | 619 else: |
| 490 raise NotImplementedError(prop.type_) | 620 raise NotImplementedError(type_) |
| 491 c.Eblock('}') | 621 |
| 492 sub = { | 622 sub = { |
| 493 'value_var': value_var, | 623 'cpp_type': self._type_helper.GetCppType(type_), |
| 494 'name': prop.unix_name, | 624 'src_var': src_var, |
| 495 'dst': dst, | 625 'dst_var': dst_var, |
| 496 'failure_value': failure_value, | 626 'failure_value': failure_value, |
| 497 } | 627 } |
| 498 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY): | 628 |
| 499 sub['ctype'] = self._cpp_type_generator.GetType(prop) | 629 if underlying_type.property_type not in (PropertyType.ANY, |
| 500 sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop) | 630 PropertyType.CHOICES): |
|
Yoyo Zhou
2013/01/15 01:49:25
nit: indent
not at google - send to devlin
2013/01/15 21:47:27
Done.
| |
| 501 sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator | 631 sub['value_type'] = cpp_util.GetValueType(underlying_type) |
| 502 .GetReferencedProperty(prop).type_) | 632 |
| 503 c.Substitute(sub) | 633 return c.Eblock('}').Substitute(sub) |
| 504 return c | 634 |
| 505 | 635 def _GenerateListValueToEnumArrayConversion(self, |
| 506 def _GenerateFundamentalOrFundamentalRefPopulate(self, | 636 item_type, |
| 507 c, | 637 src_var, |
| 508 prop, | 638 dst_var, |
| 509 value_var, | 639 failure_value, |
| 510 dst): | 640 is_optional=False): |
| 511 if prop.optional: | 641 """Returns Code that converts a ListValue of string constants from |
| 512 (c.Append('%(ctype)s temp;') | 642 |src_var| into an array of enums of |type_| in |dst_var|. On failure, |
| 513 .Append('if (!%s)' % | 643 returns |failure_value|. |
| 514 cpp_util.GetAsFundamentalValue( | 644 """ |
| 515 self._cpp_type_generator.GetReferencedProperty(prop), | 645 c = Code() |
| 516 value_var, | 646 accessor = '.' |
| 517 '&temp')) | 647 if is_optional: |
| 518 .Append(' return %(failure_value)s;') | 648 accessor = '->' |
| 519 ) | 649 c.Append('%s.reset(new std::vector<%s>);' % ( |
| 520 if prop.type_ != prop.compiled_type: | 650 dst_var, |
| 521 (c.Append('%(compiled_ctype)s temp2;') | 651 self._type_helper.GetCppType(item_type, |
| 522 .Append('if (!%s)' % | 652 is_in_container=True))) |
| 523 cpp_util.GenerateTypeToCompiledTypeConversion( | 653 (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); ' |
| 524 self._cpp_type_generator.GetReferencedProperty(prop), | 654 'it != %s->end(); ++it) {' % (src_var, src_var)) |
| 525 'temp', | 655 .Append('%s tmp;' % self._type_helper.GetCppType(item_type)) |
| 526 'temp2')) | 656 .Concat(self._GenerateStringToEnumConversion(item_type, |
| 527 .Append(' return %(failure_value)s;') | 657 '(*it)', |
| 528 .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));') | 658 'tmp', |
| 529 ) | 659 failure_value)) |
| 530 else: | 660 .Append('%s%spush_back(tmp);' % (dst_var, accessor)) |
| 531 c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));') | |
| 532 | |
| 533 else: | |
| 534 if prop.type_ == prop.compiled_type: | |
| 535 assignment_target = '&%s->%s' % (dst, prop.unix_name) | |
| 536 else: | |
| 537 c.Append('%(ctype)s temp;') | |
| 538 assignment_target = '&temp' | |
| 539 (c.Append('if (!%s)' % | |
| 540 cpp_util.GetAsFundamentalValue( | |
| 541 self._cpp_type_generator.GetReferencedProperty(prop), | |
| 542 value_var, | |
| 543 assignment_target)) | |
| 544 .Append(' return %(failure_value)s;') | |
| 545 ) | |
| 546 if prop.type_ != prop.compiled_type: | |
| 547 (c.Append('if (!%s)' % | |
| 548 cpp_util.GenerateTypeToCompiledTypeConversion( | |
| 549 self._cpp_type_generator.GetReferencedProperty(prop), | |
| 550 'temp', | |
| 551 '%s->%s' % (dst, prop.unix_name))) | |
| 552 .Append(' return %(failure_value)s;') | |
| 553 ) | |
| 554 | |
| 555 def _GenerateObjectOrObjectRefPopulate(self, c, prop): | |
| 556 if prop.optional: | |
| 557 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 558 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
| 559 .Append(' return %(failure_value)s;') | |
| 560 .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());') | |
| 561 .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))') | |
| 562 .Append(' return %(failure_value)s;') | |
| 563 .Append('%(dst)s->%(name)s = temp.Pass();') | |
| 564 ) | |
| 565 else: | |
| 566 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 567 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
| 568 .Append(' return %(failure_value)s;') | |
| 569 .Append( | |
| 570 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') | |
| 571 .Append(' return %(failure_value)s;') | |
| 572 ) | |
| 573 | |
| 574 def _GenerateFunctionPopulate(self, c, prop): | |
| 575 if prop.optional: | |
| 576 c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());') | |
| 577 | |
| 578 def _GenerateAnyPopulate(self, c, prop, value_var, dst): | |
| 579 if prop.optional: | |
| 580 c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());') | |
| 581 c.Append(self._any_helper.Init(prop, value_var, dst) + ';') | |
| 582 | |
| 583 def _GenerateArrayOrArrayRefPopulate(self, c, prop, dst): | |
| 584 # util_cc_helper deals with optional and required arrays | |
| 585 (c.Append('const base::ListValue* list = NULL;') | |
| 586 .Append('if (!%(value_var)s->GetAsList(&list))') | |
| 587 .Append(' return %(failure_value)s;')) | |
| 588 if prop.item_type.type_ == PropertyType.ENUM: | |
| 589 self._GenerateListValueToEnumArrayConversion(c, prop) | |
| 590 else: | |
| 591 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | |
| 592 self._cpp_type_generator.GetReferencedProperty(prop), 'list', | |
| 593 dst + '->' + prop.unix_name, prop.optional)) | |
| 594 .Append(' return %(failure_value)s;') | |
| 595 ) | |
| 596 | |
| 597 def _GenerateChoicePopulate(self, c, prop, value_var, dst, failure_value): | |
| 598 type_var = '%(dst)s->%(name)s_type' | |
| 599 c.Sblock('switch (%(value_var)s->GetType()) {') | |
| 600 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
| 601 (c.Sblock('case %s: {' % cpp_util.GetValueType( | |
| 602 self._cpp_type_generator.GetReferencedProperty(choice).type_)) | |
| 603 .Concat(self._GeneratePopulatePropertyFromValue( | |
| 604 choice, value_var, dst, failure_value, check_type=False)) | |
| 605 .Append('%s = %s;' % | |
| 606 (type_var, | |
| 607 self._cpp_type_generator.GetEnumValue( | |
| 608 prop, choice.type_.name))) | |
| 609 .Append('break;') | |
| 610 .Eblock('}') | 661 .Eblock('}') |
| 611 ) | 662 ) |
| 612 (c.Append('default:') | 663 return c |
| 613 .Append(' return %(failure_value)s;') | 664 |
| 614 ) | 665 def _GenerateStringToEnumConversion(self, |
| 615 c.Eblock('}') | 666 type_, |
| 616 | 667 src_var, |
| 617 def _GenerateEnumPopulate(self, c, prop, value_var): | 668 dst_var, |
| 618 c.Sblock('{') | 669 failure_value): |
| 619 self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp') | 670 """Returns Code that converts a string type in |src_var| to an enum with |
| 620 c.Append('%(dst)s->%(name)s = enum_temp;') | 671 type |type_| in |dst_var|. On failure, returns |failure_value|. |
|
Yoyo Zhou
2013/01/15 01:49:25
"on failure" should be a subordinate clause, other
not at google - send to devlin
2013/01/15 21:47:27
Done.
| |
| 621 c.Eblock('}') | 672 """ |
| 622 | 673 c = Code() |
| 623 def _GenerateBinaryPopulate(self, c, prop): | 674 enum_as_string = '%s_as_string' % type_.unix_name |
| 624 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') | 675 (c.Append('std::string %s;' % enum_as_string) |
| 625 .Append(' return %(failure_value)s;') | 676 .Append('if (!%s->GetAsString(&%s))' % (src_var, enum_as_string)) |
| 626 .Append('const base::BinaryValue* binary_value =') | 677 .Append(' return %s;' % failure_value) |
| 627 .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);') | 678 .Append('%s = Parse%s(%s);' % (dst_var, |
| 628 ) | 679 self._type_helper.GetCppType(type_), |
| 629 if prop.optional: | 680 enum_as_string)) |
| 630 (c.Append('%(dst)s->%(name)s.reset(') | 681 .Append('if (%s == %s)' % (dst_var, |
| 631 .Append(' new std::string(binary_value->GetBuffer(),') | 682 self._type_helper.GetEnumNoneValue(type_))) |
| 632 .Append(' binary_value->GetSize()));') | 683 .Append(' return %s;' % failure_value) |
| 633 ) | 684 ) |
| 634 else: | 685 return c |
| 635 (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),') | 686 |
| 636 .Append(' binary_value->GetSize());') | 687 def _GeneratePropertyFunctions(self, namespace, params): |
| 637 ) | 688 """Generates the member functions for a list of parameters. |
| 638 | 689 """ |
| 639 def _GenerateListValueToEnumArrayConversion(self, c, prop): | 690 return self._GenerateTypes(namespace, (param.type_ for param in params)) |
| 640 """Appends code that converts a ListValue of string contstants to | 691 |
| 641 an array of enums in dst. | 692 def _GenerateTypes(self, namespace, types): |
| 642 Leaves dst, name, and failure_value unsubstituted. | 693 """Generates the member functions for a list of types. |
| 643 | 694 """ |
| 644 c: the Code object that is being appended to. | 695 c = Code() |
| 645 prop: the property that the code is populating. | 696 for type_ in types: |
| 646 """ | 697 c.Cblock(self._GenerateType(namespace, type_)) |
| 647 accessor = '.' | 698 return c |
| 648 if prop.optional: | 699 |
| 649 c.Append('%(dst)s->%(name)s.reset(new std::vector<' + ( | 700 def _GenerateEnumToString(self, cpp_namespace, type_): |
| 650 self._cpp_type_generator.GetType(prop.item_type) + '>);')) | |
| 651 accessor = '->' | |
| 652 c.Sblock('for (ListValue::const_iterator it = list->begin(); ' | |
| 653 'it != list->end(); ++it) {') | |
| 654 self._GenerateStringToEnumConversion( | |
| 655 c, prop.item_type, '(*it)', 'enum_temp') | |
| 656 c.Append('%(dst)s->%(name)s' + accessor + 'push_back(enum_temp);') | |
| 657 c.Eblock('}') | |
| 658 | |
| 659 def _GenerateStringToEnumConversion(self, c, prop, value_var, enum_temp): | |
| 660 """Appends code that converts a string to an enum. | |
| 661 Leaves failure_value unsubstituted. | |
| 662 | |
| 663 c: the code that is appended to. | |
| 664 prop: the property that the code is populating. | |
| 665 value_var: the string value that is being converted. | |
| 666 enum_temp: the name used to store the temporary enum value. | |
| 667 """ | |
| 668 (c.Append('std::string enum_as_string;') | |
| 669 .Append('if (!%s->GetAsString(&enum_as_string))' % value_var) | |
| 670 .Append(' return %(failure_value)s;') | |
| 671 .Append('%(type)s %(enum)s = From%(type)sString(enum_as_string);' % { | |
| 672 'type': self._cpp_type_generator.GetCompiledType(prop), | |
| 673 'enum': enum_temp | |
| 674 }) | |
| 675 .Append('if (%s == %s)' % | |
| 676 (enum_temp, self._cpp_type_generator.GetEnumNoneValue(prop))) | |
| 677 .Append(' return %(failure_value)s;')) | |
| 678 | |
| 679 def _GeneratePropertyFunctions(self, param_namespace, params): | |
| 680 """Generate the functions for structures generated by a property such as | |
| 681 CreateEnumValue for ENUMs and Populate/ToValue for Params/Results objects. | |
| 682 """ | |
| 683 c = Code() | |
| 684 for param in params: | |
| 685 if param.type_ == PropertyType.OBJECT: | |
| 686 c.Concat(self._GenerateType( | |
| 687 param_namespace + '::' + cpp_util.Classname(param.name), | |
| 688 param)) | |
| 689 c.Append() | |
| 690 elif param.type_ == PropertyType.ARRAY: | |
| 691 c.Concat(self._GeneratePropertyFunctions( | |
| 692 param_namespace, [param.item_type])) | |
| 693 elif param.type_ == PropertyType.CHOICES: | |
| 694 c.Concat(self._GeneratePropertyFunctions( | |
| 695 param_namespace, param.choices.values())) | |
| 696 if param.from_client: | |
| 697 c.Concat(self._GenerateGetChoiceValue(param_namespace, param)) | |
| 698 elif param.type_ == PropertyType.ENUM: | |
| 699 (c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) | |
| 700 .Append() | |
| 701 .Concat(self._GenerateEnumFromString(param_namespace, | |
| 702 param, | |
| 703 use_namespace=True)) | |
| 704 .Append() | |
| 705 .Concat(self._GenerateEnumToString(param_namespace, | |
| 706 param, | |
| 707 use_namespace=True)) | |
| 708 .Append()) | |
| 709 return c | |
| 710 | |
| 711 def _GenerateGetChoiceValue(self, cpp_namespace, prop): | |
| 712 """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value> | |
| 713 representing the choice value. | |
| 714 """ | |
| 715 c = Code() | |
| 716 (c.Sblock('scoped_ptr<base::Value> ' | |
| 717 '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {') | |
| 718 .Sblock('switch (%s_type) {' % prop.unix_name) | |
| 719 .Concat(self._GenerateReturnCase( | |
| 720 self._cpp_type_generator.GetEnumNoneValue(prop), | |
| 721 'scoped_ptr<base::Value>()'))) | |
| 722 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
| 723 c.Concat(self._GenerateReturnCase( | |
| 724 self._cpp_type_generator.GetEnumValue(prop, choice.type_.name), | |
| 725 'make_scoped_ptr<base::Value>(%s)' % | |
| 726 self._CreateValueFromProperty(choice, choice.unix_name))) | |
| 727 (c.Eblock('}') | |
| 728 .Append('return scoped_ptr<base::Value>();') | |
| 729 .Eblock('}') | |
| 730 .Append() | |
| 731 .Substitute({ | |
| 732 'cpp_namespace': cpp_namespace, | |
| 733 'choice': cpp_util.Classname(prop.name) | |
| 734 }) | |
| 735 ) | |
| 736 return c | |
| 737 | |
| 738 def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop): | |
| 739 """Generates CreateEnumValue() that returns the base::StringValue | |
| 740 representation of an enum type. | |
| 741 """ | |
| 742 c = Code() | |
| 743 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | |
| 744 (c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' % | |
| 745 (classname, classname.lower())) | |
| 746 .Append('std::string enum_temp = ToString(%s);' % classname.lower()) | |
| 747 .Append('if (enum_temp.empty())') | |
| 748 .Append(' return scoped_ptr<base::Value>();') | |
| 749 .Append('return scoped_ptr<base::Value>(' | |
| 750 'base::Value::CreateStringValue(enum_temp));') | |
| 751 .Eblock('}')) | |
| 752 return c | |
| 753 | |
| 754 def _GenerateEnumToString(self, cpp_namespace, prop, use_namespace=False): | |
| 755 """Generates ToString() which gets the string representation of an enum. | 701 """Generates ToString() which gets the string representation of an enum. |
| 756 """ | 702 """ |
| 757 c = Code() | 703 c = Code() |
| 758 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 704 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 759 if use_namespace: | 705 |
| 760 namespace = '%s::' % cpp_namespace | 706 if cpp_namespace is not None: |
| 761 else: | 707 c.Append('// static') |
| 762 namespace = '' | 708 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
| 763 | 709 |
| 764 (c.Append('// static') | 710 c.Sblock('std::string %sToString(%s enum_param) {' % |
| 765 .Sblock('std::string %(namespace)sToString(%(class)s enum_param) {')) | 711 (maybe_namespace, classname)) |
| 766 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
| 767 c.Sblock('switch (enum_param) {') | 712 c.Sblock('switch (enum_param) {') |
| 768 for enum_value in enum_prop.enum_values: | 713 for enum_value in self._type_helper.FollowRef(type_).enum_values: |
| 769 c.Concat(self._GenerateReturnCase( | 714 (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value)) |
| 770 self._cpp_type_generator.GetEnumValue(prop, enum_value), | 715 .Append(' return "%s";' % enum_value)) |
| 771 '"%s"' % enum_value)) | 716 (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_)) |
| 772 (c.Append('case %s:' % self._cpp_type_generator.GetEnumNoneValue(prop)) | |
| 773 .Append(' return "";') | 717 .Append(' return "";') |
| 774 .Eblock('}') | 718 .Eblock('}') |
| 719 .Append('NOTREACHED();') | |
| 775 .Append('return "";') | 720 .Append('return "";') |
| 776 .Eblock('}') | 721 .Eblock('}') |
| 777 .Substitute({ | 722 ) |
| 778 'namespace': namespace, | 723 return c |
| 779 'class': classname | 724 |
| 780 })) | 725 def _GenerateEnumFromString(self, cpp_namespace, type_): |
| 781 return c | |
| 782 | |
| 783 def _GenerateEnumFromString(self, cpp_namespace, prop, use_namespace=False): | |
| 784 """Generates FromClassNameString() which gets an enum from its string | 726 """Generates FromClassNameString() which gets an enum from its string |
| 785 representation. | 727 representation. |
| 786 """ | 728 """ |
| 787 c = Code() | 729 c = Code() |
| 788 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 730 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 789 if use_namespace: | 731 |
| 790 namespace = '%s::' % cpp_namespace | 732 if cpp_namespace is not None: |
| 791 else: | 733 c.Append('// static') |
| 792 namespace = '' | 734 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
| 793 | 735 |
| 794 (c.Append('// static') | 736 c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' % |
| 795 .Sblock('%(namespace)s%(class)s' | 737 (maybe_namespace, classname, maybe_namespace, classname)) |
| 796 ' %(namespace)sFrom%(class)sString(' | |
| 797 'const std::string& enum_string) {')) | |
| 798 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
| 799 for i, enum_value in enumerate( | 738 for i, enum_value in enumerate( |
| 800 self._cpp_type_generator.GetReferencedProperty(prop).enum_values): | 739 self._type_helper.FollowRef(type_).enum_values): |
| 801 # This is broken up into all ifs with no else ifs because we get | 740 # This is broken up into all ifs with no else ifs because we get |
| 802 # "fatal error C1061: compiler limit : blocks nested too deeply" | 741 # "fatal error C1061: compiler limit : blocks nested too deeply" |
| 803 # on Windows. | 742 # on Windows. |
| 804 (c.Append('if (enum_string == "%s")' % enum_value) | 743 (c.Append('if (enum_string == "%s")' % enum_value) |
| 805 .Append(' return %s;' % | 744 .Append(' return %s;' % |
| 806 self._cpp_type_generator.GetEnumValue(prop, enum_value))) | 745 self._type_helper.GetEnumValue(type_, enum_value))) |
| 807 (c.Append('return %s;' % | 746 (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_)) |
| 808 self._cpp_type_generator.GetEnumNoneValue(prop)) | |
| 809 .Eblock('}') | 747 .Eblock('}') |
| 810 .Substitute({ | 748 ) |
| 811 'namespace': namespace, | 749 return c |
| 812 'class': classname | 750 |
| 813 })) | 751 def _GenerateCreateCallbackArguments(self, function_scope, callback): |
| 814 return c | |
| 815 | |
| 816 # TODO(chebert): This is basically the same as GenerateCreateEnumTypeValue(). | |
| 817 # The plan is to phase out the old-style enums, and make all enums into REF | |
| 818 # types. | |
| 819 def _GenerateCreateEnumValue(self, cpp_namespace, prop): | |
| 820 """Generates CreateEnumValue() that returns the base::StringValue | |
| 821 representation of an enum. | |
| 822 """ | |
| 823 c = Code() | |
| 824 (c.Append('// static') | |
| 825 .Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' | |
| 826 '%(arg)s) {') | |
| 827 .Append('std::string enum_temp = ToString(%s);' % prop.unix_name) | |
| 828 .Append('if (enum_temp.empty())') | |
| 829 .Append(' return scoped_ptr<base::Value>();') | |
| 830 .Append('return scoped_ptr<base::Value>(' | |
| 831 'base::Value::CreateStringValue(enum_temp));') | |
| 832 .Eblock('}') | |
| 833 .Substitute({ | |
| 834 'cpp_namespace': cpp_namespace, | |
| 835 'arg': cpp_util.GetParameterDeclaration( | |
| 836 prop, self._cpp_type_generator.GetType(prop)) | |
| 837 })) | |
| 838 return c | |
| 839 | |
| 840 def _GenerateReturnCase(self, case_value, return_value): | |
| 841 """Generates a single return case for a switch block. | |
| 842 """ | |
| 843 c = Code() | |
| 844 (c.Append('case %s:' % case_value) | |
| 845 .Append(' return %s;' % return_value) | |
| 846 ) | |
| 847 return c | |
| 848 | |
| 849 def _GenerateCreateCallbackArguments(self, | |
| 850 function_scope, | |
| 851 callback, | |
| 852 generate_to_json=False): | |
| 853 """Generate all functions to create Value parameters for a callback. | 752 """Generate all functions to create Value parameters for a callback. |
| 854 | 753 |
| 855 E.g for function "Bar", generate Bar::Results::Create | 754 E.g for function "Bar", generate Bar::Results::Create |
| 856 E.g for event "Baz", generate Baz::Create | 755 E.g for event "Baz", generate Baz::Create |
| 857 | 756 |
| 858 function_scope: the function scope path, e.g. Foo::Bar for the function | 757 function_scope: the function scope path, e.g. Foo::Bar for the function |
| 859 Foo::Bar::Baz(). | 758 Foo::Bar::Baz(). May be None if there is no function scope. |
| 860 callback: the Function object we are creating callback arguments for. | 759 callback: the Function object we are creating callback arguments for. |
| 861 generate_to_json: Generate a ToJson method. | |
| 862 """ | 760 """ |
| 863 c = Code() | 761 c = Code() |
| 864 params = callback.params | 762 params = callback.params |
| 865 expanded_params = self._cpp_type_generator.ExpandParams(params) | 763 c.Concat(self._GeneratePropertyFunctions(function_scope, params)) |
| 866 c.Concat(self._GeneratePropertyFunctions(function_scope, expanded_params)) | 764 |
| 867 | 765 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' |
| 868 param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params) | 766 'Create(%(declaration_list)s) {') |
| 869 for param_list in param_lists: | 767 .Append('scoped_ptr<base::ListValue> create_results(' |
| 870 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::' | 768 'new base::ListValue());') |
| 871 'Create(%(declaration_list)s) {') | 769 ) |
| 872 .Append('scoped_ptr<base::ListValue> create_results(' | 770 declaration_list = [] |
| 873 'new base::ListValue());') | 771 for param in params: |
| 874 ) | 772 declaration_list.append(cpp_util.GetParameterDeclaration( |
| 875 declaration_list = [] | 773 param, self._type_helper.GetCppType(param.type_))) |
| 876 for param in param_list: | 774 c.Append('create_results->Append(%s);' % |
| 877 # We treat this argument as 'required' to avoid wrapping it in a | 775 self._CreateValueFromType(param.type_, param.unix_name)) |
| 878 # scoped_ptr if it's optional. | 776 c.Append('return create_results.Pass();') |
| 879 param_copy = param.Copy() | 777 c.Eblock('}') |
| 880 param_copy.optional = False | 778 c.Substitute({ |
| 881 declaration_list.append("const %s" % cpp_util.GetParameterDeclaration( | 779 'function_scope': ('%s::' % function_scope) if function_scope else '', |
| 882 param_copy, self._cpp_type_generator.GetCompiledType(param_copy))) | 780 'declaration_list': ', '.join(declaration_list), |
| 883 param_name = param_copy.unix_name | 781 'param_names': ', '.join(param.unix_name for param in params) |
| 884 if param_copy.type_ != param_copy.compiled_type: | 782 }) |
| 885 param_name = 'temp_' + param_name | |
| 886 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(param_copy), | |
| 887 param_name)) | |
| 888 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | |
| 889 param_copy, | |
| 890 param_copy.unix_name, | |
| 891 param_name) + ';') | |
| 892 ) | |
| 893 c.Append('create_results->Append(%s);' % | |
| 894 self._CreateValueFromProperty(param_copy, param_name)) | |
| 895 | |
| 896 c.Append('return create_results.Pass();') | |
| 897 c.Eblock('}') | |
| 898 if generate_to_json: | |
| 899 c.Append() | |
| 900 (c.Sblock('std::string %(function_scope)s::' | |
| 901 'ToJson(%(declaration_list)s) {') | |
| 902 .Append('scoped_ptr<base::ListValue> create_results = ' | |
| 903 '%(function_scope)s::Create(%(param_list)s);') | |
| 904 .Append('std::string json;') | |
| 905 .Append('base::JSONWriter::Write(create_results.get(), &json);') | |
| 906 .Append('return json;') | |
| 907 ) | |
| 908 c.Eblock('}') | |
| 909 | |
| 910 c.Substitute({ | |
| 911 'function_scope': function_scope, | |
| 912 'declaration_list': ', '.join(declaration_list), | |
| 913 'param_list': ', '.join(param.unix_name for param in param_list) | |
| 914 }) | |
| 915 | |
| 916 return c | 783 return c |
| 917 | 784 |
| 918 def _InitializePropertyToDefault(self, prop, dst): | 785 def _InitializePropertyToDefault(self, prop, dst): |
| 919 """Initialize a model.Property to its default value inside an object. | 786 """Initialize a model.Property to its default value inside an object. |
| 920 | 787 |
| 921 E.g for optional enum "state", generate dst->state = STATE_NONE; | 788 E.g for optional enum "state", generate dst->state = STATE_NONE; |
| 922 | 789 |
| 923 dst: Type* | 790 dst: Type* |
| 924 """ | 791 """ |
| 925 c = Code() | 792 c = Code() |
| 926 if (self._cpp_type_generator.IsEnumOrEnumRef(prop) or | 793 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 927 prop.type_ == PropertyType.CHOICES): | 794 if (underlying_type.property_type == PropertyType.ENUM and |
| 928 if prop.optional: | 795 prop.optional): |
| 929 prop_name = prop.unix_name | 796 c.Append('%s->%s = %s;' % ( |
| 930 if prop.type_ == PropertyType.CHOICES: | 797 dst, |
| 931 prop_name = prop.unix_name + '_type' | 798 prop.unix_name, |
| 932 c.Append('%s->%s = %s;' % ( | 799 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 933 dst, | |
| 934 prop_name, | |
| 935 self._cpp_type_generator.GetEnumNoneValue(prop))) | |
| 936 return c | 800 return c |
| 937 | |
| 938 def _IsObjectOrObjectRef(self, prop): | |
| 939 """Determines if this property is an Object or is a ref to an Object. | |
| 940 """ | |
| 941 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
| 942 PropertyType.OBJECT) | |
| 943 | |
| 944 def _IsArrayOrArrayRef(self, prop): | |
| 945 """Determines if this property is an Array or is a ref to an Array. | |
| 946 """ | |
| 947 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
| 948 PropertyType.ARRAY) | |
| 949 | |
| 950 def _IsFundamentalOrFundamentalRef(self, prop): | |
| 951 """Determines if this property is a Fundamental type or is a ref to a | |
| 952 Fundamental type. | |
| 953 """ | |
| 954 return (self._cpp_type_generator.GetReferencedProperty(prop).type_. | |
| 955 is_fundamental) | |
| OLD | NEW |