Fix build break
[chromium-blink-merge.git] / tools / json_schema_compiler / dart_generator.py
blobd40cc7329ceb5c5378089ef1cd74011d90c61bea
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
3 # found in the LICENSE file.
4 """
5 Generator language component for compiler.py that adds Dart language support.
6 """
8 from code import Code
9 from model import *
10 from schema_util import *
12 import os
13 from datetime import datetime
15 LICENSE = (
16 """// Copyright (c) %s, the Dart project authors. Please see the AUTHORS file
17 // for details. All rights reserved. Use of this source code is governed by a
18 // BSD-style license that can be found in the LICENSE file.""" %
19 datetime.now().year)
21 class DartGenerator(object):
22 def __init__(self, dart_overrides_dir=None):
23 self._dart_overrides_dir = dart_overrides_dir
25 def Generate(self, namespace):
26 return _Generator(namespace, self._dart_overrides_dir).Generate()
28 class _Generator(object):
29 """A .dart generator for a namespace.
30 """
32 def __init__(self, namespace, dart_overrides_dir=None):
33 self._namespace = namespace
34 # TODO(sashab): Once inline type definitions start being added to
35 # self._types, make a _FindType(self, type_) function that looks at
36 # self._namespace.types.
37 self._types = namespace.types
39 # Build a dictionary of Type Name --> Custom Dart code.
40 self._type_overrides = {}
41 if dart_overrides_dir is not None:
42 for filename in os.listdir(dart_overrides_dir):
43 if filename.startswith(namespace.unix_name):
44 with open(os.path.join(dart_overrides_dir, filename)) as f:
45 # Split off the namespace and file extension, leaving just the type.
46 type_path = '.'.join(filename.split('.')[1:-1])
47 self._type_overrides[type_path] = f.read()
49 # TODO(sashab): Add all inline type definitions to the global Types
50 # dictionary here, so they have proper names, and are implemented along with
51 # all other types. Also update the parameters/members with these types
52 # to reference these new types instead.
54 def Generate(self):
55 """Generates a Code object with the .dart for the entire namespace.
56 """
57 c = Code()
58 (c.Append(LICENSE)
59 .Append()
60 .Append('// Generated from namespace: %s' % self._namespace.name)
61 .Append()
62 .Append('part of chrome;'))
64 if self._types:
65 (c.Append()
66 .Append('/**')
67 .Append(' * Types')
68 .Append(' */')
69 .Append()
71 for type_ in self._types.values():
72 # Check for custom dart for this whole type.
73 override = self._GetOverride([type_.name], document_with=type_)
74 c.Cblock(override if override is not None else self._GenerateType(type_))
76 if self._namespace.events:
77 (c.Append('/**')
78 .Append(' * Events')
79 .Append(' */')
80 .Append()
82 for event_name in self._namespace.events:
83 c.Cblock(self._GenerateEvent(self._namespace.events[event_name]))
85 (c.Append('/**')
86 .Append(' * Functions')
87 .Append(' */')
88 .Append()
90 c.Cblock(self._GenerateMainClass())
92 return c
94 def _GenerateType(self, type_):
95 """Given a Type object, returns the Code with the .dart for this
96 type's definition.
98 Assumes this type is a Parameter Type (creatable by user), and creates an
99 object that extends ChromeObject. All parameters are specifiable as named
100 arguments in the constructor, and all methods are wrapped with getters and
101 setters that hide the JS() implementation.
103 c = Code()
105 # Since enums are just treated as strings for now, don't generate their
106 # type.
107 # TODO(sashab): Find a nice way to wrap enum objects.
108 if type_.property_type is PropertyType.ENUM:
109 return c
111 (c.Concat(self._GenerateDocumentation(type_))
112 .Sblock('class %(type_name)s extends ChromeObject {')
115 # Check whether this type has function members. If it does, don't allow
116 # public construction.
117 add_public_constructor = all(not self._IsFunction(p.type_)
118 for p in type_.properties.values())
119 constructor_fields = [self._GeneratePropertySignature(p)
120 for p in type_.properties.values()]
122 if add_public_constructor:
123 (c.Append('/*')
124 .Append(' * Public constructor')
125 .Append(' */')
126 .Sblock('%(type_name)s({%(constructor_fields)s}) {')
129 for prop_name in type_.properties:
130 (c.Sblock('if (?%s)' % prop_name)
131 .Append('this.%s = %s;' % (prop_name, prop_name))
132 .Eblock()
134 (c.Eblock('}')
135 .Append()
138 (c.Append('/*')
139 .Append(' * Private constructor')
140 .Append(' */')
141 .Append('%(type_name)s._proxy(_jsObject) : super._proxy(_jsObject);')
144 # Add an accessor (getter & setter) for each property.
145 properties = [p for p in type_.properties.values()
146 if not self._IsFunction(p.type_)]
147 if properties:
148 (c.Append()
149 .Append('/*')
150 .Append(' * Public accessors')
151 .Append(' */')
153 for prop in properties:
154 override = self._GetOverride([type_.name, prop.name], document_with=prop)
155 c.Concat(override if override is not None
156 else self._GenerateGetterAndSetter(type_, prop))
158 # Now add all the methods.
159 methods = [t for t in type_.properties.values()
160 if self._IsFunction(t.type_)]
161 if methods:
162 (c.Append()
163 .Append('/*')
164 .Append(' * Methods')
165 .Append(' */')
167 for prop in methods:
168 # Check if there's an override for this method.
169 override = self._GetOverride([type_.name, prop.name], document_with=prop)
170 c.Cblock(override if override is not None
171 else self._GenerateFunction(prop.type_.function))
173 (c.Eblock('}')
174 .Substitute({
175 'type_name': self._AddPrefix(type_.simple_name),
176 'constructor_fields': ', '.join(constructor_fields)
180 return c
182 def _GenerateGetterAndSetter(self, type_, prop):
183 """Given a Type and Property, returns the Code object for the getter and
184 setter for that property.
186 c = Code()
187 override = self._GetOverride([type_.name, prop.name, '.get'],
188 document_with=prop)
189 c.Cblock(override if override is not None
190 else self._GenerateGetter(type_, prop))
191 override = self._GetOverride([type_.name, prop.name, '.set'])
192 c.Cblock(override if override is not None
193 else self._GenerateSetter(type_, prop))
194 return c
196 def _GenerateGetter(self, type_, prop):
197 """Given a Type and Property, returns the Code object for the getter for
198 that property.
200 Also adds the documentation for this property before the method.
202 c = Code()
203 c.Concat(self._GenerateDocumentation(prop))
205 type_name = self._GetDartType(prop.type_)
206 if (self._IsBaseType(prop.type_)):
207 c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" %
208 (type_name, prop.name, type_name, prop.name))
209 elif self._IsSerializableObjectType(prop.type_):
210 c.Append("%s get %s => new %s._proxy(JS('', '#.%s', "
211 "this._jsObject));"
212 % (type_name, prop.name, type_name, prop.name))
213 elif self._IsListOfSerializableObjects(prop.type_):
214 (c.Sblock('%s get %s {' % (type_name, prop.name))
215 .Append('%s __proxy_%s = new %s();' % (type_name, prop.name,
216 type_name))
217 .Sblock("for (var o in JS('List', '#.%s', this._jsObject)) {" %
218 prop.name)
219 .Append('__proxy_%s.add(new %s._proxy(o));' % (prop.name,
220 self._GetDartType(prop.type_.item_type)))
221 .Eblock('}')
222 .Append('return __proxy_%s;' % prop.name)
223 .Eblock('}')
225 elif self._IsObjectType(prop.type_):
226 # TODO(sashab): Think of a way to serialize generic Dart objects.
227 if type_name in self._types:
228 c.Append("%s get %s => new %s._proxy(JS('%s', '#.%s', "
229 "this._jsObject));" %
230 (type_name, prop.name, type_name, type_name, prop.name))
231 else:
232 c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" %
233 (type_name, prop.name, type_name, prop.name))
234 else:
235 raise Exception(
236 "Could not generate wrapper for %s.%s: unserializable type %s" %
237 (type_.name, prop.name, type_name)
239 return c
241 def _GenerateSetter(self, type_, prop):
242 """Given a Type and Property, returns the Code object for the setter for
243 that property.
245 c = Code()
246 type_name = self._GetDartType(prop.type_)
247 wrapped_name = prop.name
248 if not self._IsBaseType(prop.type_):
249 wrapped_name = 'convertArgument(%s)' % prop.name
251 (c.Sblock("void set %s(%s %s) {" % (prop.name, type_name, prop.name))
252 .Append("JS('void', '#.%s = #', this._jsObject, %s);" %
253 (prop.name, wrapped_name))
254 .Eblock("}")
256 return c
258 def _GenerateDocumentation(self, prop):
259 """Given an object, generates the documentation for this object (as a
260 code string) and returns the Code object.
262 Returns an empty code object if the object has no documentation.
264 Uses triple-quotes for the string.
266 c = Code()
267 if prop.description is not None:
268 for line in prop.description.split('\n'):
269 c.Comment(line, comment_prefix='/// ')
270 return c
272 def _GenerateFunction(self, f):
273 """Returns the Code object for the given function.
275 c = Code()
276 c.Concat(self._GenerateDocumentation(f))
278 if not self._NeedsProxiedCallback(f):
279 c.Append("%s => %s;" % (self._GenerateFunctionSignature(f),
280 self._GenerateProxyCall(f)))
281 return c
283 (c.Sblock("%s {" % self._GenerateFunctionSignature(f))
284 .Concat(self._GenerateProxiedFunction(f.callback, f.callback.name))
285 .Append('%s;' % self._GenerateProxyCall(f))
286 .Eblock('}')
289 return c
291 def _GenerateProxiedFunction(self, f, callback_name):
292 """Given a function (assumed to be a callback), generates the proxied
293 version of this function, which calls |callback_name| if it is defined.
295 Returns a Code object.
297 c = Code()
298 proxied_params = []
299 # A list of Properties, containing List<*> objects that need proxying for
300 # their members (by copying out each member and proxying it).
301 lists_to_proxy = []
302 for p in f.params:
303 if self._IsBaseType(p.type_):
304 proxied_params.append(p.name)
305 elif self._IsSerializableObjectType(p.type_):
306 proxied_params.append('new %s._proxy(%s)' % (
307 self._GetDartType(p.type_), p.name))
308 elif self._IsListOfSerializableObjects(p.type_):
309 proxied_params.append('__proxy_%s' % p.name)
310 lists_to_proxy.append(p)
311 elif self._IsObjectType(p.type_):
312 # TODO(sashab): Find a way to build generic JS objects back in Dart.
313 proxied_params.append('%s' % p.name)
314 elif p.type_.property_type is PropertyType.ARRAY:
315 # TODO(sashab): This might be okay - what if this is a list of
316 # FileEntry elements? In this case, a basic list will proxy the objects
317 # fine.
318 proxied_params.append('%s' % p.name)
319 else:
320 raise Exception(
321 "Cannot automatically create proxy; can't wrap %s, type %s" % (
322 self._GenerateFunctionSignature(f), self._GetDartType(p.type_)))
324 (c.Sblock("void __proxy_callback(%s) {" % ', '.join(p.name for p in
325 f.params))
326 .Sblock('if (?%s) {' % callback_name)
329 # Add the proxied lists.
330 for list_to_proxy in lists_to_proxy:
331 (c.Append("%s __proxy_%s = new %s();" % (
332 self._GetDartType(list_to_proxy.type_),
333 list_to_proxy.name,
334 self._GetDartType(list_to_proxy.type_)))
335 .Sblock("for (var o in %s) {" % list_to_proxy.name)
336 .Append('__proxy_%s.add(new %s._proxy(o));' % (list_to_proxy.name,
337 self._GetDartType(list_to_proxy.type_.item_type)))
338 .Eblock("}")
341 (c.Append("%s(%s);" % (callback_name, ', '.join(proxied_params)))
342 .Eblock('}')
343 .Eblock('}')
345 return c
347 def _NeedsProxiedCallback(self, f):
348 """Given a function, returns True if this function's callback needs to be
349 proxied, False if not.
351 Function callbacks need to be proxied if they have at least one
352 non-base-type parameter.
354 return f.callback and self._NeedsProxy(f.callback)
356 def _NeedsProxy(self, f):
357 """Given a function, returns True if it needs to be proxied, False if not.
359 A function needs to be proxied if any of its members are non-base types.
360 This means that, when the function object is passed to Javascript, it
361 needs to be wrapped in a "proxied" call that converts the JS inputs to Dart
362 objects explicitly, before calling the real function with these new objects.
364 return any(not self._IsBaseType(p.type_) for p in f.params)
366 def _GenerateProxyCall(self, function, call_target='this._jsObject'):
367 """Given a function, generates the code to call that function via JS().
368 Returns a string.
370 |call_target| is the name of the object to call the function on. The default
371 is this._jsObject.
373 e.g.
374 JS('void', '#.resizeTo(#, #)', this._jsObject, width, height)
375 JS('void', '#.setBounds(#)', this._jsObject, convertArgument(bounds))
377 n_params = len(function.params)
378 if function.callback:
379 n_params += 1
381 return_type_str = self._GetDartType(function.returns)
382 params = []
384 # If this object is serializable, don't convert the type from JS - pass the
385 # JS object straight into the proxy.
386 if self._IsSerializableObjectType(function.returns):
387 params.append("''")
388 else:
389 params.append("'%s'" % return_type_str)
391 params.append("'#.%s(%s)'" % (function.name, ', '.join(['#'] * n_params)))
392 params.append(call_target)
394 for param in function.params:
395 if not self._IsBaseType(param.type_):
396 params.append('convertArgument(%s)' % param.name)
397 else:
398 params.append(param.name)
399 if function.callback:
400 # If this isn't a base type, we need a proxied callback.
401 callback_name = function.callback.name
402 if self._NeedsProxiedCallback(function):
403 callback_name = "__proxy_callback"
404 params.append('convertDartClosureToJS(%s, %s)' % (callback_name,
405 len(function.callback.params)))
407 # If the object is serializable, call the proxy constructor for this type.
408 proxy_call = 'JS(%s)' % ', '.join(params)
409 if self._IsSerializableObjectType(function.returns):
410 proxy_call = 'new %s._proxy(%s)' % (return_type_str, proxy_call)
412 return proxy_call
414 def _GenerateEvent(self, event):
415 """Given a Function object, returns the Code with the .dart for this event,
416 represented by the function.
418 All events extend the Event base type.
420 c = Code()
422 # Add documentation for this event.
423 (c.Concat(self._GenerateDocumentation(event))
424 .Sblock('class Event_%(event_name)s extends Event {')
427 # If this event needs a proxy, all calls need to be proxied.
428 needs_proxy = self._NeedsProxy(event)
430 # Override Event callback type definitions.
431 for ret_type, event_func in (('void', 'addListener'),
432 ('void', 'removeListener'),
433 ('bool', 'hasListener')):
434 param_list = self._GenerateParameterList(event.params, event.callback,
435 convert_optional=True)
436 if needs_proxy:
437 (c.Sblock('%s %s(void callback(%s)) {' % (ret_type, event_func,
438 param_list))
439 .Concat(self._GenerateProxiedFunction(event, 'callback'))
440 .Append('super.%s(callback);' % event_func)
441 .Eblock('}')
443 else:
444 c.Append('%s %s(void callback(%s)) => super.%s(callback);' %
445 (ret_type, event_func, param_list, event_func))
446 c.Append()
448 # Generate the constructor.
449 (c.Append('Event_%(event_name)s(jsObject) : '
450 'super._(jsObject, %(param_num)d);')
451 .Eblock('}')
452 .Substitute({
453 'event_name': self._namespace.unix_name + '_' + event.name,
454 'param_num': len(event.params)
458 return c
460 def _GenerateMainClass(self):
461 """Generates the main class for this file, which links to all functions
462 and events.
464 Returns a code object.
466 c = Code()
467 (c.Sblock('class API_%s {' % self._namespace.unix_name)
468 .Append('/*')
469 .Append(' * API connection')
470 .Append(' */')
471 .Append('Object _jsObject;')
474 # Add events.
475 if self._namespace.events:
476 (c.Append()
477 .Append('/*')
478 .Append(' * Events')
479 .Append(' */')
481 for event_name in self._namespace.events:
482 c.Append('Event_%s_%s %s;' % (self._namespace.unix_name, event_name,
483 event_name))
485 # Add functions.
486 if self._namespace.functions:
487 (c.Append()
488 .Append('/*')
489 .Append(' * Functions')
490 .Append(' */')
492 for function in self._namespace.functions.values():
493 # Check for custom dart for this whole property.
494 override = self._GetOverride([function.name], document_with=function)
495 c.Cblock(override if override is not None
496 else self._GenerateFunction(function))
498 # Add the constructor.
499 c.Sblock('API_%s(this._jsObject) {' % self._namespace.unix_name)
501 # Add events to constructor.
502 for event_name in self._namespace.events:
503 c.Append("%s = new Event_%s_%s(JS('', '#.%s', this._jsObject));" %
504 (event_name, self._namespace.unix_name, event_name, event_name))
506 (c.Eblock('}')
507 .Eblock('}')
509 return c
511 def _GeneratePropertySignature(self, prop):
512 """Given a property, returns a signature for that property.
513 Recursively generates the signature for callbacks.
514 Returns a String for the given property.
516 e.g.
517 bool x
518 void onClosed()
519 void doSomething(bool x, void callback([String x]))
521 if self._IsFunction(prop.type_):
522 return self._GenerateFunctionSignature(prop.type_.function)
523 return '%(type)s %(name)s' % {
524 'type': self._GetDartType(prop.type_),
525 'name': prop.simple_name
528 def _GenerateFunctionSignature(self, function, convert_optional=False):
529 """Given a function object, returns the signature for that function.
530 Recursively generates the signature for callbacks.
531 Returns a String for the given function.
533 If convert_optional is True, changes optional parameters to be required.
535 e.g.
536 void onClosed()
537 bool isOpen([String type])
538 void doSomething(bool x, void callback([String x]))
540 sig = '%(return_type)s %(name)s(%(params)s)'
542 if function.returns:
543 return_type = self._GetDartType(function.returns)
544 else:
545 return_type = 'void'
547 return sig % {
548 'return_type': return_type,
549 'name': function.simple_name,
550 'params': self._GenerateParameterList(function.params,
551 function.callback,
552 convert_optional=convert_optional)
555 def _GenerateParameterList(self,
556 params,
557 callback=None,
558 convert_optional=False):
559 """Given a list of function parameters, generates their signature (as a
560 string).
562 e.g.
563 [String type]
564 bool x, void callback([String x])
566 If convert_optional is True, changes optional parameters to be required.
567 Useful for callbacks, where optional parameters are treated as required.
569 # Params lists (required & optional), to be joined with commas.
570 # TODO(sashab): Don't assume optional params always come after required
571 # ones.
572 params_req = []
573 params_opt = []
574 for param in params:
575 p_sig = self._GeneratePropertySignature(param)
576 if param.optional and not convert_optional:
577 params_opt.append(p_sig)
578 else:
579 params_req.append(p_sig)
581 # Add the callback, if it exists.
582 if callback:
583 c_sig = self._GenerateFunctionSignature(callback, convert_optional=True)
584 if callback.optional:
585 params_opt.append(c_sig)
586 else:
587 params_req.append(c_sig)
589 # Join the parameters with commas.
590 # Optional parameters have to be in square brackets, e.g.:
592 # required params | optional params | output
593 # [] | [] | ''
594 # [x, y] | [] | 'x, y'
595 # [] | [a, b] | '[a, b]'
596 # [x, y] | [a, b] | 'x, y, [a, b]'
597 if params_opt:
598 params_opt[0] = '[%s' % params_opt[0]
599 params_opt[-1] = '%s]' % params_opt[-1]
600 param_sets = [', '.join(params_req), ', '.join(params_opt)]
602 # The 'if p' part here is needed to prevent commas where there are no
603 # parameters of a certain type.
604 # If there are no optional parameters, this prevents a _trailing_ comma,
605 # e.g. '(x, y,)'. Similarly, if there are no required parameters, this
606 # prevents a leading comma, e.g. '(, [a, b])'.
607 return ', '.join(p for p in param_sets if p)
609 def _GetOverride(self, key_chain, document_with=None):
610 """Given a list of keys, joins them with periods and searches for them in
611 the custom dart overrides.
612 If there is an override for that key, finds the override code and returns
613 the Code object. If not, returns None.
615 If document_with is not None, adds the documentation for this property
616 before the override code.
618 c = Code()
619 contents = self._type_overrides.get('.'.join(key_chain))
620 if contents is None:
621 return None
623 if document_with is not None:
624 c.Concat(self._GenerateDocumentation(document_with))
625 for line in contents.strip('\n').split('\n'):
626 c.Append(line)
627 return c
629 def _AddPrefix(self, name):
630 """Given the name of a type, prefixes the namespace (as camelcase) and
631 returns the new name.
633 # TODO(sashab): Split the dart library into multiple files, avoiding the
634 # need for this prefixing.
635 return ('%s%s' % (
636 ''.join(s.capitalize() for s in self._namespace.name.split('.')),
637 name))
639 def _IsFunction(self, type_):
640 """Given a model.Type, returns whether this type is a function.
642 return type_.property_type == PropertyType.FUNCTION
644 def _IsSerializableObjectType(self, type_):
645 """Given a model.Type, returns whether this type is a serializable object.
646 Serializable objects are custom types defined in this namespace.
648 If this object is a reference to something not in this namespace, assumes
649 its a serializable object.
651 if type_ is None:
652 return False
653 if type_.property_type is PropertyType.CHOICES:
654 return all(self._IsSerializableObjectType(c) for c in type_.choices)
655 if type_.property_type is PropertyType.REF:
656 if type_.ref_type in self._types:
657 return self._IsObjectType(self._types[type_.ref_type])
658 return True
659 if (type_.property_type == PropertyType.OBJECT
660 and type_.instance_of in self._types):
661 return self._IsObjectType(self._types[type_.instance_of])
662 return False
664 def _IsObjectType(self, type_):
665 """Given a model.Type, returns whether this type is an object.
667 return (self._IsSerializableObjectType(type_)
668 or type_.property_type in [PropertyType.OBJECT, PropertyType.ANY])
670 def _IsListOfSerializableObjects(self, type_):
671 """Given a model.Type, returns whether this type is a list of serializable
672 objects (or regular objects, if this list is treated as a type - in this
673 case, the item type was defined inline).
675 If this type is a reference to something not in this namespace, assumes
676 it is not a list of serializable objects.
678 if type_.property_type is PropertyType.CHOICES:
679 return all(self._IsListOfSerializableObjects(c) for c in type_.choices)
680 if type_.property_type is PropertyType.REF:
681 if type_.ref_type in self._types:
682 return self._IsListOfSerializableObjects(self._types[type_.ref_type])
683 return False
684 return (type_.property_type is PropertyType.ARRAY and
685 (self._IsSerializableObjectType(type_.item_type)))
687 def _IsListOfBaseTypes(self, type_):
688 """Given a model.Type, returns whether this type is a list of base type
689 objects (PropertyType.REF types).
691 if type_.property_type is PropertyType.CHOICES:
692 return all(self._IsListOfBaseTypes(c) for c in type_.choices)
693 return (type_.property_type is PropertyType.ARRAY and
694 self._IsBaseType(type_.item_type))
696 def _IsBaseType(self, type_):
697 """Given a model.type_, returns whether this type is a base type
698 (string, number, boolean, or a list of these).
700 If type_ is a Choices object, returns True if all possible choices are base
701 types.
703 # TODO(sashab): Remove 'Choices' as a base type once they are wrapped in
704 # native Dart classes.
705 if type_.property_type is PropertyType.CHOICES:
706 return all(self._IsBaseType(c) for c in type_.choices)
707 return (
708 (self._GetDartType(type_) in ['bool', 'num', 'int', 'double', 'String'])
709 or (type_.property_type is PropertyType.ARRAY
710 and self._IsBaseType(type_.item_type))
713 def _GetDartType(self, type_):
714 """Given a model.Type object, returns its type as a Dart string.
716 if type_ is None:
717 return 'void'
719 prop_type = type_.property_type
720 if prop_type is PropertyType.REF:
721 if type_.ref_type in self._types:
722 return self._GetDartType(self._types[type_.ref_type])
723 # TODO(sashab): If the type is foreign, it might have to be imported.
724 return StripNamespace(type_.ref_type)
725 elif prop_type is PropertyType.BOOLEAN:
726 return 'bool'
727 elif prop_type is PropertyType.INTEGER:
728 return 'int'
729 elif prop_type is PropertyType.INT64:
730 return 'num'
731 elif prop_type is PropertyType.DOUBLE:
732 return 'double'
733 elif prop_type is PropertyType.STRING:
734 return 'String'
735 elif prop_type is PropertyType.ENUM:
736 return 'String'
737 elif prop_type is PropertyType.CHOICES:
738 # TODO(sashab): Think of a nice way to generate code for Choices objects
739 # in Dart.
740 return 'Object'
741 elif prop_type is PropertyType.ANY:
742 return 'Object'
743 elif prop_type is PropertyType.OBJECT:
744 # TODO(sashab): type_.name is the name of the function's parameter for
745 # inline types defined in functions. Think of a way to generate names
746 # for this, or remove all inline type definitions at the start.
747 if type_.instance_of is not None:
748 return type_.instance_of
749 if not isinstance(type_.parent, Function):
750 return self._AddPrefix(type_.name)
751 return 'Object'
752 elif prop_type is PropertyType.FUNCTION:
753 return 'Function'
754 elif prop_type is PropertyType.ARRAY:
755 return 'List<%s>' % self._GetDartType(type_.item_type)
756 elif prop_type is PropertyType.BINARY:
757 return 'String'
758 else:
759 raise NotImplementedError(prop_type)