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 |