 Chromium Code Reviews
 Chromium Code Reviews| OLD | NEW | 
|---|---|
| (Empty) | |
| 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 | |
| 7 Pass 'dart' with the -l flag to compiler.py to activate the use of this library. | |
| 8 """ | |
| 9 | |
| 10 from collections import defaultdict | |
| 
not at google - send to devlin
2013/01/29 16:37:08
unused
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 11 | |
| 12 from code import Code | |
| 13 from model import * | |
| 14 | |
| 15 import os | |
| 16 from datetime import datetime | |
| 17 | |
| 18 LICENSE = (""" | |
| 19 // Copyright (c) %s, the Dart project authors. Please see the AUTHORS file | |
| 20 // for details. All rights reserved. Use of this source code is governed by a | |
| 21 // BSD-style license that can be found in the LICENSE file.""" % | |
| 22 datetime.now().year) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
indent this line?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 23 | |
| 24 class DartGenerator(object): | |
| 25 """A .dart generator for a namespace. | |
| 26 """ | |
| 27 | |
| 28 def __init__(self, namespace, custom_dart_folder): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
IMO like you said in the doc, "overrides" would be
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 29 self._namespace = namespace | |
| 30 self._types = namespace.types | |
| 31 | |
| 32 # Build a dictionary of Type Name --> Custom Dart code. | |
| 33 self._custom_dart = {} | |
| 34 if custom_dart_folder: | |
| 
not at google - send to devlin
2013/01/29 16:37:08
If custom_dart_folder is optional then make the ar
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 35 for filename in os.listdir(custom_dart_folder): | |
| 36 if filename.startswith(namespace.unix_name): | |
| 37 with open(os.path.join(custom_dart_folder, filename)) as f: | |
| 38 # Split off the namespace and file extension, leaving just the type. | |
| 39 type_path = '.'.join(filename.split('.')[1:-1]) | |
| 40 self._custom_dart[type_path] = f.read() | |
| 41 print self._custom_dart | |
| 42 global x | |
| 43 x= self._namespace | |
| 
not at google - send to devlin
2013/01/29 16:37:08
delete 3 lines above here?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 44 | |
| 45 def Generate(self): | |
| 46 """Generates a Code object with the .dart for the entire namespace. | |
| 47 """ | |
| 48 c = Code() | |
| 49 (c.Append(LICENSE) | |
| 50 .Append() | |
| 51 .Append('part of chrome;')) | |
| 52 | |
| 53 # Add all types. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
comment not useful
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 54 if self._types: | |
| 55 (c.Append() | |
| 56 .Append('/**') | |
| 57 .Append(' * Types') | |
| 58 .Append(' */') | |
| 59 ) | |
| 60 for type_name in self._types: | |
| 61 c.Concat(self._GenerateType(self._types[type_name])) | |
| 62 | |
| 63 # Add all events. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
ditto
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 64 if self._namespace.events: | |
| 65 (c.Append() | |
| 66 .Append('/**') | |
| 67 .Append(' * Events') | |
| 68 .Append(' */') | |
| 69 ) | |
| 70 for event_name in self._namespace.events: | |
| 71 c.Concat(self._GenerateEvent(self._namespace.events[event_name])) | |
| 72 | |
| 73 # Add main class for this file. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
ditto
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 74 (c.Append() | |
| 75 .Append('/**') | |
| 76 .Append(' * Functions') | |
| 77 .Append(' */') | |
| 78 ) | |
| 79 c.Concat(self._GenerateMainClass()) | |
| 80 | |
| 81 return c | |
| 82 | |
| 83 def _GenerateType(self, type_): | |
| 84 """Given a Type object, returns the Code with the .dart for this | |
| 85 type's definition. | |
| 86 | |
| 87 Assumes this type is a Parameter Type (creatable by user), and creates an | |
| 88 object that extends ChromeObject. All parameters are specifiable as named | |
| 89 arguments in the constructor, and all methods are wrapped with getters and | |
| 90 setters that hide the JS() implementation. | |
| 91 """ | |
| 92 c = Code() | |
| 93 (c.Append() | |
| 94 .Concat(self._GenerateDocumentation(type_)) | |
| 95 .Sblock('class %(type_name)s extends ChromeObject {') | |
| 96 ) | |
| 97 | |
| 98 # Check whether this type has function members. If it does, don't allow | |
| 99 # public construction. | |
| 100 add_public_constructor = True | |
| 
not at google - send to devlin
2013/01/29 16:37:08
add_public_constructor = any(self._IsFunction(p)
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 101 for prop_name in type_.properties: | |
| 102 if self._IsFunction(type_.properties[prop_name]): | |
| 103 add_public_constructor = False | |
| 104 break | |
| 105 | |
| 106 constructor_fields = [] | |
| 
not at google - send to devlin
2013/01/29 16:37:08
constructor_fields = [self._GeneratePropertySignat
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 107 for prop_name in type_.properties: | |
| 108 constructor_fields.append( | |
| 109 self._GeneratePropertySignature(type_.properties[prop_name], | |
| 110 prepend_this = False, | |
| 111 omitBasicTypes = False)) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
prepend_this = False -> prepend_this=False
omitBas
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 112 | |
| 113 # Add the public constructor. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
I think you can leave this comment out, the variab
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 114 if add_public_constructor: | |
| 115 (c.Append('/*') | |
| 116 .Append(' * Public constructor') | |
| 117 .Append(' */') | |
| 118 .Sblock('%(type_name)s({%(constructor_fields)s}) {') | |
| 119 ) | |
| 120 | |
| 121 for prop_name in type_.properties: | |
| 122 c.Append('this.%s = %s;' % (prop_name, prop_name)) | |
| 123 (c.Eblock('}') | |
| 124 .Append() | |
| 125 ) | |
| 126 | |
| 127 # Add the private constructor. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
ditto
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 128 (c.Append('/*') | |
| 129 .Append(' * Private constructor') | |
| 130 .Append(' */') | |
| 131 .Append('%(type_name)s._proxy(_jsObject) : super._proxy(_jsObject);') | |
| 132 ) | |
| 133 | |
| 134 # Add an accessor (getter & setter) for each property. | |
| 135 properties = [t for t in type_.properties.values() | |
| 136 if not self._IsFunction(t)] | |
| 
not at google - send to devlin
2013/01/29 16:37:08
nit: p would be a slighty more appropriate tempora
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 137 if properties: | |
| 138 (c.Append() | |
| 139 .Append('/*') | |
| 140 .Append(' * Public accessors') | |
| 141 .Append(' */') | |
| 142 ) | |
| 143 for prop in properties: | |
| 144 type_name = self._GetPropertyType(prop) | |
| 145 prop_is_base_type = self._IsBaseType(prop) | |
| 146 | |
| 147 # Check for custom dart for this whole property. | |
| 148 overwrite_key = '%s.%s' % (type_.name, prop.name) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
overwrite -> override?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 149 if overwrite_key in self._custom_dart: | |
| 
not at google - send to devlin
2013/01/29 16:37:08
A common idiom is like:
override = self._custom_d
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 150 contents = self._custom_dart[overwrite_key] | |
| 151 if contents.strip(): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
Why is this guard necessary? If it is for some rea
 
sashab
2013/01/30 05:26:03
If you want to "hide" a function completely, you c
 
not at google - send to devlin
2013/01/31 02:08:48
So is this an alternative to specifying nodart?
 
sashab
2013/01/31 04:41:40
Exactly. The good thing about this is its all in t
 | |
| 152 (c.Append() | |
| 153 .Concat(self._GenerateDocumentation(prop)) | |
| 154 ) | |
| 155 for line in contents.split('\n'): | |
| 156 c.Append(line) | |
| 157 else: | |
| 158 # Add the getter. | |
| 159 getter_key = '%s.%s.get' % (type_.name, prop.name) | |
| 160 if getter_key in self._custom_dart: | |
| 161 contents = self._custom_dart[getter_key] | |
| 162 if contents.strip(): | |
| 163 # Add the documentation for this property. | |
| 164 (c.Append() | |
| 165 .Concat(self._GenerateDocumentation(prop)) | |
| 166 ) | |
| 167 for line in contents.split('\n'): | |
| 168 c.Append(line) | |
| 169 else: | |
| 170 # Add the documentation for this property. | |
| 171 (c.Append() | |
| 172 .Concat(self._GenerateDocumentation(prop)) | |
| 173 ) | |
| 174 | |
| 175 # TODO(sashab): Serialize generic Dart objects differently. | |
| 176 if prop_is_base_type or self._IsObjectType(prop): | |
| 177 c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" % | |
| 178 (type_name, prop.name, type_name, prop.name)) | |
| 179 elif prop.type_.property_type == PropertyType.REF: | |
| 180 c.Append("%s get %s => new %s._proxy(JS('', '#.%s', " | |
| 181 "this._jsObject));" | |
| 182 % (type_name, prop.name, type_name, prop.name)) | |
| 183 else: | |
| 184 # TODO(sashab): What to do in this situation? Unserializable type. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
throw an exception?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 185 c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" % | |
| 186 (type_name, prop.name, type_name, prop.name)) | |
| 187 | |
| 188 # Add the setter. | |
| 189 setter_key = '%s.%s.set' % (type_.name, prop.name) | |
| 190 if setter_key in self._custom_dart: | |
| 191 contents = self._custom_dart[setter_key] | |
| 192 if contents.strip(): | |
| 193 c.Append() | |
| 194 for line in contents.split('\n'): | |
| 195 c.Append(line) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
This pattern (reading from custom dart and then ap
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 196 else: | |
| 197 wrapped_name = prop.name | |
| 198 if not prop_is_base_type: | |
| 199 wrapped_name = 'convertArgument(%s)' % prop.name | |
| 200 | |
| 201 (c.Append() | |
| 202 .Sblock("void set %s(%s %s) {" % (prop.name, type_name, prop.name)) | |
| 203 .Append("JS('void', '#.%s = #', this._jsObject, %s);" % | |
| 204 (prop.name, wrapped_name)) | |
| 205 .Eblock("}") | |
| 206 ) | |
| 207 | |
| 208 # Now add all the function properties. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
s/function properties/methods/ ?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 209 function_properties = [t for t in type_.properties.values() | |
| 210 if self._IsFunction(t)] | |
| 211 if function_properties: | |
| 212 (c.Append() | |
| 213 .Append('/*') | |
| 214 .Append(' * Methods') | |
| 215 .Append(' */') | |
| 216 ) | |
| 217 for prop in function_properties: | |
| 218 c.Concat(self._GenerateFunction(prop.type_.function)) | |
| 219 | |
| 220 (c.Eblock('}') | |
| 221 .Substitute({ | |
| 222 'type_name': type_.simple_name, | |
| 223 'constructor_fields': ', '.join(constructor_fields) | |
| 224 }) | |
| 225 ) | |
| 226 | |
| 227 return c | |
| 228 | |
| 229 def _GenerateDocumentation(self, prop): | |
| 230 """Given an object, generates the documentation for this object (as a | |
| 231 code string) and returns the Code object. | |
| 232 | |
| 233 Returns an empty code object if the object has no documentation. | |
| 234 | |
| 235 Uses triple-quotes for the string. | |
| 236 """ | |
| 237 c = Code() | |
| 238 if not hasattr(prop, 'description'): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
"hasattr" should no longer be necessary (and we sh
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 239 return c | |
| 240 | |
| 241 if prop.description: | |
| 
not at google - send to devlin
2013/01/29 16:37:08
oh, there's a check here anyway. I prefer the chec
 
sashab
2013/01/30 05:26:03
Hopefully I've made it a little clearer now.
 | |
| 242 for line in prop.description.split('\n'): | |
| 243 c.Comment(line, comment_prefix='/// ') | |
| 244 return c | |
| 245 | |
| 246 | |
| 247 def _GenerateFunction(self, f): | |
| 248 """Returns the Code object for the given function. | |
| 249 """ | |
| 250 return (Code() | |
| 251 .Append() | |
| 252 .Concat(self._GenerateDocumentation(f)) | |
| 253 .Append("%s => %s;" % (self._GenerateFunctionSignature(f), | |
| 254 self._GenerateProxyCall(f))) | |
| 255 ) | |
| 256 | |
| 257 def _GenerateProxyCall(self, function, callTarget='this._jsObject'): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
call_target
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 258 """Given a function, generates the code to call that function via JS(). | |
| 259 Returns a string. | |
| 260 | |
| 261 |callTarget| is the name of the object to call the function on. The default | |
| 262 is this._jsObject. | |
| 263 | |
| 264 e.g. | |
| 265 JS('void', '#.resizeTo(#, #)', this._jsObject, width, height) | |
| 266 JS('void', '#.setBounds(#)', this._jsObject, convertArgument(bounds)) | |
| 267 """ | |
| 268 | |
| 269 format = ("JS('%(return_type)s', " | |
| 270 "'#.%(name)s(%(param_hashes)s)', " | |
| 271 "%(target)s%(params)s)") | |
| 272 | |
| 273 params = "" | |
| 274 if function.params: | |
| 275 params_wrapped = [] | |
| 276 for param in function.params: | |
| 277 if not self._IsBaseType(param): | |
| 278 params_wrapped.append('convertArgument(%s)' % param.name) | |
| 279 else: | |
| 280 params_wrapped.append(param.name) | |
| 281 params = ', ' + ', '.join(params_wrapped) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
the adding comma stuff is a bit icky, could you ju
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 282 | |
| 283 return format % { | |
| 284 'return_type': self._GetPropertyType(function.returns), | |
| 285 'name': function.name, | |
| 286 'param_hashes': ', '.join('#' for p in function.params), | |
| 287 'target': callTarget, | |
| 288 'params': params | |
| 289 } | |
| 290 | |
| 291 def _GenerateEvent(self, event): | |
| 292 """Given a Function object, returns the Code with the .dart for this event, | |
| 293 represented by the function. | |
| 294 | |
| 295 All events extend the Event base type. | |
| 296 """ | |
| 297 c = Code() | |
| 298 | |
| 299 # Add documentation for this event. | |
| 300 (c.Append() | |
| 301 .Concat(self._GenerateDocumentation(event)) | |
| 302 .Sblock('class Event_%(event_name)s extends Event {') | |
| 303 ) | |
| 304 | |
| 305 # Override Event callback type definitions. | |
| 306 for ret_type, event_func in (('void', 'addListener'), | |
| 307 ('void', 'removeListener'), | |
| 308 ('bool', 'hasListener')): | |
| 309 | |
| 310 param_list = self._GenerateParameterList(event.params, event.callback, | |
| 311 allow_optional = False) | |
| 312 | |
| 313 c.Append('%s %s(void callback(%s)) => super.%s(callback);' % | |
| 314 (ret_type, event_func, param_list, event_func)) | |
| 315 | |
| 316 # Generate the constructor. | |
| 317 (c.Append() | |
| 318 .Append('Event_%(event_name)s(jsObject) : ' | |
| 319 'super(jsObject, %(param_num)d);') | |
| 320 ) | |
| 321 | |
| 322 (c.Eblock('}') | |
| 323 .Substitute({ | |
| 324 'event_name': self._namespace.unix_name + '_' + event.name, | |
| 325 'param_num': len(event.params) | |
| 326 }) | |
| 327 ) | |
| 328 | |
| 329 return c | |
| 330 | |
| 331 def _GenerateMainClass(self): | |
| 332 """Generates the main class for this file, which links to all functions | |
| 333 and events. | |
| 334 | |
| 335 Includes a ChromeApi member variable to represent the connection. | |
| 336 | |
| 337 Returns a code object. | |
| 338 """ | |
| 339 c = Code() | |
| 340 (c.Append() | |
| 341 .Sblock('class API_%(namespace_name)s {') | |
| 342 .Append('/*') | |
| 343 .Append(' * API connection') | |
| 344 .Append(' */') | |
| 345 .Append('Object _jsObject;') | |
| 346 ) | |
| 347 | |
| 348 # Add events. | |
| 349 if self._namespace.events: | |
| 350 (c.Append() | |
| 351 .Append('/*') | |
| 352 .Append(' * Events') | |
| 353 .Append(' */') | |
| 354 ) | |
| 355 for event_name in self._namespace.events: | |
| 356 c.Append('Event_%s_%s %s;' % (self._namespace.unix_name, event_name, | |
| 357 event_name)) | |
| 358 | |
| 359 # Add functions. | |
| 360 if self._namespace.functions: | |
| 361 (c.Append() | |
| 362 .Append('/*') | |
| 363 .Append(' * Functions') | |
| 364 .Append(' */') | |
| 365 ) | |
| 366 for function in self._namespace.functions.values(): | |
| 367 c.Concat(self._GenerateFunction(function)) | |
| 368 | |
| 369 # Add the constructor. | |
| 370 (c.Append() | |
| 371 .Sblock('API_%(namespace_name)s(this._jsObject) {') | |
| 372 ) | |
| 373 | |
| 374 # Add events to constructor. | |
| 375 for event_name in self._namespace.events: | |
| 376 c.Append("%s = new Event_%s_%s(JS('', '#.%s', this._jsObject));" % | |
| 377 (event_name, self._namespace.unix_name, event_name, event_name)) | |
| 378 c.Eblock('}') | |
| 379 | |
| 380 (c.Eblock('}') | |
| 381 .Substitute({ | |
| 382 'namespace_name': self._namespace.unix_name | |
| 
not at google - send to devlin
2013/01/29 16:37:08
substitution only used once, just %s it above?
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 383 }) | |
| 384 ) | |
| 385 | |
| 386 return c | |
| 387 | |
| 388 def _GeneratePropertySignature(self, prop, prepend_this=False, | |
| 389 omitBasicTypes=False, | |
| 390 functionsAsObjects=False, | |
| 391 withGetKeyword=False): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
functionsAsObjects -> functions_as_objects
withGet
 
sashab
2013/01/30 05:26:03
Fixed the camelcase problems. Removed the unused p
 | |
| 392 """Given a property, returns a signature for that property. | |
| 393 Recursively generates the signature for callbacks. | |
| 394 Returns a String for the given property. | |
| 395 | |
| 396 * If |prepend_this| is True, prepends "this." to all variable names. | |
| 397 * If |omitBasicTypes| is True, only adds type names for function types. | |
| 398 * If |functionsAsObjects| is True, treats callbacks as basic types and | |
| 399 prepends the type 'Function'. | |
| 400 * If |withGetKeyword| is True, adds the word 'get' between the property's | |
| 401 type and name. Used for getters in dart. | |
| 402 | |
| 403 e.g. | |
| 404 bool x | |
| 405 void onClosed() | |
| 406 void doSomething(bool x, void callback([String x])) | |
| 407 | |
| 408 e.g. If prepend_this is True: | |
| 409 bool this.x | |
| 410 void this.onClosed() | |
| 411 void this.doSomething(bool x, void callback([String x])) | |
| 412 | |
| 413 e.g. If omitBasicTypes is True: | |
| 414 this.x | |
| 415 void onClosed() | |
| 416 void doSomething(bool x, void callback([String x])) | |
| 417 | |
| 418 e.g. If functionsAsObjects is True: | |
| 419 bool x | |
| 420 Function onClosed | |
| 421 Function doSomething | |
| 422 | |
| 423 e.g. If withGetKeyword and functionsAsObjects is True: | |
| 424 bool get x | |
| 425 Function get onClosed | |
| 426 Function get doSomething | |
| 427 """ | |
| 428 if self._IsFunction(prop) and not functionsAsObjects: | |
| 429 return self._GenerateFunctionSignature(prop.type_.function, prepend_this) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
for optional arguments, be explicit, it's easier t
 
sashab
2013/01/30 05:26:03
Removed this parameter pass anyway, but note taken
 | |
| 430 else: | |
| 431 name_parts = [prop.simple_name] | |
| 432 if prepend_this: | |
| 433 name_parts[0] = 'this.' + name_parts[0] | |
| 
not at google - send to devlin
2013/01/29 16:37:08
might be a bit more concise as
name = '%s%s' % ('
 
sashab
2013/01/30 05:26:03
Not used anymore anyway.
 | |
| 434 if withGetKeyword: | |
| 435 name_parts = ['get'] + name_parts | |
| 
not at google - send to devlin
2013/01/29 16:37:08
somewhat likewise, like
if with_get_keyword:
  na
 
sashab
2013/01/30 05:26:03
Not used anymore anyway.
 | |
| 436 | |
| 437 name = ' '.join(name_parts) | |
| 438 type_ = (self._GetPropertyType(prop) + ' ') if not omitBasicTypes else '' | |
| 439 | |
| 440 return '%(type)s%(name)s' % { | |
| 441 'type': type_, | |
| 442 'name': name | |
| 443 } | |
| 444 | |
| 445 def _GenerateFunctionSignature(self, function, prepend_this=False): | |
| 446 """Given a function object, returns the signature for that function. | |
| 447 Recursively generates the signature for callbacks. | |
| 448 Returns a String for the given function. | |
| 449 | |
| 450 If prepend_this is True, adds "this." to the function's name. | |
| 451 | |
| 452 e.g. | |
| 453 void onClosed() | |
| 454 bool isOpen([String type]) | |
| 455 void doSomething(bool x, void callback([String x])) | |
| 456 | |
| 457 e.g. If prepend_this is True: | |
| 458 void this.onClosed() | |
| 459 bool this.isOpen([String type]) | |
| 460 void this.doSomething(bool x, void callback([String x])) | |
| 461 """ | |
| 462 sig = '%(return_type)s %(name)s(%(params)s)' | |
| 463 | |
| 464 # Get function return type. | |
| 465 if function.returns: | |
| 466 return_type = self._GetPropertyType(function.returns) | |
| 467 else: | |
| 468 return_type = 'void' | |
| 469 | |
| 470 # Get function name. | |
| 
not at google - send to devlin
2013/01/29 16:37:08
comment here and above seems unnecessary
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 471 function_name = function.simple_name | |
| 472 if prepend_this: | |
| 473 function_name = 'this.' + function_name | |
| 
not at google - send to devlin
2013/01/29 16:37:08
use 'this.%s' % function_name rather than string c
 
sashab
2013/01/30 05:26:03
No longer used, but note taken.
 | |
| 474 | |
| 475 return sig % { | |
| 476 'return_type': return_type, | |
| 477 'name': function_name, | |
| 478 'params': self._GenerateParameterList(function.params, | |
| 479 getattr(function, 'callback', None)) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
getattr/reflection shouldn't be necessary, if ther
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 480 } | |
| 481 | |
| 482 def _GenerateParameterList(self, params, callback=None, | |
| 483 allow_optional=True): | |
| 484 """Given a list of function parameters, generates their signature (as a | |
| 485 string). | |
| 486 | |
| 487 e.g. | |
| 488 [String type] | |
| 489 bool x, void callback([String x]) | |
| 490 | |
| 491 If allow_optional is False, ignores optional parameters. Useful for | |
| 492 callbacks, where optional parameters are not used. | |
| 493 """ | |
| 494 # params lists (required & optional), to be joined with ,'s | |
| 495 # FIXME(sashab): assuming all optional params come after required ones | |
| 496 params_req = [] | |
| 497 params_opt = [] | |
| 498 for param in params: | |
| 499 p_sig = self._GeneratePropertySignature(param) | |
| 500 if allow_optional and param.optional: | |
| 501 params_opt.append(p_sig) | |
| 502 else: | |
| 503 params_req.append(p_sig) | |
| 504 | |
| 505 # Add the callback, if it exists. | |
| 506 if callback: | |
| 507 c_sig = self._GenerateFunctionSignature(callback) | |
| 508 if callback.optional: | |
| 509 params_opt.append(c_sig) | |
| 510 else: | |
| 511 params_req.append(c_sig) | |
| 512 | |
| 513 # join params | |
| 
not at google - send to devlin
2013/01/29 16:37:08
comment doesn't look right, also, can this all be
 
sashab
2013/01/30 05:26:03
Fixed comment.
Optional parameters have to be in
 | |
| 514 params = '' | |
| 515 if params_req: | |
| 516 params += ', '.join(params_req) | |
| 517 if params_opt: | |
| 518 params += ', ' | |
| 519 if params_opt: | |
| 520 params += '[' + ', '.join(params_opt) + ']' | |
| 521 | |
| 522 return params | |
| 523 | |
| 524 def _GetNamespace(self, name): | |
| 525 """Given a name a.b.c, returns the namespace (in this case, a.b). | |
| 526 """ | |
| 527 return name.rsplit('.', 1)[0] | |
| 528 | |
| 529 def _GetBaseName(self, name): | |
| 530 """Given a name a.b.c, returns the base name of the path (in this case, c). | |
| 531 """ | |
| 532 return name.rsplit('.', 1)[1] | |
| 
not at google - send to devlin
2013/01/29 16:37:08
I think there are utils for this nand GetNamespace
 
sashab
2013/01/30 05:26:03
Removed; replaced usages with the ones from schema
 | |
| 533 | |
| 534 def _IsFunction(self, prop): | |
| 535 """Given a model.Property, returns whether this type is a function. | |
| 536 """ | |
| 537 return prop.type_.property_type == PropertyType.FUNCTION | |
| 538 | |
| 539 def _IsObjectType(self, prop): | |
| 540 """Given a model.Property, returns whether this type is an object. | |
| 541 """ | |
| 542 return (prop.type_.property_type == PropertyType.OBJECT or | |
| 543 prop.type_.property_type == PropertyType.ANY) | |
| 
not at google - send to devlin
2013/01/29 16:37:08
return prop.type_.property_name in [PropertyType.O
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 544 | |
| 545 def _IsBaseType(self, prop): | |
| 546 """Given a model.Property, returns whether this type is a base type | |
| 547 (string, number or boolean). | |
| 548 """ | |
| 549 base_type = self._GetPropertyType(prop) | |
| 550 if base_type in ['bool', 'num', 'int', 'double', 'String']: | |
| 551 return True | |
| 552 return False | |
| 
not at google - send to devlin
2013/01/29 16:37:08
return self._GetPropertyType(prop) in ['bool', 'nu
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 553 | |
| 554 def _GetReferencedType(self, name): | |
| 555 """Given the name of a referenced type, returns the type object for that | |
| 
not at google - send to devlin
2013/01/29 16:37:08
unused?
 
sashab
2013/01/30 05:26:03
Removed.
 | |
| 556 reference. | |
| 557 | |
| 558 Returns None if the type is not found. | |
| 559 """ | |
| 560 if name in self._namespace.types: | |
| 561 return self._namespace.types[name] | |
| 562 return None | |
| 563 | |
| 564 def _GetPropertyType(self, prop): | |
| 565 """Given a model.Property object, returns its type as a Dart string. | |
| 566 """ | |
| 567 if prop == None: | |
| 
not at google - send to devlin
2013/01/29 16:37:08
is None
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 568 return 'void' | |
| 569 | |
| 570 dart_type = None | |
| 571 type_ = prop.type_.property_type | |
| 572 | |
| 573 if type_ == None: | |
| 
not at google - send to devlin
2013/01/29 16:37:08
for all comparisons here, use "is" not ==
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 574 dart_type = 'void' | |
| 575 elif type_ == PropertyType.REF: | |
| 576 if self._GetNamespace(prop.type_.ref_type) == self._namespace.name: | |
| 577 # This type is in this namespace; just use its base name. | |
| 578 dart_type = self._GetBaseName(prop.type_.ref_type) | |
| 579 else: | |
| 580 # TODO(sashab): Work out how to import this foreign type. | |
| 581 dart_type = prop.type_.ref_type | |
| 582 elif type_ == PropertyType.BOOLEAN: | |
| 583 dart_type = 'bool' | |
| 
not at google - send to devlin
2013/01/29 16:37:08
return 'bool'
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 584 elif type_ == PropertyType.INTEGER: | |
| 585 dart_type = 'int' | |
| 
not at google - send to devlin
2013/01/29 16:37:08
return 'int'
(etc)
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 586 elif type_ == PropertyType.INT64: | |
| 587 dart_type = 'num' | |
| 588 elif type_ == PropertyType.DOUBLE: | |
| 589 dart_type = 'double' | |
| 590 elif type_ == PropertyType.STRING: | |
| 591 dart_type = 'String' | |
| 592 elif type_ == PropertyType.ENUM: | |
| 593 dart_type = 'String' | |
| 594 elif type_ == PropertyType.CHOICES: | |
| 595 # TODO(sashab): What is Choices? Is it closer to a Map? | |
| 
not at google - send to devlin
2013/01/29 16:37:08
who are you asking?
 
sashab
2013/01/30 05:26:03
Anyone who knows? ^^
What is the Dart equivalent
 
not at google - send to devlin
2013/01/31 02:08:48
Heh. I was just making sure you weren't asking me
 
sashab
2013/01/31 04:41:40
Object will support all types, but obviously stric
 | |
| 596 dart_type = 'Object' | |
| 597 elif type_ == PropertyType.ANY: | |
| 598 dart_type = 'Object' | |
| 599 elif type_ == PropertyType.OBJECT: | |
| 600 # TODO(sashab): Work out a mapped type name? | |
| 
not at google - send to devlin
2013/01/29 16:37:08
who are you asking?
 
sashab
2013/01/30 05:26:03
That was directed at myself; not sure what to do h
 
not at google - send to devlin
2013/01/31 02:08:48
uninformed idea: could you just not generate type
 
sashab
2013/01/31 04:41:40
Yes, that's why its "Object" if it can't figure ou
 
not at google - send to devlin
2013/02/02 00:45:47
Yep, I get that - but I presume ultimately that th
 
sashab
2013/02/04 05:09:27
Ohhhh right, I understand what you're saying now.
 | |
| 601 dart_type = prop.type_.instance_of or 'Object' | |
| 
not at google - send to devlin
2013/02/02 00:45:47
^^^
That said you could also generate for choices
 
sashab
2013/02/04 05:09:27
This is a great idea. Let me talk this over with t
 | |
| 602 elif type_ == PropertyType.FUNCTION: | |
| 603 dart_type = 'Function' | |
| 604 elif type_ == PropertyType.ARRAY: | |
| 605 if hasattr(prop, 'item_type'): | |
| 
not at google - send to devlin
2013/01/29 16:37:08
if it's an ARRAY it will always have an item_type,
 
sashab
2013/01/30 05:26:03
Done.
 | |
| 606 container_type = self._GetPropertyType(prop.item_type) | |
| 607 dart_type = 'List<%s>' % container_type | |
| 608 else: | |
| 609 dart_type = 'List' | |
| 610 elif type_ == PropertyType.BINARY: | |
| 611 dart_type = 'String' | |
| 612 else: | |
| 613 raise NotImplementedError(type_) | |
| 614 | |
| 615 return dart_type.strip() | |
| 
not at google - send to devlin
2013/01/29 16:37:08
why do you need to .strip()?
 
sashab
2013/01/30 05:26:03
Old fix; removed.
 | |
| OLD | NEW |