Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: tools/json_schema_compiler/cc_generator.py

Issue 9491002: json_schema_compiler: any, additionalProperties, functions on types (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: add any in arrays to util.h Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/json_schema_compiler/api_gen_util.gyp ('k') | tools/json_schema_compiler/code.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 model import PropertyType 5 from model import PropertyType
6 import any_helper
6 import code 7 import code
7 import cpp_util 8 import cpp_util
9 import model
8 import util_cc_helper 10 import util_cc_helper
9 11
10 class CCGenerator(object): 12 class CCGenerator(object):
11 """A .cc generator for a namespace. 13 """A .cc generator for a namespace.
12 """ 14 """
13 def __init__(self, namespace, cpp_type_generator): 15 def __init__(self, namespace, cpp_type_generator):
14 self._cpp_type_generator = cpp_type_generator 16 self._cpp_type_generator = cpp_type_generator
15 self._namespace = namespace 17 self._namespace = namespace
16 self._target_namespace = ( 18 self._target_namespace = (
17 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) 19 self._cpp_type_generator.GetCppNamespaceName(self._namespace))
18 self._util_cc_helper = ( 20 self._util_cc_helper = (
19 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) 21 util_cc_helper.UtilCCHelper(self._cpp_type_generator))
22 self._any_helper = any_helper.AnyHelper()
20 23
21 def Generate(self): 24 def Generate(self):
22 """Generates a code.Code object with the .cc for a single namespace. 25 """Generates a code.Code object with the .cc for a single namespace.
23 """ 26 """
24 c = code.Code() 27 c = code.Code()
25 (c.Append(cpp_util.CHROMIUM_LICENSE) 28 (c.Append(cpp_util.CHROMIUM_LICENSE)
26 .Append() 29 .Append()
27 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) 30 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
28 .Append() 31 .Append()
29 .Append(self._util_cc_helper.GetIncludePath()) 32 .Append(self._util_cc_helper.GetIncludePath())
30 .Append('#include "%s/%s.h"' % 33 .Append('#include "%s/%s.h"' %
31 (self._namespace.source_file_dir, self._namespace.name)) 34 (self._namespace.source_file_dir, self._namespace.name))
32 ) 35 )
33 includes = self._cpp_type_generator.GenerateIncludes() 36 includes = self._cpp_type_generator.GenerateIncludes()
34 if not includes.IsEmpty(): 37 if not includes.IsEmpty():
35 (c.Concat(includes) 38 (c.Concat(includes)
36 .Append() 39 .Append()
37 ) 40 )
38 41
39 (c.Append() 42 (c.Append()
40 .Append('using base::Value;') 43 .Append('using base::Value;')
41 .Append('using base::DictionaryValue;') 44 .Append('using base::DictionaryValue;')
42 .Append('using base::ListValue;') 45 .Append('using base::ListValue;')
46 .Append('using %s;' % any_helper.ANY_CLASS)
43 .Append() 47 .Append()
44 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) 48 .Concat(self._cpp_type_generator.GetRootNamespaceStart())
45 .Concat(self._cpp_type_generator.GetNamespaceStart()) 49 .Concat(self._cpp_type_generator.GetNamespaceStart())
46 .Append() 50 .Append()
47 ) 51 )
48 if self._namespace.types: 52 if self._namespace.types:
49 (c.Append('//') 53 (c.Append('//')
50 .Append('// Types') 54 .Append('// Types')
51 .Append('//') 55 .Append('//')
52 .Append() 56 .Append()
53 ) 57 )
54 for type_ in self._namespace.types.values(): 58 for type_ in self._namespace.types.values():
55 (c.Concat(self._GenerateType(type_.name, type_)) 59 (c.Concat(self._GenerateType(type_.name, type_))
56 .Append() 60 .Append()
57 ) 61 )
58 if self._namespace.functions: 62 if self._namespace.functions:
59 (c.Append('//') 63 (c.Append('//')
60 .Append('// Functions') 64 .Append('// Functions')
61 .Append('//') 65 .Append('//')
62 .Append() 66 .Append()
63 ) 67 )
64 for function in self._namespace.functions.values(): 68 for function in self._namespace.functions.values():
65 (c.Concat(self._GenerateFunction(function)) 69 (c.Concat(self._GenerateFunction(
70 cpp_util.Classname(function.name), function))
66 .Append() 71 .Append()
67 ) 72 )
68 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) 73 (c.Concat(self._cpp_type_generator.GetNamespaceEnd())
69 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) 74 .Concat(self._cpp_type_generator.GetRootNamespaceEnd())
70 .Append() 75 .Append()
71 ) 76 )
72 # TODO(calamity): Events 77 # TODO(calamity): Events
73 return c 78 return c
74 79
75 def _GenerateType(self, cpp_namespace, type_): 80 def _GenerateType(self, cpp_namespace, type_):
76 """Generates the function definitions for a type. 81 """Generates the function definitions for a type.
77 """ 82 """
78 classname = cpp_util.Classname(type_.name) 83 classname = cpp_util.Classname(type_.name)
79 c = code.Code() 84 c = code.Code()
80 85
81 (c.Concat(self._GeneratePropertyFunctions( 86 if type_.functions:
82 cpp_namespace, type_.properties.values())) 87 # Types with functions are not instantiable in C++ because they are
83 .Append('%(namespace)s::%(classname)s() {}') 88 # handled in pure Javascript and hence have no properties or
84 .Append('%(namespace)s::~%(classname)s() {}') 89 # additionalProperties.
85 .Append() 90 if type_.properties:
86 ) 91 raise NotImplementedError('\n'.join(model.GetModelHierarchy(type_)) +
87 if type_.from_json: 92 '\nCannot generate both functions and properties on a type')
88 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) 93 for function in type_.functions.values():
94 (c.Concat(
95 self._GenerateFunction(
96 cpp_namespace + '::' + cpp_util.Classname(function.name),
97 function))
98 .Append()
99 )
100 else:
101 (c.Concat(self._GeneratePropertyFunctions(
102 cpp_namespace, type_.properties.values()))
103 .Append('%(namespace)s::%(classname)s() {}')
104 .Append('%(namespace)s::~%(classname)s() {}')
89 .Append() 105 .Append()
90 ) 106 )
91 if type_.from_client: 107 if type_.from_json:
92 c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) 108 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
93 c.Append() 109 .Append()
110 )
111 if type_.from_client:
112 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
113 .Append()
114 )
94 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) 115 c.Substitute({'classname': classname, 'namespace': cpp_namespace})
95 116
96 return c 117 return c
97 118
98 def _GenerateTypePopulate(self, cpp_namespace, type_): 119 def _GenerateTypePopulate(self, cpp_namespace, type_):
99 """Generates the function for populating a type given a pointer to it. 120 """Generates the function for populating a type given a pointer to it.
121
122 E.g for type "Foo", generates Foo::Populate()
100 """ 123 """
101 classname = cpp_util.Classname(type_.name) 124 classname = cpp_util.Classname(type_.name)
102 c = code.Code() 125 c = code.Code()
103 (c.Append('// static') 126 (c.Append('// static')
104 .Sblock('bool %(namespace)s::Populate' 127 .Sblock('bool %(namespace)s::Populate'
105 '(const Value& value, %(name)s* out) {') 128 '(const Value& value, %(name)s* out) {')
106 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') 129 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))')
107 .Append(' return false;') 130 .Append(' return false;')
108 .Append('const DictionaryValue* dict = ' 131 .Append('const DictionaryValue* dict = '
109 'static_cast<const DictionaryValue*>(&value);') 132 'static_cast<const DictionaryValue*>(&value);')
110 .Append() 133 .Append()
111 ) 134 )
112 for prop in type_.properties.values(): 135 for prop in type_.properties.values():
113 c.Concat(self._InitializePropertyToDefault(prop, 'out')) 136 c.Concat(self._InitializePropertyToDefault(prop, 'out'))
114 for prop in type_.properties.values(): 137 for prop in type_.properties.values():
115 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) 138 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
139 c.Append('out->additional_properties.MergeDictionary(dict);')
140 # remove all keys that are actual properties
141 for cur_prop in type_.properties.values():
142 if prop != cur_prop:
143 c.Append('out->additional_properties'
144 '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name)
145 c.Append()
146 else:
147 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
116 (c.Append('return true;') 148 (c.Append('return true;')
117 .Eblock('}') 149 .Eblock('}')
118 ) 150 )
119 c.Substitute({'namespace': cpp_namespace, 'name': classname}) 151 c.Substitute({'namespace': cpp_namespace, 'name': classname})
120 return c 152 return c
121 153
122 def _GenerateTypePopulateProperty(self, prop, src, dst): 154 def _GenerateTypePopulateProperty(self, prop, src, dst):
123 """Generate the code to populate a single property in a type. 155 """Generate the code to populate a single property in a type.
124 156
125 src: DictionaryValue* 157 src: DictionaryValue*
(...skipping 16 matching lines...) Expand all
142 .Append(' return false;') 174 .Append(' return false;')
143 .Concat(self._GeneratePopulatePropertyFromValue( 175 .Concat(self._GeneratePopulatePropertyFromValue(
144 prop, value_var, dst, 'false')) 176 prop, value_var, dst, 'false'))
145 ) 177 )
146 c.Append() 178 c.Append()
147 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src}) 179 c.Substitute({'value_var': value_var, 'key': prop.name, 'src': src})
148 return c 180 return c
149 181
150 def _GenerateTypeToValue(self, cpp_namespace, type_): 182 def _GenerateTypeToValue(self, cpp_namespace, type_):
151 """Generates a function that serializes the type into a |DictionaryValue|. 183 """Generates a function that serializes the type into a |DictionaryValue|.
184
185 E.g. for type "Foo" generates Foo::ToValue()
152 """ 186 """
153 c = code.Code() 187 c = code.Code()
154 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % 188 (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' %
155 cpp_namespace) 189 cpp_namespace)
156 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') 190 .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());')
157 .Append() 191 .Append()
158 ) 192 )
159 for prop in type_.properties.values(): 193 for prop in type_.properties.values():
160 if prop.optional: 194 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
161 if prop.type_ == PropertyType.ENUM: 195 c.Append('value->MergeDictionary(&%s);' % prop.unix_name)
162 c.Sblock('if (%s != %s)' % 196 else:
163 (prop.unix_name, self._cpp_type_generator.GetEnumNoneValue(prop))) 197 if prop.optional:
164 else: 198 if prop.type_ == PropertyType.ENUM:
165 c.Sblock('if (%s.get())' % prop.unix_name) 199 c.Sblock('if (%s != %s)' %
166 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( 200 (prop.unix_name,
167 prop.name, 201 self._cpp_type_generator.GetEnumNoneValue(prop)))
168 self._CreateValueFromProperty(prop, prop.unix_name))) 202 else:
169 if prop.optional: 203 c.Sblock('if (%s.get())' % prop.unix_name)
170 c.Eblock(); 204 c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
205 prop.name,
206 self._CreateValueFromProperty(prop, prop.unix_name)))
207 if prop.optional:
208 c.Eblock();
171 (c.Append() 209 (c.Append()
172 .Append('return value.Pass();') 210 .Append('return value.Pass();')
173 .Eblock('}') 211 .Eblock('}')
174 ) 212 )
175 return c 213 return c
176 214
177 def _GenerateFunction(self, function): 215 def _GenerateFunction(self, cpp_namespace, function):
178 """Generates the definitions for function structs. 216 """Generates the definitions for function structs.
179 """ 217 """
180 classname = cpp_util.Classname(function.name)
181 c = code.Code() 218 c = code.Code()
182 219
183 # Params::Populate function 220 # Params::Populate function
184 if function.params: 221 if function.params:
185 c.Concat(self._GeneratePropertyFunctions(classname + '::Params', 222 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params',
186 function.params)) 223 function.params))
187 (c.Append('%(name)s::Params::Params() {}') 224 (c.Append('%(cpp_namespace)s::Params::Params() {}')
188 .Append('%(name)s::Params::~Params() {}') 225 .Append('%(cpp_namespace)s::Params::~Params() {}')
189 .Append() 226 .Append()
190 .Concat(self._GenerateFunctionParamsCreate(function)) 227 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function))
191 .Append() 228 .Append()
192 ) 229 )
193 230
194 # Result::Create function 231 # Result::Create function
195 if function.callback: 232 if function.callback:
196 c.Concat(self._GenerateFunctionResultCreate(function)) 233 c.Concat(self._GenerateFunctionResultCreate(cpp_namespace, function))
197 234
198 c.Substitute({'name': classname}) 235 c.Substitute({'cpp_namespace': cpp_namespace})
199 236
200 return c 237 return c
201 238
202 def _GenerateCreateEnumValue(self, cpp_namespace, prop): 239 def _GenerateCreateEnumValue(self, cpp_namespace, prop):
203 """Generates a function that returns the |StringValue| representation of an 240 """Generates CreateEnumValue() that returns the |StringValue|
204 enum. 241 representation of an enum.
205 """ 242 """
206 c = code.Code() 243 c = code.Code()
207 c.Append('// static') 244 c.Append('// static')
208 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') 245 c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {')
209 c.Sblock('switch (%s) {' % prop.unix_name) 246 c.Sblock('switch (%s) {' % prop.unix_name)
210 if prop.optional: 247 if prop.optional:
211 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) 248 (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop))
212 .Append(' return scoped_ptr<Value>();') 249 .Append(' return scoped_ptr<Value>();')
213 .Append('}') 250 .Append('}')
214 ) 251 )
(...skipping 11 matching lines...) Expand all
226 c.Eblock('}') 263 c.Eblock('}')
227 c.Eblock('}') 264 c.Eblock('}')
228 c.Substitute({ 265 c.Substitute({
229 'cpp_namespace': cpp_namespace, 266 'cpp_namespace': cpp_namespace,
230 'arg': cpp_util.GetParameterDeclaration( 267 'arg': cpp_util.GetParameterDeclaration(
231 prop, self._cpp_type_generator.GetType(prop)) 268 prop, self._cpp_type_generator.GetType(prop))
232 }) 269 })
233 return c 270 return c
234 271
235 def _CreateValueFromProperty(self, prop, var): 272 def _CreateValueFromProperty(self, prop, var):
236 """Creates a Value given a single property. Generated code passes ownership 273 """Creates a Value given a property. Generated code passes ownership
237 to caller. 274 to caller.
238 275
239 var: variable or variable* 276 var: variable or variable*
277
278 E.g for std::string, generate Value::CreateStringValue(var)
240 """ 279 """
241 if prop.type_ == PropertyType.CHOICES: 280 if prop.type_ == PropertyType.CHOICES:
242 # CHOICES conversion not implemented because it's not used. If needed, 281 # CHOICES conversion not implemented. If needed, write something to
243 # write something to generate a function that returns a scoped_ptr<Value> 282 # generate a function that returns a scoped_ptr<Value> and put it in
244 # and put it in _GeneratePropertyFunctions. 283 # _GeneratePropertyFunctions, then use it here. Look at CreateEnumValue()
284 # for reference.
245 raise NotImplementedError( 285 raise NotImplementedError(
246 'Conversion of CHOICES to Value not implemented') 286 'Conversion of CHOICES to Value not implemented')
247 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT): 287 if prop.type_ in (PropertyType.REF, PropertyType.OBJECT):
248 if prop.optional: 288 if prop.optional:
249 return '%s->ToValue().release()' % var 289 return '%s->ToValue().release()' % var
250 else: 290 else:
251 return '%s.ToValue().release()' % var 291 return '%s.ToValue().release()' % var
292 elif prop.type_ == PropertyType.ANY:
293 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var)
294 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES:
295 return '%s.DeepCopy()' % var
252 elif prop.type_ == PropertyType.ENUM: 296 elif prop.type_ == PropertyType.ENUM:
253 return 'CreateEnumValue(%s).release()' % var 297 return 'CreateEnumValue(%s).release()' % var
254 elif prop.type_ == PropertyType.ARRAY: 298 elif prop.type_ == PropertyType.ARRAY:
255 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( 299 return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
256 prop, var) 300 prop, var)
257 elif prop.type_.is_fundamental: 301 elif prop.type_.is_fundamental:
258 if prop.optional: 302 if prop.optional:
259 var = '*' + var 303 var = '*' + var
260 return { 304 return {
261 PropertyType.STRING: 'Value::CreateStringValue(%s)', 305 PropertyType.STRING: 'Value::CreateStringValue(%s)',
(...skipping 22 matching lines...) Expand all
284 c.Append('if (%(var)s.GetSize() < %(required)d' 328 c.Append('if (%(var)s.GetSize() < %(required)d'
285 ' || %(var)s.GetSize() > %(total)d)') 329 ' || %(var)s.GetSize() > %(total)d)')
286 c.Append(' return scoped_ptr<Params>();') 330 c.Append(' return scoped_ptr<Params>();')
287 c.Substitute({ 331 c.Substitute({
288 'var': var, 332 'var': var,
289 'required': num_required, 333 'required': num_required,
290 'total': len(function.params), 334 'total': len(function.params),
291 }) 335 })
292 return c 336 return c
293 337
294 def _GenerateFunctionParamsCreate(self, function): 338 def _GenerateFunctionParamsCreate(self, cpp_namespace, function):
295 """Generate function to create an instance of Params. The generated 339 """Generate function to create an instance of Params. The generated
296 function takes a ListValue of arguments. 340 function takes a ListValue of arguments.
341
342 E.g for function "Bar", generate Bar::Params::Create()
297 """ 343 """
298 classname = cpp_util.Classname(function.name)
299 c = code.Code() 344 c = code.Code()
300 (c.Append('// static') 345 (c.Append('// static')
301 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' 346 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> '
302 '(const ListValue& args) {') 347 '%(cpp_namespace)s::Params::Create(const ListValue& args) {')
303 .Concat(self._GenerateParamsCheck(function, 'args')) 348 .Concat(self._GenerateParamsCheck(function, 'args'))
304 .Append('scoped_ptr<Params> params(new Params());') 349 .Append('scoped_ptr<Params> params(new Params());')
305 ) 350 )
306 c.Substitute({'classname': classname}) 351 c.Substitute({'cpp_namespace': cpp_namespace})
307 352
308 for param in function.params: 353 for param in function.params:
309 c.Concat(self._InitializePropertyToDefault(param, 'params')) 354 c.Concat(self._InitializePropertyToDefault(param, 'params'))
310 355
311 for i, param in enumerate(function.params): 356 for i, param in enumerate(function.params):
312 # Any failure will cause this function to return. If any argument is 357 # Any failure will cause this function to return. If any argument is
313 # incorrect or missing, those following it are not processed. Note that 358 # incorrect or missing, those following it are not processed. Note that
314 # this is still correct in the case of multiple optional arguments as an 359 # this is still correct in the case of multiple optional arguments as an
315 # optional argument at position 4 cannot exist without an argument at 360 # optional argument at position 4 cannot exist without an argument at
316 # position 3. 361 # position 3.
(...skipping 29 matching lines...) Expand all
346 prop: the property the code is populating. 391 prop: the property the code is populating.
347 value_var: a Value* that should represent |prop|. 392 value_var: a Value* that should represent |prop|.
348 dst: the object with |prop| as a member. 393 dst: the object with |prop| as a member.
349 failure_value: the value to return if |prop| cannot be extracted from 394 failure_value: the value to return if |prop| cannot be extracted from
350 |value_var| 395 |value_var|
351 check_type: if true, will check if |value_var| is the correct Value::Type 396 check_type: if true, will check if |value_var| is the correct Value::Type
352 """ 397 """
353 c = code.Code() 398 c = code.Code()
354 c.Sblock('{') 399 c.Sblock('{')
355 400
356 if check_type and prop.type_ != PropertyType.CHOICES: 401 if check_type and prop.type_ not in (
402 PropertyType.CHOICES, PropertyType.ANY):
357 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') 403 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))')
358 .Append(' return %(failure_value)s;') 404 .Append(' return %(failure_value)s;')
359 ) 405 )
360 406
361 if prop.type_.is_fundamental: 407 if prop.type_.is_fundamental:
362 if prop.optional: 408 if prop.optional:
363 (c.Append('%(ctype)s temp;') 409 (c.Append('%(ctype)s temp;')
364 .Append('if (%s)' % 410 .Append('if (%s)' %
365 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp')) 411 cpp_util.GetAsFundamentalValue(prop, value_var, '&temp'))
366 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));') 412 .Append(' %(dst)s->%(name)s.reset(new %(ctype)s(temp));')
(...skipping 15 matching lines...) Expand all
382 .Append('%(dst)s->%(name)s = temp.Pass();') 428 .Append('%(dst)s->%(name)s = temp.Pass();')
383 ) 429 )
384 else: 430 else:
385 (c.Append('DictionaryValue* dictionary = NULL;') 431 (c.Append('DictionaryValue* dictionary = NULL;')
386 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') 432 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
387 .Append(' return %(failure_value)s;') 433 .Append(' return %(failure_value)s;')
388 .Append( 434 .Append(
389 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') 435 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))')
390 .Append(' return %(failure_value)s;') 436 .Append(' return %(failure_value)s;')
391 ) 437 )
438 elif prop.type_ == PropertyType.ANY:
439 if prop.optional:
440 c.Append('%(dst)s->%(name)s.reset(new Any());')
441 c.Append(self._any_helper.Init(prop, value_var, dst) + ';')
392 elif prop.type_ == PropertyType.ARRAY: 442 elif prop.type_ == PropertyType.ARRAY:
393 # util_cc_helper deals with optional and required arrays 443 # util_cc_helper deals with optional and required arrays
394 (c.Append('ListValue* list = NULL;') 444 (c.Append('ListValue* list = NULL;')
395 .Append('if (!%(value_var)s->GetAsList(&list))') 445 .Append('if (!%(value_var)s->GetAsList(&list))')
396 .Append(' return %(failure_value)s;') 446 .Append(' return %(failure_value)s;')
397 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( 447 .Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
398 prop, 'list', dst + '->' + prop.unix_name)) 448 prop, 'list', dst + '->' + prop.unix_name))
399 .Append(' return %(failure_value)s;') 449 .Append(' return %(failure_value)s;')
400 ) 450 )
401 elif prop.type_ == PropertyType.CHOICES: 451 elif prop.type_ == PropertyType.CHOICES:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 ) 485 )
436 else: 486 else:
437 raise NotImplementedError(prop.type_) 487 raise NotImplementedError(prop.type_)
438 c.Eblock('}') 488 c.Eblock('}')
439 sub = { 489 sub = {
440 'value_var': value_var, 490 'value_var': value_var,
441 'name': prop.unix_name, 491 'name': prop.unix_name,
442 'dst': dst, 492 'dst': dst,
443 'failure_value': failure_value, 493 'failure_value': failure_value,
444 } 494 }
445 if prop.type_ != PropertyType.CHOICES: 495 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
446 sub['ctype'] = self._cpp_type_generator.GetType(prop) 496 sub['ctype'] = self._cpp_type_generator.GetType(prop)
447 sub['value_type'] = cpp_util.GetValueType(prop) 497 sub['value_type'] = cpp_util.GetValueType(prop)
448 c.Substitute(sub) 498 c.Substitute(sub)
449 return c 499 return c
450 500
451 def _GeneratePropertyFunctions(self, param_namespace, params): 501 def _GeneratePropertyFunctions(self, param_namespace, params):
452 """Generate the functions for structures generated by a property such as 502 """Generate the functions for structures generated by a property such as
453 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects. 503 CreateEnumValue for ENUMs and Populate/ToValue for Params/Result objects.
454 """ 504 """
455 c = code.Code() 505 c = code.Code()
456 for param in params: 506 for param in params:
457 if param.type_ == PropertyType.OBJECT: 507 if param.type_ == PropertyType.OBJECT:
458 c.Concat(self._GenerateType( 508 c.Concat(self._GenerateType(
459 param_namespace + '::' + cpp_util.Classname(param.name), 509 param_namespace + '::' + cpp_util.Classname(param.name),
460 param)) 510 param))
461 c.Append() 511 c.Append()
512 elif param.type_ == PropertyType.CHOICES:
513 c.Concat(self._GeneratePropertyFunctions(
514 param_namespace, param.choices.values()))
462 elif param.type_ == PropertyType.ENUM: 515 elif param.type_ == PropertyType.ENUM:
463 c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) 516 c.Concat(self._GenerateCreateEnumValue(param_namespace, param))
464 c.Append() 517 c.Append()
465 return c 518 return c
466 519
467 def _GenerateFunctionResultCreate(self, function): 520 def _GenerateFunctionResultCreate(self, cpp_namespace, function):
468 """Generate function to create a Result given the return value. 521 """Generate function to create a Result given the return value.
522
523 E.g for function "Bar", generate Bar::Result::Create
469 """ 524 """
470 classname = cpp_util.Classname(function.name)
471 c = code.Code() 525 c = code.Code()
472 params = function.callback.params 526 params = function.callback.params
473 527
474 if not params: 528 if not params:
475 (c.Append('Value* %s::Result::Create() {' % classname) 529 (c.Append('Value* %s::Result::Create() {' % cpp_namespace)
476 .Append(' return Value::CreateNullValue();') 530 .Append(' return Value::CreateNullValue();')
477 .Append('}') 531 .Append('}')
478 ) 532 )
479 else: 533 else:
480 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams( 534 expanded_params = self._cpp_type_generator.GetExpandedChoicesInParams(
481 params) 535 params)
482 c.Concat(self._GeneratePropertyFunctions( 536 c.Concat(self._GeneratePropertyFunctions(
483 classname + '::Result', expanded_params)) 537 cpp_namespace + '::Result', expanded_params))
484 538
485 # If there is a single parameter, this is straightforward. However, if 539 # If there is a single parameter, this is straightforward. However, if
486 # the callback parameter is of 'choices', this generates a Create method 540 # the callback parameter is of 'choices', this generates a Create method
487 # for each choice. This works because only 1 choice can be returned at a 541 # for each choice. This works because only 1 choice can be returned at a
488 # time. 542 # time.
489 for param in expanded_params: 543 for param in expanded_params:
544 if param.type_ == PropertyType.ANY:
545 # Generation of Value* Create(Value*) is redundant.
546 continue
490 # We treat this argument as 'required' to avoid wrapping it in a 547 # We treat this argument as 'required' to avoid wrapping it in a
491 # scoped_ptr if it's optional. 548 # scoped_ptr if it's optional.
492 param_copy = param.Copy() 549 param_copy = param.Copy()
493 param_copy.optional = False 550 param_copy.optional = False
494 c.Sblock('Value* %(classname)s::Result::Create(const %(arg)s) {') 551 c.Sblock('Value* %(cpp_namespace)s::Result::Create(const %(arg)s) {')
495 c.Append('return %s;' % 552 c.Append('return %s;' %
496 self._CreateValueFromProperty(param_copy, param_copy.unix_name)) 553 self._CreateValueFromProperty(param_copy, param_copy.unix_name))
497 c.Eblock('}') 554 c.Eblock('}')
498 c.Substitute({'classname': classname, 555 c.Substitute({
556 'cpp_namespace': cpp_namespace,
499 'arg': cpp_util.GetParameterDeclaration( 557 'arg': cpp_util.GetParameterDeclaration(
500 param_copy, self._cpp_type_generator.GetType(param_copy)) 558 param_copy, self._cpp_type_generator.GetType(param_copy))
501 }) 559 })
502 560
503 return c 561 return c
504 562
505 def _InitializePropertyToDefault(self, prop, dst): 563 def _InitializePropertyToDefault(self, prop, dst):
506 """Initialize a model.Property to its default value inside an object. 564 """Initialize a model.Property to its default value inside an object.
507 565
566 E.g for optional enum "state", generate dst->state = STATE_NONE;
567
508 dst: Type* 568 dst: Type*
509 """ 569 """
510 c = code.Code() 570 c = code.Code()
511 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES): 571 if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES):
512 if prop.optional: 572 if prop.optional:
513 prop_name = prop.unix_name 573 prop_name = prop.unix_name
514 if prop.type_ == PropertyType.CHOICES: 574 if prop.type_ == PropertyType.CHOICES:
515 prop_name = prop.unix_name + '_type' 575 prop_name = prop.unix_name + '_type'
516 c.Append('%s->%s = %s;' % ( 576 c.Append('%s->%s = %s;' % (
517 dst, 577 dst,
518 prop_name, 578 prop_name,
519 self._cpp_type_generator.GetEnumNoneValue(prop))) 579 self._cpp_type_generator.GetEnumNoneValue(prop)))
520 return c 580 return c
521 581
OLDNEW
« no previous file with comments | « tools/json_schema_compiler/api_gen_util.gyp ('k') | tools/json_schema_compiler/code.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698