OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module generates Dart APIs from the IDL database.""" | 6 """This module generates Dart APIs from the IDL database.""" |
7 | 7 |
8 import emitter | 8 import emitter |
9 import idlnode | 9 import idlnode |
10 import logging | 10 import logging |
11 import multiemitter | 11 import multiemitter |
12 import os | 12 import os |
13 import re | 13 import re |
14 import shutil | 14 import shutil |
| 15 from generator import * |
| 16 from systembase import * |
| 17 from systemfrog import * |
| 18 from systemhtml import * |
| 19 from systeminterface import * |
15 | 20 |
16 _logger = logging.getLogger('dartgenerator') | 21 _logger = logging.getLogger('dartgenerator') |
17 | 22 |
18 # IDL->Dart primitive types conversion. | |
19 _idl_to_dart_type_conversions = { | |
20 'any': 'Object', | |
21 'any[]': 'List', | |
22 'custom': 'Dynamic', | |
23 'boolean': 'bool', | |
24 'DOMObject': 'Object', | |
25 'DOMString': 'String', | |
26 'DOMStringList': 'List<String>', | |
27 'DOMTimeStamp': 'int', | |
28 'Date': 'Date', | |
29 # Map to num to enable callers to pass in Dart int, rational | |
30 # types. Our implementations will need to convert these to | |
31 # doubles or floats as needed. | |
32 'double': 'num', | |
33 'float': 'num', | |
34 'int': 'int', | |
35 # Map to extra precision - int is a bignum in Dart. | |
36 'long': 'int', | |
37 'long long': 'int', | |
38 'object': 'Object', | |
39 # Map to extra precision - int is a bignum in Dart. | |
40 'short': 'int', | |
41 'string': 'String', | |
42 'void': 'void', | |
43 'Array': 'List', | |
44 'sequence': 'List', | |
45 # TODO(sra): Come up with some meaningful name so that where this appears in | |
46 # the documentation, the user is made aware that only a limited subset of | |
47 # serializable types are actually permitted. | |
48 'SerializedScriptValue': 'Dynamic', | |
49 # TODO(vsm): Automatically recognize types defined in src. | |
50 'TimeoutHandler': 'TimeoutHandler', | |
51 'RequestAnimationFrameCallback': 'RequestAnimationFrameCallback', | |
52 | |
53 # TODO(sra): Flags is really a dictionary: {create:bool, exclusive:bool} | |
54 # http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#the-flags-interfa
ce | |
55 'WebKitFlags': 'Object', | |
56 } | |
57 | |
58 _dart_to_idl_type_conversions = dict((v,k) for k, v in | |
59 _idl_to_dart_type_conversions.iteritems()) | |
60 | |
61 | |
62 # | |
63 # Identifiers that are used in the IDL than need to be treated specially because | |
64 # *some* JavaScript processors forbid them as properties. | |
65 # | |
66 _javascript_keywords = ['delete', 'continue'] | |
67 | |
68 # | |
69 # Interface version of the DOM needs to delegate typed array constructors to a | |
70 # factory provider. | |
71 # | |
72 _interface_factories = { | |
73 'Float32Array': '_TypedArrayFactoryProvider', | |
74 'Float64Array': '_TypedArrayFactoryProvider', | |
75 'Int8Array': '_TypedArrayFactoryProvider', | |
76 'Int16Array': '_TypedArrayFactoryProvider', | |
77 'Int32Array': '_TypedArrayFactoryProvider', | |
78 'Uint8Array': '_TypedArrayFactoryProvider', | |
79 'Uint16Array': '_TypedArrayFactoryProvider', | |
80 'Uint32Array': '_TypedArrayFactoryProvider', | |
81 'Uint8ClampedArray': '_TypedArrayFactoryProvider', | |
82 } | |
83 | |
84 # | |
85 # Custom methods that must be implemented by hand. | |
86 # | |
87 _custom_methods = set([ | |
88 ('DOMWindow', 'setInterval'), | |
89 ('DOMWindow', 'setTimeout'), | |
90 ('WorkerContext', 'setInterval'), | |
91 ('WorkerContext', 'setTimeout'), | |
92 ('CanvasRenderingContext2D', 'setFillStyle'), | |
93 ('CanvasRenderingContext2D', 'setStrokeStyle'), | |
94 ('CanvasRenderingContext2D', 'setFillStyle'), | |
95 ]) | |
96 | |
97 # | |
98 # Custom getters that must be implemented by hand. | |
99 # | |
100 _custom_getters = set([ | |
101 ('DOMWindow', 'localStorage'), | |
102 ]) | |
103 | |
104 # | |
105 # Custom native specs for the Frog dom. | |
106 # | |
107 _frog_dom_custom_native_specs = { | |
108 # Decorate the singleton Console object, if present (workers do not have a | |
109 # console). | |
110 'Console': "=(typeof console == 'undefined' ? {} : console)", | |
111 | |
112 # DOMWindow aliased with global scope. | |
113 'DOMWindow': '@*DOMWindow', | |
114 } | |
115 | |
116 # | |
117 # Simple method substitution when one method had different names on different | |
118 # browsers, but are otherwise identical. The alternates are tried in order and | |
119 # the first one defined is used. | |
120 # | |
121 # This can be probably be removed when Chrome renames initWebKitWheelEvent to | |
122 # initWheelEvent. | |
123 # | |
124 _alternate_methods = { | |
125 ('WheelEvent', 'initWheelEvent'): ['initWebKitWheelEvent', 'initWheelEvent'] | |
126 } | |
127 | |
128 | |
129 def _MatchSourceFilter(filter, thing): | |
130 if not filter: | |
131 return True | |
132 else: | |
133 return any(token in thing.annotations for token in filter) | |
134 | |
135 def _IsDartListType(type): | |
136 return type == 'List' or type.startswith('List<') | |
137 | |
138 def _IsDartCollectionType(type): | |
139 return _IsDartListType(type) | |
140 | |
141 | |
142 class DartGenerator(object): | 23 class DartGenerator(object): |
143 """Utilities to generate Dart APIs and corresponding JavaScript.""" | 24 """Utilities to generate Dart APIs and corresponding JavaScript.""" |
144 | 25 |
145 def __init__(self, auxiliary_dir, template_dir, base_package): | 26 def __init__(self, auxiliary_dir, template_dir, base_package): |
146 """Constructor for the DartGenerator. | 27 """Constructor for the DartGenerator. |
147 | 28 |
148 Args: | 29 Args: |
149 auxiliary_dir -- location of auxiliary handwritten classes | 30 auxiliary_dir -- location of auxiliary handwritten classes |
150 template_dir -- location of template files | 31 template_dir -- location of template files |
151 base_package -- the base package name for the generated code. | 32 base_package -- the base package name for the generated code. |
152 """ | 33 """ |
153 self._auxiliary_dir = auxiliary_dir | 34 self._auxiliary_dir = auxiliary_dir |
154 self._template_dir = template_dir | 35 self._template_dir = template_dir |
155 self._base_package = base_package | 36 self._base_package = base_package |
156 self._auxiliary_files = {} | 37 self._auxiliary_files = {} |
157 self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>') | 38 self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>') |
158 | 39 |
159 self._emitters = None # set later | 40 self._emitters = None # set later |
160 | 41 |
161 | 42 |
162 def _StripModules(self, type_name): | 43 def _StripModules(self, type_name): |
163 return type_name.split('::')[-1] | 44 return type_name.split('::')[-1] |
164 | 45 |
165 def _IsPrimitiveType(self, type_name): | |
166 return (self._ConvertPrimitiveType(type_name) is not None or | |
167 type_name in _dart_to_idl_type_conversions) | |
168 | |
169 def _IsCompoundType(self, database, type_name): | 46 def _IsCompoundType(self, database, type_name): |
170 if self._IsPrimitiveType(type_name): | 47 if IsPrimitiveType(type_name): |
171 return True | 48 return True |
172 | 49 |
173 striped_type_name = self._StripModules(type_name) | 50 striped_type_name = self._StripModules(type_name) |
174 if database.HasInterface(striped_type_name): | 51 if database.HasInterface(striped_type_name): |
175 return True | 52 return True |
176 | 53 |
177 dart_template_match = self._dart_templates_re.match(type_name) | 54 dart_template_match = self._dart_templates_re.match(type_name) |
178 if dart_template_match: | 55 if dart_template_match: |
179 # Dart templates | 56 # Dart templates |
180 parent_type_name = type_name[0 : dart_template_match.start(1) - 1] | 57 parent_type_name = type_name[0 : dart_template_match.start(1) - 1] |
181 sub_type_name = dart_template_match.group(1) | 58 sub_type_name = dart_template_match.group(1) |
182 return (self._IsCompoundType(database, parent_type_name) and | 59 return (self._IsCompoundType(database, parent_type_name) and |
183 self._IsCompoundType(database, sub_type_name)) | 60 self._IsCompoundType(database, sub_type_name)) |
184 return False | 61 return False |
185 | 62 |
186 def _IsDartType(self, type_name): | 63 def _IsDartType(self, type_name): |
187 return '.' in type_name | 64 return '.' in type_name |
188 | 65 |
189 def _ConvertPrimitiveType(self, type_name): | |
190 if type_name.startswith('unsigned '): | |
191 type_name = type_name[len('unsigned '):] | |
192 | |
193 if type_name in _idl_to_dart_type_conversions: | |
194 # Primitive type conversion | |
195 return _idl_to_dart_type_conversions[type_name] | |
196 return None | |
197 | |
198 def LoadAuxiliary(self): | 66 def LoadAuxiliary(self): |
199 def Visitor(_, dirname, names): | 67 def Visitor(_, dirname, names): |
200 for name in names: | 68 for name in names: |
201 if name.endswith('.dart'): | 69 if name.endswith('.dart'): |
202 name = name[0:-5] # strip off ".dart" | 70 name = name[0:-5] # strip off ".dart" |
203 self._auxiliary_files[name] = os.path.join(dirname, name) | 71 self._auxiliary_files[name] = os.path.join(dirname, name) |
204 os.path.walk(self._auxiliary_dir, Visitor, None) | 72 os.path.walk(self._auxiliary_dir, Visitor, None) |
205 | 73 |
206 def RenameTypes(self, database, conversion_table=None): | 74 def RenameTypes(self, database, conversion_table, rename_javascript_binding_na
mes): |
207 """Renames interfaces using the given conversion table. | 75 """Renames interfaces using the given conversion table. |
208 | 76 |
209 References through all interfaces will be renamed as well. | 77 References through all interfaces will be renamed as well. |
210 | 78 |
211 Args: | 79 Args: |
212 database: the database to apply the renames to. | 80 database: the database to apply the renames to. |
213 conversion_table: maps old names to new names. | 81 conversion_table: maps old names to new names. |
214 """ | 82 """ |
215 | 83 |
216 if conversion_table is None: | 84 if conversion_table is None: |
217 conversion_table = {} | 85 conversion_table = {} |
218 | 86 |
219 # Rename interfaces: | 87 # Rename interfaces: |
220 for old_name, new_name in conversion_table.items(): | 88 for old_name, new_name in conversion_table.items(): |
221 if database.HasInterface(old_name): | 89 if database.HasInterface(old_name): |
222 _logger.info('renaming interface %s to %s' % | 90 _logger.info('renaming interface %s to %s' % (old_name, new_name)) |
223 (old_name, new_name)) | |
224 interface = database.GetInterface(old_name) | 91 interface = database.GetInterface(old_name) |
225 database.DeleteInterface(old_name) | 92 database.DeleteInterface(old_name) |
226 if not database.HasInterface(new_name): | 93 if not database.HasInterface(new_name): |
227 interface.id = new_name | 94 interface.id = new_name |
228 database.AddInterface(interface) | 95 database.AddInterface(interface) |
229 | 96 else: |
| 97 new_interface = database.GetInterface(new_name) |
| 98 new_interface.merge(interface) |
| 99 |
| 100 interface.javascript_binding_name = (old_name if rename_javascript_bindi
ng_names |
| 101 else new_name) |
| 102 |
230 # Fix references: | 103 # Fix references: |
231 for interface in database.GetInterfaces(): | 104 for interface in database.GetInterfaces(): |
232 for idl_type in interface.all(idlnode.IDLType): | 105 for idl_type in interface.all(idlnode.IDLType): |
233 type_name = self._StripModules(idl_type.id) | 106 type_name = self._StripModules(idl_type.id) |
234 if type_name in conversion_table: | 107 if type_name in conversion_table: |
235 idl_type.id = conversion_table[type_name] | 108 idl_type.id = conversion_table[type_name] |
236 | 109 |
237 def FilterMembersWithUnidentifiedTypes(self, database): | 110 def FilterMembersWithUnidentifiedTypes(self, database): |
238 """Removes unidentified types. | 111 """Removes unidentified types. |
239 | 112 |
(...skipping 18 matching lines...) Expand all Loading... |
258 interface.attributes = filter(IsIdentified, interface.attributes) | 131 interface.attributes = filter(IsIdentified, interface.attributes) |
259 interface.operations = filter(IsIdentified, interface.operations) | 132 interface.operations = filter(IsIdentified, interface.operations) |
260 interface.parents = filter(IsIdentified, interface.parents) | 133 interface.parents = filter(IsIdentified, interface.parents) |
261 | 134 |
262 def ConvertToDartTypes(self, database): | 135 def ConvertToDartTypes(self, database): |
263 """Converts all IDL types to Dart primitives or qualified types""" | 136 """Converts all IDL types to Dart primitives or qualified types""" |
264 | 137 |
265 def ConvertType(interface, type_name): | 138 def ConvertType(interface, type_name): |
266 """Helper method for converting a type name to the proper | 139 """Helper method for converting a type name to the proper |
267 Dart name""" | 140 Dart name""" |
268 if self._IsPrimitiveType(type_name): | 141 if IsPrimitiveType(type_name): |
269 return self._ConvertPrimitiveType(type_name) | 142 return ConvertPrimitiveType(type_name) |
270 | 143 |
271 if self._IsDartType(type_name): | 144 if self._IsDartType(type_name): |
272 # This is for when dart qualified names are explicitly | 145 # This is for when dart qualified names are explicitly |
273 # defined in the IDLs. Just let them be. | 146 # defined in the IDLs. Just let them be. |
274 return type_name | 147 return type_name |
275 | 148 |
276 dart_template_match = self._dart_templates_re.match(type_name) | 149 dart_template_match = self._dart_templates_re.match(type_name) |
277 if dart_template_match: | 150 if dart_template_match: |
278 # Dart templates | 151 # Dart templates |
279 parent_type_name = type_name[0 : dart_template_match.start(1) - 1] | 152 parent_type_name = type_name[0 : dart_template_match.start(1) - 1] |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 interface.parents = filter(HasAnnotations, interface.parents) | 221 interface.parents = filter(HasAnnotations, interface.parents) |
349 else: | 222 else: |
350 database.DeleteInterface(interface.id) | 223 database.DeleteInterface(interface.id) |
351 | 224 |
352 self.FilterMembersWithUnidentifiedTypes(database) | 225 self.FilterMembersWithUnidentifiedTypes(database) |
353 | 226 |
354 | 227 |
355 def Generate(self, database, output_dir, | 228 def Generate(self, database, output_dir, |
356 module_source_preference=[], source_filter=None, | 229 module_source_preference=[], source_filter=None, |
357 super_database=None, common_prefix=None, super_map={}, | 230 super_database=None, common_prefix=None, super_map={}, |
358 lib_dir=None, systems=[]): | 231 html_map={}, lib_dir=None, systems=[]): |
359 """Generates Dart and JS files for the loaded interfaces. | 232 """Generates Dart and JS files for the loaded interfaces. |
360 | 233 |
361 Args: | 234 Args: |
362 database -- database containing interfaces to generate code for. | 235 database -- database containing interfaces to generate code for. |
363 output_dir -- directory to write generated files to. | 236 output_dir -- directory to write generated files to. |
364 module_source_preference -- priority order list of source annotations to | 237 module_source_preference -- priority order list of source annotations to |
365 use when choosing a module name, if none specified uses the module name | 238 use when choosing a module name, if none specified uses the module name |
366 from the database. | 239 from the database. |
367 source_filter -- if specified, only outputs interfaces that have one of | 240 source_filter -- if specified, only outputs interfaces that have one of |
368 these source annotation and rewrites the names of superclasses not | 241 these source annotation and rewrites the names of superclasses not |
369 marked with this source to use the common prefix. | 242 marked with this source to use the common prefix. |
370 super_database -- database containing super interfaces that the generated | 243 super_database -- database containing super interfaces that the generated |
371 interfaces should extend. | 244 interfaces should extend. |
372 common_prefix -- prefix for the common library, if any. | 245 common_prefix -- prefix for the common library, if any. |
373 lib_file_path -- filename for generated .lib file, None if not required. | 246 lib_file_path -- filename for generated .lib file, None if not required. |
374 lib_template -- template file in this directory for generated lib file. | 247 lib_template -- template file in this directory for generated lib file. |
375 """ | 248 """ |
376 | 249 |
377 self._emitters = multiemitter.MultiEmitter() | 250 self._emitters = multiemitter.MultiEmitter() |
378 self._database = database | 251 self._database = database |
379 self._output_dir = output_dir | 252 self._output_dir = output_dir |
380 | 253 |
381 self._ComputeInheritanceClosure() | 254 self._ComputeInheritanceClosure() |
382 | 255 |
383 self._systems = [] | 256 self._systems = [] |
384 | 257 |
385 # TODO(jmesserly): only create these if needed | 258 # TODO(jmesserly): only create these if needed |
386 interface_system = InterfacesSystem( | 259 if ('htmlfrog' in systems) or ('htmldartium' in systems): |
387 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | 260 html_interface_system = HtmlInterfacesSystem( |
388 self._database, self._emitters, self._output_dir) | 261 TemplateLoader(self._template_dir, ['html/interface', 'html', '']), |
389 self._systems.append(interface_system) | 262 self._database, self._emitters, self._output_dir, self) |
390 | 263 self._systems.append(html_interface_system) |
391 html_interface_system = HtmlInterfacesSystem( | 264 else: |
392 TemplateLoader(self._template_dir, ['html/interface', 'html', '']), | 265 interface_system = InterfacesSystem( |
393 self._database, self._emitters, self._output_dir) | 266 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), |
394 self._systems.append(html_interface_system) | 267 self._database, self._emitters, self._output_dir) |
| 268 self._systems.append(interface_system) |
395 | 269 |
396 if 'native' in systems: | 270 if 'native' in systems: |
397 native_system = NativeImplementationSystem( | 271 native_system = NativeImplementationSystem( |
398 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']), | 272 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']), |
399 self._database, self._emitters, self._auxiliary_dir, | 273 self._database, self._emitters, self._auxiliary_dir, |
400 self._output_dir) | 274 self._output_dir) |
401 | 275 |
402 self._systems.append(native_system) | 276 self._systems.append(native_system) |
403 | 277 |
404 if 'wrapping' in systems: | 278 if 'wrapping' in systems: |
(...skipping 20 matching lines...) Expand all Loading... |
425 frog_system = FrogSystem( | 299 frog_system = FrogSystem( |
426 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), | 300 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), |
427 self._database, self._emitters, self._output_dir) | 301 self._database, self._emitters, self._output_dir) |
428 | 302 |
429 frog_system._interface_system = interface_system | 303 frog_system._interface_system = interface_system |
430 self._systems.append(frog_system) | 304 self._systems.append(frog_system) |
431 | 305 |
432 if 'htmlfrog' in systems: | 306 if 'htmlfrog' in systems: |
433 html_system = HtmlFrogSystem( | 307 html_system = HtmlFrogSystem( |
434 TemplateLoader(self._template_dir, ['html/frog', 'html', '']), | 308 TemplateLoader(self._template_dir, ['html/frog', 'html', '']), |
435 self._database, self._emitters, self._output_dir) | 309 self._database, self._emitters, self._output_dir, self) |
436 | 310 |
437 html_system._interface_system = html_interface_system | 311 html_system._interface_system = html_interface_system |
438 self._systems.append(html_system) | 312 self._systems.append(html_system) |
439 | 313 |
440 if 'htmldartium' in systems: | 314 if 'htmldartium' in systems: |
441 html_system = HtmlDartiumSystem( | 315 html_system = HtmlDartiumSystem( |
442 TemplateLoader(self._template_dir, ['html/dartium', 'html', '']), | 316 TemplateLoader(self._template_dir, ['html/dartium', 'html', '']), |
443 self._database, self._emitters, self._output_dir) | 317 self._database, self._emitters, self._output_dir, self) |
444 | 318 |
445 html_system._interface_system = html_interface_system | 319 html_system._interface_system = html_interface_system |
446 self._systems.append(html_system) | 320 self._systems.append(html_system) |
447 | 321 |
448 # Collect interfaces | 322 # Collect interfaces |
449 interfaces = [] | 323 interfaces = [] |
450 for interface in database.GetInterfaces(): | 324 for interface in database.GetInterfaces(): |
451 if not _MatchSourceFilter(source_filter, interface): | 325 if not MatchSourceFilter(source_filter, interface): |
452 # Skip this interface since it's not present in the required source | 326 # Skip this interface since it's not present in the required source |
453 _logger.info('Omitting interface - %s' % interface.id) | 327 _logger.info('Omitting interface - %s' % interface.id) |
454 continue | 328 continue |
455 interfaces.append(interface) | 329 interfaces.append(interface) |
456 | 330 |
457 # TODO(sra): Use this list of exception names to generate information to | 331 # TODO(sra): Use this list of exception names to generate information to |
458 # tell Frog which exceptions can be passed from JS to Dart code. | 332 # tell Frog which exceptions can be passed from JS to Dart code. |
459 exceptions = self._CollectExceptions(interfaces) | 333 exceptions = self._CollectExceptions(interfaces) |
460 | 334 |
461 # Render all interfaces into Dart and save them in files. | 335 # Render all interfaces into Dart and save them in files. |
462 for interface in self._PreOrderInterfaces(interfaces): | 336 for interface in self._PreOrderInterfaces(interfaces): |
463 | 337 |
464 super_interface = None | 338 super_interface = None |
465 super_name = interface.id | 339 super_name = interface.id |
466 | 340 |
467 if super_name in super_map: | 341 if super_name in super_map: |
468 super_name = super_map[super_name] | 342 super_name = super_map[super_name] |
469 | 343 |
470 if (super_database is not None and | 344 if (super_database is not None and |
471 super_database.HasInterface(super_name)): | 345 super_database.HasInterface(super_name)): |
472 super_interface = super_name | 346 super_interface = super_name |
473 | 347 |
474 interface_name = interface.id | 348 interface_name = interface.id |
475 auxiliary_file = self._auxiliary_files.get(interface_name) | 349 auxiliary_file = self._auxiliary_files.get(interface_name) |
476 if auxiliary_file is not None: | 350 if auxiliary_file is not None: |
477 _logger.info('Skipping %s because %s exists' % ( | 351 _logger.info('Skipping %s because %s exists' % ( |
478 interface_name, auxiliary_file)) | 352 interface_name, auxiliary_file)) |
479 continue | 353 continue |
480 | 354 |
481 info = _RecognizeCallback(interface) | 355 info = RecognizeCallback(interface) |
482 if info: | 356 if info: |
483 for system in self._systems: | 357 for system in self._systems: |
484 system.ProcessCallback(interface, info) | 358 system.ProcessCallback(interface, info) |
485 else: | 359 else: |
486 if 'Callback' in interface.ext_attrs: | 360 if 'Callback' in interface.ext_attrs: |
487 _logger.info('Malformed callback: %s' % interface.id) | 361 _logger.info('Malformed callback: %s' % interface.id) |
488 self._ProcessInterface(interface, super_interface, | 362 self._ProcessInterface(interface, super_interface, |
489 source_filter, common_prefix) | 363 source_filter, common_prefix) |
490 | 364 |
491 # Libraries | 365 # Libraries |
492 if lib_dir: | 366 if lib_dir: |
493 for system in self._systems: | 367 for system in self._systems: |
494 system.GenerateLibraries(lib_dir) | 368 system.GenerateLibraries(lib_dir) |
495 | 369 |
496 for system in self._systems: | 370 for system in self._systems: |
497 system.Finish() | 371 system.Finish() |
498 | 372 |
499 | 373 |
500 def _PreOrderInterfaces(self, interfaces): | 374 def _PreOrderInterfaces(self, interfaces): |
501 """Returns the interfaces in pre-order, i.e. parents first.""" | 375 """Returns the interfaces in pre-order, i.e. parents first.""" |
502 seen = set() | 376 seen = set() |
503 ordered = [] | 377 ordered = [] |
504 def visit(interface): | 378 def visit(interface): |
505 if interface.id in seen: | 379 if interface.id in seen: |
506 return | 380 return |
507 seen.add(interface.id) | 381 seen.add(interface.id) |
508 for parent in interface.parents: | 382 for parent in interface.parents: |
509 if _IsDartCollectionType(parent.type.id): | 383 if IsDartCollectionType(parent.type.id): |
510 continue | 384 continue |
511 if self._database.HasInterface(parent.type.id): | 385 if self._database.HasInterface(parent.type.id): |
512 parent_interface = self._database.GetInterface(parent.type.id) | 386 parent_interface = self._database.GetInterface(parent.type.id) |
513 visit(parent_interface) | 387 visit(parent_interface) |
514 ordered.append(interface) | 388 ordered.append(interface) |
515 | 389 |
516 for interface in interfaces: | 390 for interface in interfaces: |
517 visit(interface) | 391 visit(interface) |
518 return ordered | 392 return ordered |
519 | 393 |
(...skipping 17 matching lines...) Expand all Loading... |
537 for const in sorted(interface.constants, ConstantOutputOrder): | 411 for const in sorted(interface.constants, ConstantOutputOrder): |
538 for generator in generators: | 412 for generator in generators: |
539 generator.AddConstant(const) | 413 generator.AddConstant(const) |
540 | 414 |
541 attributes = [attr for attr in interface.attributes | 415 attributes = [attr for attr in interface.attributes |
542 if not self._IsEventAttribute(interface, attr)] | 416 if not self._IsEventAttribute(interface, attr)] |
543 for (getter, setter) in _PairUpAttributes(attributes): | 417 for (getter, setter) in _PairUpAttributes(attributes): |
544 for generator in generators: | 418 for generator in generators: |
545 generator.AddAttribute(getter, setter) | 419 generator.AddAttribute(getter, setter) |
546 | 420 |
547 events = _PairUpAttributes([attr for attr in interface.attributes | 421 events = set([attr for attr in interface.attributes |
548 if self._IsEventAttribute(interface, attr)]) | 422 if self._IsEventAttribute(interface, attr)]) |
| 423 |
549 if events: | 424 if events: |
550 for generator in generators: | 425 for generator in generators: |
551 generator.AddEventAttributes(events) | 426 generator.AddEventAttributes(events) |
552 | 427 |
553 # The implementation should define an indexer if the interface directly | 428 # The implementation should define an indexer if the interface directly |
554 # extends List. | 429 # extends List. |
555 element_type = MaybeListElementType(interface) | 430 element_type = MaybeListElementType(interface) |
556 if element_type: | 431 if element_type: |
557 for generator in generators: | 432 for generator in generators: |
558 generator.AddIndexer(element_type) | 433 generator.AddIndexer(element_type) |
559 | |
560 # Group overloaded operations by id | 434 # Group overloaded operations by id |
561 operationsById = {} | 435 operationsById = {} |
562 for operation in interface.operations: | 436 for operation in interface.operations: |
563 if operation.id not in operationsById: | 437 if operation.id not in operationsById: |
564 operationsById[operation.id] = [] | 438 operationsById[operation.id] = [] |
565 operationsById[operation.id].append(operation) | 439 operationsById[operation.id].append(operation) |
566 | 440 |
567 # Generate operations | 441 # Generate operations |
568 for id in sorted(operationsById.keys()): | 442 for id in sorted(operationsById.keys()): |
569 operations = operationsById[id] | 443 operations = operationsById[id] |
570 info = _AnalyzeOperation(interface, operations) | 444 info = AnalyzeOperation(interface, operations) |
571 for generator in generators: | 445 for generator in generators: |
572 generator.AddOperation(info) | 446 generator.AddOperation(info) |
573 | 447 |
574 # With multiple inheritance, attributes and operations of non-first | 448 # With multiple inheritance, attributes and operations of non-first |
575 # interfaces need to be added. Sometimes the attribute or operation is | 449 # interfaces need to be added. Sometimes the attribute or operation is |
576 # defined in the current interface as well as a parent. In that case we | 450 # defined in the current interface as well as a parent. In that case we |
577 # avoid making a duplicate definition and pray that the signatures match. | 451 # avoid making a duplicate definition and pray that the signatures match. |
578 | 452 |
579 for parent_interface in self._TransitiveSecondaryParents(interface): | 453 for parent_interface in self._TransitiveSecondaryParents(interface): |
580 if isinstance(parent_interface, str): # _IsDartCollectionType(parent_inte
rface) | 454 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter
face) |
581 continue | 455 continue |
582 attributes = [attr for attr in parent_interface.attributes | 456 attributes = [attr for attr in parent_interface.attributes |
583 if not _FindMatchingAttribute(interface, attr)] | 457 if not FindMatchingAttribute(interface, attr)] |
584 for (getter, setter) in _PairUpAttributes(attributes): | 458 for (getter, setter) in _PairUpAttributes(attributes): |
585 for generator in generators: | 459 for generator in generators: |
586 generator.AddSecondaryAttribute(parent_interface, getter, setter) | 460 generator.AddSecondaryAttribute(parent_interface, getter, setter) |
587 | 461 |
588 # Group overloaded operations by id | 462 # Group overloaded operations by id |
589 operationsById = {} | 463 operationsById = {} |
590 for operation in parent_interface.operations: | 464 for operation in parent_interface.operations: |
591 if operation.id not in operationsById: | 465 if operation.id not in operationsById: |
592 operationsById[operation.id] = [] | 466 operationsById[operation.id] = [] |
593 operationsById[operation.id].append(operation) | 467 operationsById[operation.id].append(operation) |
594 | 468 |
595 # Generate operations | 469 # Generate operations |
596 for id in sorted(operationsById.keys()): | 470 for id in sorted(operationsById.keys()): |
597 if not any(op.id == id for op in interface.operations): | 471 if not any(op.id == id for op in interface.operations): |
598 operations = operationsById[id] | 472 operations = operationsById[id] |
599 info = _AnalyzeOperation(interface, operations) | 473 info = AnalyzeOperation(interface, operations) |
600 for generator in generators: | 474 for generator in generators: |
601 generator.AddSecondaryOperation(parent_interface, info) | 475 generator.AddSecondaryOperation(parent_interface, info) |
602 | 476 |
603 for generator in generators: | 477 for generator in generators: |
604 generator.FinishInterface() | 478 generator.FinishInterface() |
605 return | 479 return |
606 | 480 |
607 def _IsEventAttribute(self, interface, attr): | 481 def _IsEventAttribute(self, interface, attr): |
608 # Remove EventListener attributes like 'onclick' when addEventListener | 482 # Remove EventListener attributes like 'onclick' when addEventListener |
609 # is available. | 483 # is available. |
610 if attr.type.id == 'EventListener': | 484 return (attr.type.id == 'EventListener' and |
611 if 'EventTarget' in self._AllImplementedInterfaces(interface): | 485 'EventTarget' in self._AllImplementedInterfaces(interface)) |
612 return True | |
613 return False | |
614 | 486 |
615 def _TransitiveSecondaryParents(self, interface): | 487 def _TransitiveSecondaryParents(self, interface): |
616 """Returns a list of all non-primary parents. | 488 """Returns a list of all non-primary parents. |
617 | 489 |
618 The list contains the interface objects for interfaces defined in the | 490 The list contains the interface objects for interfaces defined in the |
619 database, and the name for undefined interfaces. | 491 database, and the name for undefined interfaces. |
620 """ | 492 """ |
621 def walk(parents): | 493 def walk(parents): |
622 for parent in parents: | 494 for parent in parents: |
623 if _IsDartCollectionType(parent.type.id): | 495 if IsDartCollectionType(parent.type.id): |
624 result.append(parent.type.id) | 496 result.append(parent.type.id) |
625 continue | 497 continue |
626 if self._database.HasInterface(parent.type.id): | 498 if self._database.HasInterface(parent.type.id): |
627 parent_interface = self._database.GetInterface(parent.type.id) | 499 parent_interface = self._database.GetInterface(parent.type.id) |
628 result.append(parent_interface) | 500 result.append(parent_interface) |
629 walk(parent_interface.parents) | 501 walk(parent_interface.parents) |
630 | 502 |
631 result = [] | 503 result = [] |
632 walk(interface.parents[1:]) | 504 walk(interface.parents[1:]) |
633 return result; | 505 return result; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 collected = [] | 548 collected = [] |
677 Collect(interface, seen, collected) | 549 Collect(interface, seen, collected) |
678 self._inheritance_closure[interface.id] = collected | 550 self._inheritance_closure[interface.id] = collected |
679 | 551 |
680 def _AllImplementedInterfaces(self, interface): | 552 def _AllImplementedInterfaces(self, interface): |
681 """Returns a list of the names of all interfaces implemented by 'interface'. | 553 """Returns a list of the names of all interfaces implemented by 'interface'. |
682 List includes the name of 'interface'. | 554 List includes the name of 'interface'. |
683 """ | 555 """ |
684 return self._inheritance_closure[interface.id] | 556 return self._inheritance_closure[interface.id] |
685 | 557 |
686 | |
687 def _RecognizeCallback(interface): | |
688 """Returns the info for the callback method if the interface smells like a | |
689 callback. | |
690 """ | |
691 if 'Callback' not in interface.ext_attrs: return None | |
692 handlers = [op for op in interface.operations if op.id == 'handleEvent'] | |
693 if not handlers: return None | |
694 if not (handlers == interface.operations): return None | |
695 return _AnalyzeOperation(interface, handlers) | |
696 | |
697 | |
698 def _PairUpAttributes(attributes): | 558 def _PairUpAttributes(attributes): |
699 """Returns a list of (getter, setter) pairs sorted by name. | 559 """Returns a list of (getter, setter) pairs sorted by name. |
700 | 560 |
701 One element of the pair may be None. | 561 One element of the pair may be None. |
702 """ | 562 """ |
703 names = sorted(set(attr.id for attr in attributes)) | 563 names = sorted(set(attr.id for attr in attributes)) |
704 getters = {} | 564 getters = {} |
705 setters = {} | 565 setters = {} |
706 for attr in attributes: | 566 for attr in attributes: |
707 if attr.is_fc_getter: | 567 if attr.is_fc_getter: |
708 getters[attr.id] = attr | 568 getters[attr.id] = attr |
709 elif attr.is_fc_setter and 'Replaceable' not in attr.ext_attrs: | 569 elif attr.is_fc_setter and 'Replaceable' not in attr.ext_attrs: |
710 setters[attr.id] = attr | 570 setters[attr.id] = attr |
711 return [(getters.get(id), setters.get(id)) for id in names] | 571 return [(getters.get(id), setters.get(id)) for id in names] |
712 | 572 |
713 | |
714 def _FindMatchingAttribute(interface, attr1): | |
715 matches = [attr2 for attr2 in interface.attributes | |
716 if attr1.id == attr2.id | |
717 and attr1.is_fc_getter == attr2.is_fc_getter | |
718 and attr1.is_fc_setter == attr2.is_fc_setter] | |
719 if matches: | |
720 assert len(matches) == 1 | |
721 return matches[0] | |
722 return None | |
723 | |
724 | |
725 def _AnalyzeOperation(interface, operations): | |
726 """Makes operation calling convention decision for a set of overloads. | |
727 | |
728 Returns: An OperationInfo object. | |
729 """ | |
730 | |
731 # Zip together arguments from each overload by position, then convert | |
732 # to a dart argument. | |
733 | |
734 # Given a list of overloaded arguments, choose a suitable name. | |
735 def OverloadedName(args): | |
736 return '_OR_'.join(sorted(set(arg.id for arg in args))) | |
737 | |
738 # Given a list of overloaded arguments, choose a suitable type. | |
739 def OverloadedType(args): | |
740 typeIds = sorted(set(arg.type.id for arg in args)) | |
741 if len(typeIds) == 1: | |
742 return typeIds[0] | |
743 else: | |
744 return TypeName(typeIds, interface) | |
745 | |
746 # Given a list of overloaded arguments, render a dart argument. | |
747 def DartArg(args): | |
748 filtered = filter(None, args) | |
749 optional = any(not arg or arg.is_optional for arg in args) | |
750 type = OverloadedType(filtered) | |
751 name = OverloadedName(filtered) | |
752 if optional: | |
753 return (name, type, 'null') | |
754 else: | |
755 return (name, type, None) | |
756 | |
757 args = map(lambda *args: DartArg(args), | |
758 *(op.arguments for op in operations)) | |
759 | |
760 info = OperationInfo() | |
761 info.overloads = operations | |
762 info.declared_name = operations[0].id | |
763 info.name = operations[0].ext_attrs.get('DartName', info.declared_name) | |
764 info.js_name = info.declared_name | |
765 info.type_name = operations[0].type.id # TODO: widen. | |
766 info.arg_infos = args | |
767 return info | |
768 | |
769 | |
770 class OperationInfo(object): | |
771 """Holder for various derived information from a set of overloaded operations. | |
772 | |
773 Attributes: | |
774 overloads: A list of IDL operation overloads with the same name. | |
775 name: A string, the simple name of the operation. | |
776 type_name: A string, the name of the return type of the operation. | |
777 arg_infos: A list of (name, type, default_value) tuples. | |
778 default_value is None for mandatory arguments. | |
779 """ | |
780 | |
781 def ParametersInterfaceDeclaration(self): | |
782 """Returns a formatted string declaring the parameters for the interface.""" | |
783 return self._FormatArgs(self.arg_infos, True) | |
784 | |
785 def ParametersImplementationDeclaration(self, rename_type=None): | |
786 """Returns a formatted string declaring the parameters for the | |
787 implementation. | |
788 | |
789 Args: | |
790 rename_type: A function that allows the types to be renamed. | |
791 """ | |
792 args = self.arg_infos | |
793 if rename_type: | |
794 args = [(name, rename_type(type), default) | |
795 for (name, type, default) in args] | |
796 return self._FormatArgs(args, False) | |
797 | |
798 | |
799 def _FormatArgs(self, args, is_interface): | |
800 def FormatArg(arg_info): | |
801 """Returns an argument declaration fragment for an argument info tuple.""" | |
802 (name, type, default) = arg_info | |
803 if default: | |
804 return '%s %s = %s' % (type, name, default) | |
805 else: | |
806 return '%s %s' % (type, name) | |
807 | |
808 required = [] | |
809 optional = [] | |
810 for (name, type, default) in args: | |
811 if default: | |
812 if is_interface: | |
813 optional.append((name, type, None)) # Default values illegal. | |
814 else: | |
815 optional.append((name, type, default)) | |
816 else: | |
817 if optional: | |
818 raise Exception('Optional arguments cannot precede required ones: ' | |
819 + str(args)) | |
820 required.append((name, type, None)) | |
821 argtexts = map(FormatArg, required) | |
822 if optional: | |
823 argtexts.append('[' + ', '.join(map(FormatArg, optional)) + ']') | |
824 return ', '.join(argtexts) | |
825 | |
826 | |
827 def MaybeListElementTypeName(type_name): | |
828 """Returns the List element type T from string of form "List<T>", or None.""" | |
829 match = re.match(r'List<(\w*)>$', type_name) | |
830 if match: | |
831 return match.group(1) | |
832 return None | |
833 | |
834 def MaybeListElementType(interface): | |
835 """Returns the List element type T, or None in interface does not implement | |
836 List<T>. | |
837 """ | |
838 for parent in interface.parents: | |
839 element_type = MaybeListElementTypeName(parent.type.id) | |
840 if element_type: | |
841 return element_type | |
842 return None | |
843 | |
844 def MaybeTypedArrayElementType(interface): | |
845 """Returns the typed array element type, or None in interface is not a | |
846 TypedArray. | |
847 """ | |
848 # Typed arrays implement ArrayBufferView and List<T>. | |
849 for parent in interface.parents: | |
850 if parent.type.id == 'ArrayBufferView': | |
851 return MaybeListElementType(interface) | |
852 if parent.type.id == 'Uint8Array': | |
853 return 'int' | |
854 return None | |
855 | |
856 | |
857 def AttributeOutputOrder(a, b): | |
858 """Canonical output ordering for attributes.""" | |
859 # Getters before setters: | |
860 if a.id < b.id: return -1 | |
861 if a.id > b.id: return 1 | |
862 if a.is_fc_setter < b.is_fc_setter: return -1 | |
863 if a.is_fc_setter > b.is_fc_setter: return 1 | |
864 return 0 | |
865 | |
866 def ConstantOutputOrder(a, b): | |
867 """Canonical output ordering for constants.""" | |
868 if a.id < b.id: return -1 | |
869 if a.id > b.id: return 1 | |
870 return 0 | |
871 | |
872 | |
873 def _FormatNameList(names): | |
874 """Returns JavaScript array literal expression with one name per line.""" | |
875 #names = sorted(names) | |
876 if len(names) <= 1: | |
877 expression_string = str(names) # e.g. ['length'] | |
878 else: | |
879 expression_string = ',\n '.join(str(names).split(',')) | |
880 expression_string = expression_string.replace('[', '[\n ') | |
881 return expression_string | |
882 | |
883 | |
884 def IndentText(text, indent): | |
885 """Format lines of text with indent.""" | |
886 def FormatLine(line): | |
887 if line.strip(): | |
888 return '%s%s\n' % (indent, line) | |
889 else: | |
890 return '\n' | |
891 return ''.join(FormatLine(line) for line in text.split('\n')) | |
892 | |
893 # ------------------------------------------------------------------------------ | 573 # ------------------------------------------------------------------------------ |
894 | 574 |
895 class TemplateLoader(object): | 575 class TemplateLoader(object): |
896 """Loads template files from a path.""" | 576 """Loads template files from a path.""" |
897 | 577 |
898 def __init__(self, root, subpaths): | 578 def __init__(self, root, subpaths): |
899 """Initializes loader. | 579 """Initializes loader. |
900 | 580 |
901 Args: | 581 Args: |
902 root - a string, the directory under which the templates are stored. | 582 root - a string, the directory under which the templates are stored. |
(...skipping 18 matching lines...) Expand all Loading... |
921 return None | 601 return None |
922 | 602 |
923 def Load(self, name): | 603 def Load(self, name): |
924 """Returns contents of template file as a string, or raises an exception.""" | 604 """Returns contents of template file as a string, or raises an exception.""" |
925 template = self.TryLoad(name) | 605 template = self.TryLoad(name) |
926 if template is not None: # Can be empty string | 606 if template is not None: # Can be empty string |
927 return template | 607 return template |
928 raise Exception("Could not find template '%s' on %s / %s" % ( | 608 raise Exception("Could not find template '%s' on %s / %s" % ( |
929 name, self._root, self._subpaths)) | 609 name, self._root, self._subpaths)) |
930 | 610 |
931 | |
932 # ------------------------------------------------------------------------------ | |
933 | |
934 class System(object): | |
935 """Generates all the files for one implementation.""" | |
936 | |
937 def __init__(self, templates, database, emitters, output_dir): | |
938 self._templates = templates | |
939 self._database = database | |
940 self._emitters = emitters | |
941 self._output_dir = output_dir | |
942 self._dart_callback_file_paths = [] | |
943 | |
944 def InterfaceGenerator(self, | |
945 interface, | |
946 common_prefix, | |
947 super_interface_name, | |
948 source_filter): | |
949 """Returns an interface generator for |interface|.""" | |
950 return None | |
951 | |
952 def ProcessCallback(self, interface, info): | |
953 pass | |
954 | |
955 def GenerateLibraries(self, lib_dir): | |
956 pass | |
957 | |
958 def Finish(self): | |
959 pass | |
960 | |
961 | |
962 def _ProcessCallback(self, interface, info, file_path): | |
963 """Generates a typedef for the callback interface.""" | |
964 self._dart_callback_file_paths.append(file_path) | |
965 code = self._emitters.FileEmitter(file_path) | |
966 | |
967 code.Emit(self._templates.Load('callback.darttemplate')) | |
968 code.Emit('typedef $TYPE $NAME($PARAMS);\n', | |
969 NAME=interface.id, | |
970 TYPE=info.type_name, | |
971 PARAMS=info.ParametersImplementationDeclaration()) | |
972 | |
973 def _GenerateLibFile(self, lib_template, lib_file_path, file_paths, | |
974 **template_args): | |
975 """Generates a lib file from a template and a list of files. | |
976 | |
977 Additional keyword arguments are passed to the template. | |
978 """ | |
979 # Load template. | |
980 template = self._templates.Load(lib_template) | |
981 # Generate the .lib file. | |
982 lib_file_contents = self._emitters.FileEmitter(lib_file_path) | |
983 | |
984 # Emit the list of #source directives. | |
985 list_emitter = lib_file_contents.Emit(template, **template_args) | |
986 lib_file_dir = os.path.dirname(lib_file_path) | |
987 for path in sorted(file_paths): | |
988 relpath = os.path.relpath(path, lib_file_dir) | |
989 list_emitter.Emit("#source('$PATH');\n", PATH=relpath) | |
990 | |
991 | |
992 def _BaseDefines(self, interface): | |
993 """Returns a set of names (strings) for members defined in a base class. | |
994 """ | |
995 def WalkParentChain(interface): | |
996 if interface.parents: | |
997 # Only consider primary parent, secondary parents are not on the | |
998 # implementation class inheritance chain. | |
999 parent = interface.parents[0] | |
1000 if _IsDartCollectionType(parent.type.id): | |
1001 return | |
1002 if self._database.HasInterface(parent.type.id): | |
1003 parent_interface = self._database.GetInterface(parent.type.id) | |
1004 for attr in parent_interface.attributes: | |
1005 result.add(attr.id) | |
1006 for op in parent_interface.operations: | |
1007 result.add(op.id) | |
1008 WalkParentChain(parent_interface) | |
1009 | |
1010 result = set() | |
1011 WalkParentChain(interface) | |
1012 return result; | |
1013 | |
1014 | |
1015 # ------------------------------------------------------------------------------ | |
1016 | |
1017 class InterfacesSystem(System): | |
1018 | |
1019 def __init__(self, templates, database, emitters, output_dir): | |
1020 super(InterfacesSystem, self).__init__( | |
1021 templates, database, emitters, output_dir) | |
1022 self._dart_interface_file_paths = [] | |
1023 | |
1024 | |
1025 def InterfaceGenerator(self, | |
1026 interface, | |
1027 common_prefix, | |
1028 super_interface_name, | |
1029 source_filter): | |
1030 """.""" | |
1031 interface_name = interface.id | |
1032 dart_interface_file_path = self._FilePathForDartInterface(interface_name) | |
1033 | |
1034 self._dart_interface_file_paths.append(dart_interface_file_path) | |
1035 | |
1036 dart_interface_code = self._emitters.FileEmitter(dart_interface_file_path) | |
1037 | |
1038 template_file = 'interface_%s.darttemplate' % interface_name | |
1039 template = self._templates.TryLoad(template_file) | |
1040 if not template: | |
1041 template = self._templates.Load('interface.darttemplate') | |
1042 | |
1043 return DartInterfaceGenerator( | |
1044 interface, dart_interface_code, | |
1045 template, | |
1046 common_prefix, super_interface_name, | |
1047 source_filter) | |
1048 | |
1049 def ProcessCallback(self, interface, info): | |
1050 """Generates a typedef for the callback interface.""" | |
1051 interface_name = interface.id | |
1052 file_path = self._FilePathForDartInterface(interface_name) | |
1053 self._ProcessCallback(interface, info, file_path) | |
1054 | |
1055 def GenerateLibraries(self, lib_dir): | |
1056 pass | |
1057 | |
1058 | |
1059 def _FilePathForDartInterface(self, interface_name): | |
1060 """Returns the file path of the Dart interface definition.""" | |
1061 return os.path.join(self._output_dir, 'src', 'interface', | |
1062 '%s.dart' % interface_name) | |
1063 | |
1064 | |
1065 # ------------------------------------------------------------------------------ | |
1066 | |
1067 class HtmlInterfacesSystem(System): | |
1068 | |
1069 def __init__(self, templates, database, emitters, output_dir): | |
1070 super(HtmlInterfacesSystem, self).__init__( | |
1071 templates, database, emitters, output_dir) | |
1072 self._dart_interface_file_paths = [] | |
1073 | |
1074 def InterfaceGenerator(self, | |
1075 interface, | |
1076 common_prefix, | |
1077 super_interface_name, | |
1078 source_filter): | |
1079 """.""" | |
1080 interface_name = interface.id | |
1081 dart_interface_file_path = self._FilePathForDartInterface(interface_name) | |
1082 | |
1083 self._dart_interface_file_paths.append(dart_interface_file_path) | |
1084 | |
1085 dart_interface_code = self._emitters.FileEmitter(dart_interface_file_path) | |
1086 | |
1087 template_file = 'interface_%s.darttemplate' % interface_name | |
1088 template = self._templates.TryLoad(template_file) | |
1089 if not template: | |
1090 template = self._templates.Load('interface.darttemplate') | |
1091 | |
1092 return HtmlDartInterfaceGenerator( | |
1093 interface, dart_interface_code, | |
1094 template, | |
1095 common_prefix, super_interface_name, | |
1096 source_filter) | |
1097 | |
1098 def ProcessCallback(self, interface, info): | |
1099 """Generates a typedef for the callback interface.""" | |
1100 interface_name = interface.id | |
1101 file_path = self._FilePathForDartInterface(interface_name) | |
1102 self._ProcessCallback(interface, info, file_path) | |
1103 | |
1104 def GenerateLibraries(self, lib_dir): | |
1105 pass | |
1106 | |
1107 | |
1108 def _FilePathForDartInterface(self, interface_name): | |
1109 """Returns the file path of the Dart interface definition.""" | |
1110 # TODO(jmesserly): is this the right path | |
1111 return os.path.join(self._output_dir, 'html', 'interface', | |
1112 '%s.dart' % interface_name) | |
1113 | |
1114 | |
1115 # ------------------------------------------------------------------------------ | 611 # ------------------------------------------------------------------------------ |
1116 | 612 |
1117 class DummyImplementationSystem(System): | 613 class DummyImplementationSystem(System): |
1118 """Generates a dummy implementation for use by the editor analysis. | 614 """Generates a dummy implementation for use by the editor analysis. |
1119 | 615 |
1120 All the code comes from hand-written library files. | 616 All the code comes from hand-written library files. |
1121 """ | 617 """ |
1122 | 618 |
1123 def __init__(self, templates, database, emitters, output_dir): | 619 def __init__(self, templates, database, emitters, output_dir): |
1124 super(DummyImplementationSystem, self).__init__( | 620 super(DummyImplementationSystem, self).__init__( |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 pass | 693 pass |
1198 | 694 |
1199 | 695 |
1200 def _FilePathForDartWrappingImpl(self, interface_name): | 696 def _FilePathForDartWrappingImpl(self, interface_name): |
1201 """Returns the file path of the Dart wrapping implementation.""" | 697 """Returns the file path of the Dart wrapping implementation.""" |
1202 return os.path.join(self._output_dir, 'src', 'wrapping', | 698 return os.path.join(self._output_dir, 'src', 'wrapping', |
1203 '_%sWrappingImplementation.dart' % interface_name) | 699 '_%sWrappingImplementation.dart' % interface_name) |
1204 | 700 |
1205 # ------------------------------------------------------------------------------ | 701 # ------------------------------------------------------------------------------ |
1206 | 702 |
1207 class FrogSystem(System): | |
1208 | |
1209 def __init__(self, templates, database, emitters, output_dir): | |
1210 super(FrogSystem, self).__init__( | |
1211 templates, database, emitters, output_dir) | |
1212 self._dart_frog_file_paths = [] | |
1213 | |
1214 def InterfaceGenerator(self, | |
1215 interface, | |
1216 common_prefix, | |
1217 super_interface_name, | |
1218 source_filter): | |
1219 """.""" | |
1220 dart_frog_file_path = self._FilePathForFrogImpl(interface.id) | |
1221 self._dart_frog_file_paths.append(dart_frog_file_path) | |
1222 | |
1223 template_file = 'impl_%s.darttemplate' % interface.id | |
1224 template = self._templates.TryLoad(template_file) | |
1225 if not template: | |
1226 template = self._templates.Load('frog_impl.darttemplate') | |
1227 | |
1228 dart_code = self._emitters.FileEmitter(dart_frog_file_path) | |
1229 return FrogInterfaceGenerator(self, interface, template, | |
1230 super_interface_name, dart_code) | |
1231 | |
1232 def GenerateLibraries(self, lib_dir): | |
1233 self._GenerateLibFile( | |
1234 'frog_dom.darttemplate', | |
1235 os.path.join(lib_dir, 'dom_frog.dart'), | |
1236 (self._interface_system._dart_interface_file_paths + | |
1237 self._interface_system._dart_callback_file_paths + | |
1238 self._dart_frog_file_paths)) | |
1239 | |
1240 def Finish(self): | |
1241 pass | |
1242 | |
1243 def _FilePathForFrogImpl(self, interface_name): | |
1244 """Returns the file path of the Frog implementation.""" | |
1245 return os.path.join(self._output_dir, 'src', 'frog', | |
1246 '%s.dart' % interface_name) | |
1247 | |
1248 | |
1249 # ------------------------------------------------------------------------------ | |
1250 | |
1251 class HtmlFrogSystem(System): | |
1252 | |
1253 def __init__(self, templates, database, emitters, output_dir): | |
1254 super(HtmlFrogSystem, self).__init__( | |
1255 templates, database, emitters, output_dir) | |
1256 self._dart_frog_file_paths = [] | |
1257 | |
1258 def InterfaceGenerator(self, | |
1259 interface, | |
1260 common_prefix, | |
1261 super_interface_name, | |
1262 source_filter): | |
1263 """.""" | |
1264 dart_frog_file_path = self._FilePathForFrogImpl(interface.id) | |
1265 self._dart_frog_file_paths.append(dart_frog_file_path) | |
1266 | |
1267 template_file = 'impl_%s.darttemplate' % interface.id | |
1268 template = self._templates.TryLoad(template_file) | |
1269 if not template: | |
1270 template = self._templates.Load('frog_impl.darttemplate') | |
1271 | |
1272 dart_code = self._emitters.FileEmitter(dart_frog_file_path) | |
1273 return HtmlFrogInterfaceGenerator(self, interface, template, | |
1274 super_interface_name, dart_code) | |
1275 | |
1276 def GenerateLibraries(self, lib_dir): | |
1277 self._GenerateLibFile( | |
1278 'html_frog.darttemplate', | |
1279 os.path.join(lib_dir, 'html_frog.dart'), | |
1280 (self._interface_system._dart_interface_file_paths + | |
1281 self._interface_system._dart_callback_file_paths + | |
1282 self._dart_frog_file_paths)) | |
1283 | |
1284 def Finish(self): | |
1285 pass | |
1286 | |
1287 def _FilePathForFrogImpl(self, interface_name): | |
1288 """Returns the file path of the Frog implementation.""" | |
1289 # TODO(jmesserly): is this the right path | |
1290 return os.path.join(self._output_dir, 'html', 'frog', | |
1291 '%s.dart' % interface_name) | |
1292 | |
1293 # ------------------------------------------------------------------------------ | |
1294 | |
1295 class DartInterfaceGenerator(object): | |
1296 """Generates Dart Interface definition for one DOM IDL interface.""" | |
1297 | |
1298 def __init__(self, interface, emitter, template, | |
1299 common_prefix, super_interface, source_filter): | |
1300 """Generates Dart code for the given interface. | |
1301 | |
1302 Args: | |
1303 interface -- an IDLInterface instance. It is assumed that all types have | |
1304 been converted to Dart types (e.g. int, String), unless they are in the | |
1305 same package as the interface. | |
1306 common_prefix -- the prefix for the common library, if any. | |
1307 super_interface -- the name of the common interface that this interface | |
1308 implements, if any. | |
1309 source_filter -- if specified, rewrites the names of any superinterfaces | |
1310 that are not from these sources to use the common prefix. | |
1311 """ | |
1312 self._interface = interface | |
1313 self._emitter = emitter | |
1314 self._template = template | |
1315 self._common_prefix = common_prefix | |
1316 self._super_interface = super_interface | |
1317 self._source_filter = source_filter | |
1318 | |
1319 | |
1320 def StartInterface(self): | |
1321 if self._super_interface: | |
1322 typename = self._super_interface | |
1323 else: | |
1324 typename = self._interface.id | |
1325 | |
1326 # TODO(vsm): Add appropriate package / namespace syntax. | |
1327 (extends_emitter, | |
1328 self._members_emitter, | |
1329 self._top_level_emitter) = self._emitter.Emit( | |
1330 self._template + '$!TOP_LEVEL', | |
1331 ID=typename) | |
1332 | |
1333 extends = [] | |
1334 suppressed_extends = [] | |
1335 | |
1336 for parent in self._interface.parents: | |
1337 # TODO(vsm): Remove source_filter. | |
1338 if _MatchSourceFilter(self._source_filter, parent): | |
1339 # Parent is a DOM type. | |
1340 extends.append(parent.type.id) | |
1341 elif '<' in parent.type.id: | |
1342 # Parent is a Dart collection type. | |
1343 # TODO(vsm): Make this check more robust. | |
1344 extends.append(parent.type.id) | |
1345 else: | |
1346 suppressed_extends.append('%s.%s' % | |
1347 (self._common_prefix, parent.type.id)) | |
1348 | |
1349 comment = ' extends' | |
1350 if extends: | |
1351 extends_emitter.Emit(' extends $SUPERS', SUPERS=', '.join(extends)) | |
1352 comment = ',' | |
1353 if suppressed_extends: | |
1354 extends_emitter.Emit(' /*$COMMENT $SUPERS */', | |
1355 COMMENT=comment, | |
1356 SUPERS=', '.join(suppressed_extends)) | |
1357 | |
1358 if typename in _interface_factories: | |
1359 extends_emitter.Emit(' default $F', F=_interface_factories[typename]) | |
1360 | |
1361 element_type = MaybeTypedArrayElementType(self._interface) | |
1362 if element_type: | |
1363 self._members_emitter.Emit( | |
1364 '\n' | |
1365 ' $CTOR(int length);\n' | |
1366 '\n' | |
1367 ' $CTOR.fromList(List<$TYPE> list);\n' | |
1368 '\n' | |
1369 ' $CTOR.fromBuffer(ArrayBuffer buffer);\n', | |
1370 CTOR=self._interface.id, | |
1371 TYPE=element_type) | |
1372 | |
1373 | |
1374 def FinishInterface(self): | |
1375 # TODO(vsm): Use typedef if / when that is supported in Dart. | |
1376 # Define variant as subtype. | |
1377 if (self._super_interface and | |
1378 self._interface.id is not self._super_interface): | |
1379 consts_emitter = self._top_level_emitter.Emit( | |
1380 '\n' | |
1381 'interface $NAME extends $BASE {\n' | |
1382 '$!CONSTS' | |
1383 '}\n', | |
1384 NAME=self._interface.id, | |
1385 BASE=self._super_interface) | |
1386 for const in sorted(self._interface.constants, ConstantOutputOrder): | |
1387 self._EmitConstant(consts_emitter, const) | |
1388 | |
1389 def AddConstant(self, constant): | |
1390 if (not self._super_interface or | |
1391 self._interface.id is self._super_interface): | |
1392 self._EmitConstant(self._members_emitter, constant) | |
1393 | |
1394 def _EmitConstant(self, emitter, constant): | |
1395 emitter.Emit('\n static final $TYPE $NAME = $VALUE;\n', | |
1396 NAME=constant.id, | |
1397 TYPE=constant.type.id, | |
1398 VALUE=constant.value) | |
1399 | |
1400 def AddAttribute(self, getter, setter): | |
1401 if getter and setter and getter.type.id == setter.type.id: | |
1402 self._members_emitter.Emit('\n $TYPE $NAME;\n', | |
1403 NAME=getter.id, TYPE=getter.type.id); | |
1404 return | |
1405 if getter and not setter: | |
1406 self._members_emitter.Emit('\n final $TYPE $NAME;\n', | |
1407 NAME=getter.id, TYPE=getter.type.id); | |
1408 return | |
1409 raise Exception('Unexpected getter/setter combination %s %s' % | |
1410 (getter, setter)) | |
1411 | |
1412 def AddIndexer(self, element_type): | |
1413 # Interface inherits all operations from List<element_type>. | |
1414 pass | |
1415 | |
1416 def AddOperation(self, info): | |
1417 """ | |
1418 Arguments: | |
1419 operations - contains the overloads, one or more operations with the same | |
1420 name. | |
1421 """ | |
1422 self._members_emitter.Emit('\n' | |
1423 ' $TYPE $NAME($PARAMS);\n', | |
1424 TYPE=info.type_name, | |
1425 NAME=info.name, | |
1426 PARAMS=info.ParametersInterfaceDeclaration()) | |
1427 | |
1428 # Interfaces get secondary members directly via the superinterfaces. | |
1429 def AddSecondaryAttribute(self, interface, getter, setter): | |
1430 pass | |
1431 | |
1432 def AddSecondaryOperation(self, interface, attr): | |
1433 pass | |
1434 | |
1435 def AddEventAttributes(self, event_attrs): | |
1436 pass | |
1437 | |
1438 # Given a sorted sequence of type identifiers, return an appropriate type | |
1439 # name | |
1440 def TypeName(typeIds, interface): | |
1441 # Dynamically type this field for now. | |
1442 return 'var' | |
1443 | |
1444 # ------------------------------------------------------------------------------ | |
1445 | |
1446 # TODO(jmesserly): inheritance is probably not the right way to factor this long | |
1447 # term, but it makes merging better for now. | |
1448 class HtmlDartInterfaceGenerator(DartInterfaceGenerator): | |
1449 """Generates Dart Interface definition for one DOM IDL interface.""" | |
1450 | |
1451 def __init__(self, interface, emitter, template, | |
1452 common_prefix, super_interface, source_filter): | |
1453 super(HtmlDartInterfaceGenerator, self).__init__(interface, | |
1454 emitter, template, common_prefix, super_interface, source_filter) | |
1455 | |
1456 def AddEventAttributes(self, event_attrs): | |
1457 events_interface = self._interface.id + 'Events' | |
1458 self._members_emitter.Emit('\n $TYPE get on();\n', | |
1459 TYPE=events_interface) | |
1460 events_members = self._emitter.Emit( | |
1461 '\ninterface $INTERFACE {\n$!MEMBERS}\n', | |
1462 INTERFACE=events_interface) | |
1463 | |
1464 for getter, setter in event_attrs: | |
1465 event = getter or setter | |
1466 events_members.Emit('\n EventListenerList get $NAME();\n', NAME=event.id) | |
1467 | |
1468 | |
1469 # ------------------------------------------------------------------------------ | |
1470 | |
1471 class DummyInterfaceGenerator(object): | 703 class DummyInterfaceGenerator(object): |
1472 """Generates nothing.""" | 704 """Generates nothing.""" |
1473 | 705 |
1474 def __init__(self, system, interface): | 706 def __init__(self, system, interface): |
1475 pass | 707 pass |
1476 | 708 |
1477 def StartInterface(self): | 709 def StartInterface(self): |
1478 pass | 710 pass |
1479 | 711 |
1480 def FinishInterface(self): | 712 def FinishInterface(self): |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 if not interface.parents: | 794 if not interface.parents: |
1563 return 'DOMWrapperBase' | 795 return 'DOMWrapperBase' |
1564 | 796 |
1565 supertype = interface.parents[0].type.id | 797 supertype = interface.parents[0].type.id |
1566 | 798 |
1567 # FIXME: We're currently injecting List<..> and EventTarget as | 799 # FIXME: We're currently injecting List<..> and EventTarget as |
1568 # supertypes in dart.idl. We should annotate/preserve as | 800 # supertypes in dart.idl. We should annotate/preserve as |
1569 # attributes instead. For now, this hack lets the interfaces | 801 # attributes instead. For now, this hack lets the interfaces |
1570 # inherit, but not the classes. | 802 # inherit, but not the classes. |
1571 # List methods are injected in AddIndexer. | 803 # List methods are injected in AddIndexer. |
1572 if _IsDartListType(supertype) or _IsDartCollectionType(supertype): | 804 if IsDartListType(supertype) or IsDartCollectionType(supertype): |
1573 return 'DOMWrapperBase' | 805 return 'DOMWrapperBase' |
1574 | 806 |
1575 if supertype == 'EventTarget': | 807 if supertype == 'EventTarget': |
1576 # Most implementors of EventTarget specify the EventListener operations | 808 # Most implementors of EventTarget specify the EventListener operations |
1577 # again. If the operations are not specified, try to inherit from the | 809 # again. If the operations are not specified, try to inherit from the |
1578 # EventTarget implementation. | 810 # EventTarget implementation. |
1579 # | 811 # |
1580 # Applies to MessagePort. | 812 # Applies to MessagePort. |
1581 if not [op for op in interface.operations if op.id == 'addEventListener']: | 813 if not [op for op in interface.operations if op.id == 'addEventListener']: |
1582 return self._ImplClassName(supertype) | 814 return self._ImplClassName(supertype) |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1954 # that Y = Z-X, so we need to check for Y. | 1186 # that Y = Z-X, so we need to check for Y. |
1955 true_code = emitter.Emit( | 1187 true_code = emitter.Emit( |
1956 '$(INDENT)if ($COND) {\n' | 1188 '$(INDENT)if ($COND) {\n' |
1957 '$!TRUE' | 1189 '$!TRUE' |
1958 '$(INDENT)}\n', | 1190 '$(INDENT)}\n', |
1959 COND=test, INDENT=indent) | 1191 COND=test, INDENT=indent) |
1960 self.GenerateDispatch( | 1192 self.GenerateDispatch( |
1961 true_code, info, indent + ' ', position + 1, positive) | 1193 true_code, info, indent + ' ', position + 1, positive) |
1962 return True | 1194 return True |
1963 | 1195 |
1964 | |
1965 # ------------------------------------------------------------------------------ | |
1966 | |
1967 class FrogInterfaceGenerator(object): | |
1968 """Generates a Frog class for a DOM IDL interface.""" | |
1969 | |
1970 def __init__(self, system, interface, template, super_interface, dart_code): | |
1971 """Generates Dart code for the given interface. | |
1972 | |
1973 Args: | |
1974 | |
1975 interface: an IDLInterface instance. It is assumed that all types have | |
1976 been converted to Dart types (e.g. int, String), unless they are in | |
1977 the same package as the interface. | |
1978 template: A string template. | |
1979 super_interface: A string or None, the name of the common interface that | |
1980 this interface implements, if any. | |
1981 dart_code: an Emitter for the file containing the Dart implementation | |
1982 class. | |
1983 """ | |
1984 self._system = system | |
1985 self._interface = interface | |
1986 self._template = template | |
1987 self._super_interface = super_interface | |
1988 self._dart_code = dart_code | |
1989 self._current_secondary_parent = None | |
1990 | |
1991 | |
1992 def StartInterface(self): | |
1993 interface = self._interface | |
1994 interface_name = interface.id | |
1995 | |
1996 self._class_name = self._ImplClassName(interface_name) | |
1997 | |
1998 base = None | |
1999 if interface.parents: | |
2000 supertype = interface.parents[0].type.id | |
2001 if _IsDartCollectionType(supertype): | |
2002 # List methods are injected in AddIndexer. | |
2003 pass | |
2004 else: | |
2005 base = self._ImplClassName(supertype) | |
2006 | |
2007 if interface_name in _frog_dom_custom_native_specs: | |
2008 native_spec = _frog_dom_custom_native_specs[interface_name] | |
2009 else: | |
2010 # Make the class 'hidden' so it is dynamically patched at runtime. This | |
2011 # is useful not only for browser compat, but to allow code that links | |
2012 # against dart:dom to load in a worker isolate. | |
2013 native_spec = '*' + interface_name | |
2014 | |
2015 if base: | |
2016 extends = ' extends ' + base | |
2017 elif native_spec[0] == '=': | |
2018 # The implementation is a singleton with no prototype. | |
2019 extends = '' | |
2020 else: | |
2021 extends = ' extends _DOMTypeJs' | |
2022 | |
2023 # TODO: Include all implemented interfaces, including other Lists. | |
2024 implements = [interface_name] | |
2025 element_type = MaybeTypedArrayElementType(self._interface) | |
2026 if element_type: | |
2027 implements.append('List<' + element_type + '>') | |
2028 | |
2029 self._members_emitter = self._dart_code.Emit( | |
2030 self._template, | |
2031 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { | |
2032 #$!MEMBERS | |
2033 #} | |
2034 CLASSNAME=self._class_name, | |
2035 EXTENDS=extends, | |
2036 IMPLEMENTS=' implements ' + ', '.join(implements), | |
2037 NATIVESPEC=' native "' + native_spec + '"') | |
2038 | |
2039 element_type = MaybeTypedArrayElementType(interface) | |
2040 if element_type: | |
2041 self.AddTypedArrayConstructors(element_type) | |
2042 | |
2043 | |
2044 def FinishInterface(self): | |
2045 """.""" | |
2046 pass | |
2047 | |
2048 def _ImplClassName(self, type_name): | |
2049 return '_' + type_name + 'Js' | |
2050 | |
2051 def _NarrowToImplementationType(self, type_name): | |
2052 # TODO(sra): Move into the 'system' and cache the result. | |
2053 if type_name == 'EventListener': | |
2054 # Callbacks are typedef functions so don't have a class. | |
2055 return type_name | |
2056 if self._system._database.HasInterface(type_name): | |
2057 interface = self._system._database.GetInterface(type_name) | |
2058 if _RecognizeCallback(interface): | |
2059 # Callbacks are typedef functions so don't have a class. | |
2060 return type_name | |
2061 else: | |
2062 return self._ImplClassName(type_name) | |
2063 return type_name | |
2064 | |
2065 def _NarrowInputType(self, type_name): | |
2066 return self._NarrowToImplementationType(type_name) | |
2067 | |
2068 def _NarrowOutputType(self, type_name): | |
2069 return self._NarrowToImplementationType(type_name) | |
2070 | |
2071 def AddConstant(self, constant): | |
2072 # Since we are currently generating native classes without interfaces, | |
2073 # generate the constants as part of the class. This will need to go away | |
2074 # if we revert back to generating interfaces. | |
2075 self._members_emitter.Emit('\n static final $TYPE $NAME = $VALUE;\n', | |
2076 NAME=constant.id, | |
2077 TYPE=constant.type.id, | |
2078 VALUE=constant.value) | |
2079 | |
2080 pass | |
2081 | |
2082 def AddAttribute(self, getter, setter): | |
2083 output_type = getter and self._NarrowOutputType(getter.type.id) | |
2084 input_type = setter and self._NarrowInputType(setter.type.id) | |
2085 | |
2086 # If the (getter, setter) pair is shadowing, we can't generate a shadowing | |
2087 # field (Issue 1633). | |
2088 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter) | |
2089 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter) | |
2090 if super_getter or super_setter: | |
2091 if getter and not setter and super_getter and not super_setter: | |
2092 if getter.type.id == super_getter.type.id: | |
2093 # Compatible getter, use the superclass property. This works because | |
2094 # JavaScript will do its own dynamic dispatch. | |
2095 self._members_emitter.Emit( | |
2096 '\n' | |
2097 ' // Use implementation from $SUPER.\n' | |
2098 ' // final $TYPE $NAME;\n', | |
2099 SUPER=super_getter_interface.id, | |
2100 NAME=getter.id, TYPE=output_type) | |
2101 return | |
2102 | |
2103 self._members_emitter.Emit('\n // Shadowing definition.') | |
2104 self._AddAttributeUsingProperties(getter, setter) | |
2105 return | |
2106 | |
2107 if getter and setter and input_type == output_type: | |
2108 self._members_emitter.Emit( | |
2109 '\n $TYPE $NAME;\n', | |
2110 NAME=getter.id, TYPE=output_type) | |
2111 return | |
2112 if getter and not setter: | |
2113 self._members_emitter.Emit( | |
2114 '\n final $TYPE $NAME;\n', | |
2115 NAME=getter.id, TYPE=output_type) | |
2116 return | |
2117 self._AddAttributeUsingProperties(getter, setter) | |
2118 | |
2119 def _AddAttributeUsingProperties(self, getter, setter): | |
2120 if getter: | |
2121 self._AddGetter(getter) | |
2122 if setter: | |
2123 self._AddSetter(setter) | |
2124 | |
2125 def _AddGetter(self, attr): | |
2126 # TODO(sra): Remove native body when Issue 829 fixed. | |
2127 self._members_emitter.Emit( | |
2128 '\n $TYPE get $NAME() native "return this.$NAME;";\n', | |
2129 NAME=attr.id, TYPE=self._NarrowOutputType(attr.type.id)) | |
2130 | |
2131 def _AddSetter(self, attr): | |
2132 # TODO(sra): Remove native body when Issue 829 fixed. | |
2133 self._members_emitter.Emit( | |
2134 ' void set $NAME($TYPE value) native "this.$NAME = value;";\n', | |
2135 NAME=attr.id, TYPE=self._NarrowInputType(attr.type.id)) | |
2136 | |
2137 def _FindShadowedAttribute(self, attr): | |
2138 """Returns (attribute, superinterface) or (None, None).""" | |
2139 def FindInParent(interface): | |
2140 """Returns matching attribute in parent, or None.""" | |
2141 if interface.parents: | |
2142 parent = interface.parents[0] | |
2143 if _IsDartCollectionType(parent.type.id): | |
2144 return (None, None) | |
2145 if self._system._database.HasInterface(parent.type.id): | |
2146 parent_interface = self._system._database.GetInterface(parent.type.id) | |
2147 attr2 = _FindMatchingAttribute(parent_interface, attr) | |
2148 if attr2: | |
2149 return (attr2, parent_interface) | |
2150 return FindInParent(parent_interface) | |
2151 return (None, None) | |
2152 | |
2153 return FindInParent(self._interface) if attr else (None, None) | |
2154 | |
2155 | |
2156 def AddSecondaryAttribute(self, interface, getter, setter): | |
2157 self._SecondaryContext(interface) | |
2158 self.AddAttribute(getter, setter) | |
2159 | |
2160 def AddSecondaryOperation(self, interface, info): | |
2161 self._SecondaryContext(interface) | |
2162 self.AddOperation(info) | |
2163 | |
2164 def AddEventAttributes(self, event_attrs): | |
2165 pass | |
2166 | |
2167 def _SecondaryContext(self, interface): | |
2168 if interface is not self._current_secondary_parent: | |
2169 self._current_secondary_parent = interface | |
2170 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id) | |
2171 | |
2172 def AddIndexer(self, element_type): | |
2173 """Adds all the methods required to complete implementation of List.""" | |
2174 # We would like to simply inherit the implementation of everything except | |
2175 # get length(), [], and maybe []=. It is possible to extend from a base | |
2176 # array implementation class only when there is no other implementation | |
2177 # inheritance. There might be no implementation inheritance other than | |
2178 # DOMBaseWrapper for many classes, but there might be some where the | |
2179 # array-ness is introduced by a non-root interface: | |
2180 # | |
2181 # interface Y extends X, List<T> ... | |
2182 # | |
2183 # In the non-root case we have to choose between: | |
2184 # | |
2185 # class YImpl extends XImpl { add List<T> methods; } | |
2186 # | |
2187 # and | |
2188 # | |
2189 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | |
2190 # | |
2191 self._members_emitter.Emit( | |
2192 '\n' | |
2193 ' $TYPE operator[](int index) native "return this[index];";\n', | |
2194 TYPE=self._NarrowOutputType(element_type)) | |
2195 | |
2196 if 'CustomIndexedSetter' in self._interface.ext_attrs: | |
2197 self._members_emitter.Emit( | |
2198 '\n' | |
2199 ' void operator[]=(int index, $TYPE value) native "this[index] = valu
e";\n', | |
2200 TYPE=self._NarrowInputType(element_type)) | |
2201 else: | |
2202 self._members_emitter.Emit( | |
2203 '\n' | |
2204 ' void operator[]=(int index, $TYPE value) {\n' | |
2205 ' throw new UnsupportedOperationException("Cannot assign element of
immutable List.");\n' | |
2206 ' }\n', | |
2207 TYPE=self._NarrowInputType(element_type)) | |
2208 | |
2209 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | |
2210 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | |
2211 template_file = 'immutable_list_mixin.darttemplate' | |
2212 template = self._system._templates.Load(template_file) | |
2213 self._members_emitter.Emit(template, E=element_type) | |
2214 | |
2215 | |
2216 def AddTypedArrayConstructors(self, element_type): | |
2217 self._members_emitter.Emit( | |
2218 '\n' | |
2219 ' factory $CTOR(int length) => _construct_$CTOR(length);\n' | |
2220 '\n' | |
2221 ' factory $CTOR.fromList(List<$TYPE> list) => _construct_$CTOR(list);\n
' | |
2222 '\n' | |
2223 ' factory $CTOR.fromBuffer(ArrayBuffer buffer) => _construct_$CTOR(buff
er);\n' | |
2224 '\n' | |
2225 ' static _construct_$CTOR(arg) native \'return new $CTOR(arg);\';\n', | |
2226 CTOR=self._interface.id, | |
2227 TYPE=element_type) | |
2228 | |
2229 | |
2230 def AddOperation(self, info): | |
2231 """ | |
2232 Arguments: | |
2233 info: An OperationInfo object. | |
2234 """ | |
2235 # TODO(vsm): Handle overloads. | |
2236 self._members_emitter.Emit( | |
2237 '\n' | |
2238 ' $TYPE $NAME($PARAMS) native;\n', | |
2239 TYPE=self._NarrowOutputType(info.type_name), | |
2240 NAME=info.name, | |
2241 PARAMS=info.ParametersImplementationDeclaration( | |
2242 lambda type_name: self._NarrowInputType(type_name))) | |
2243 | |
2244 | |
2245 # ------------------------------------------------------------------------------ | |
2246 | |
2247 # TODO(jmesserly): inheritance is probably not the right way to factor this long | |
2248 # term, but it makes merging better for now. | |
2249 class HtmlFrogInterfaceGenerator(FrogInterfaceGenerator): | |
2250 """Generates a Frog class for the dart:html library from a DOM IDL | |
2251 interface. | |
2252 """ | |
2253 | |
2254 def __init__(self, system, interface, template, super_interface, dart_code): | |
2255 super(HtmlFrogInterfaceGenerator, self).__init__( | |
2256 system, interface, template, super_interface, dart_code) | |
2257 | |
2258 def AddEventAttributes(self, event_attrs): | |
2259 events_class = self._interface.id + 'EventsImpl' | |
2260 events_interface = self._interface.id + 'Events' | |
2261 self._members_emitter.Emit('\n $TYPE get on() =>\n new $TYPE(this);\n', | |
2262 TYPE=events_class) | |
2263 | |
2264 events_members = self._dart_code.Emit( | |
2265 '\n' | |
2266 'class $CLASSNAME extends EventsImplementation ' | |
2267 'implements $INTERFACE {\n' | |
2268 ' $CLASSNAME(_ptr) : super._wrap(_ptr);\n' | |
2269 '$!MEMBERS}\n', | |
2270 CLASSNAME=events_class, | |
2271 INTERFACE=events_interface) | |
2272 | |
2273 for getter, setter in event_attrs: | |
2274 event = getter or setter | |
2275 events_members.Emit( | |
2276 "\n" | |
2277 "EventListenerList get $NAME() => _get('$NAME');\n", | |
2278 NAME=event.id) | |
2279 | |
2280 | |
2281 # ------------------------------------------------------------------------------ | 1196 # ------------------------------------------------------------------------------ |
2282 | 1197 |
2283 class IDLTypeInfo(object): | 1198 class IDLTypeInfo(object): |
2284 def __init__(self, idl_type, native_type=None, ref_counted=True, | 1199 def __init__(self, idl_type, native_type=None, ref_counted=True, |
2285 has_dart_wrapper=True, conversion_template=None, | 1200 has_dart_wrapper=True, conversion_template=None, |
2286 custom_to_dart=False): | 1201 custom_to_dart=False): |
2287 self._idl_type = idl_type | 1202 self._idl_type = idl_type |
2288 self._native_type = native_type | 1203 self._native_type = native_type |
2289 self._ref_counted = ref_counted | 1204 self._ref_counted = ref_counted |
2290 self._has_dart_wrapper = has_dart_wrapper | 1205 self._has_dart_wrapper = has_dart_wrapper |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3166 namespace = 'HTMLNames' | 2081 namespace = 'HTMLNames' |
3167 svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload', | 2082 svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload', |
3168 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', | 2083 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', |
3169 'onmouseup', 'onresize', 'onscroll', 'onunload'] | 2084 'onmouseup', 'onresize', 'onscroll', 'onunload'] |
3170 if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions: | 2085 if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions: |
3171 namespace = 'SVGNames' | 2086 namespace = 'SVGNames' |
3172 self._cpp_impl_includes[namespace] = 1 | 2087 self._cpp_impl_includes[namespace] = 1 |
3173 | 2088 |
3174 attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower() | 2089 attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower() |
3175 return 'WebCore::%s::%sAttr' % (namespace, attribute_name) | 2090 return 'WebCore::%s::%sAttr' % (namespace, attribute_name) |
OLD | NEW |