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

Side by Side Diff: lib/html/scripts/systemhtml.py

Issue 11091046: Move interface merging info to type registry. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « lib/html/scripts/generator.py ('k') | lib/html/scripts/systemnative.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/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 provides shared functionality for the system to generate 6 """This module provides shared functionality for the system to generate
7 Dart:html APIs from the IDL database.""" 7 Dart:html APIs from the IDL database."""
8 8
9 import emitter 9 import emitter
10 import os 10 import os
(...skipping 15 matching lines...) Expand all
26 'SelectElement.selectedOptions', 26 'SelectElement.selectedOptions',
27 'TableElement.createTBody', 27 'TableElement.createTBody',
28 'LocalWindow.document', 28 'LocalWindow.document',
29 'LocalWindow.indexedDB', 29 'LocalWindow.indexedDB',
30 'LocalWindow.location', 30 'LocalWindow.location',
31 'LocalWindow.open', 31 'LocalWindow.open',
32 'LocalWindow.webkitCancelAnimationFrame', 32 'LocalWindow.webkitCancelAnimationFrame',
33 'LocalWindow.webkitRequestAnimationFrame', 33 'LocalWindow.webkitRequestAnimationFrame',
34 ]) 34 ])
35 35
36 # This map controls merging of interfaces in dart:html library.
37 # All constants, attributes, and operations of merged interface (key) are
38 # added to target interface (value). All references to the merged interface
39 # (e.g. parameter types, return types, parent interfaces) are replaced with
40 # target interface. There are two important restrictions:
41 # 1) Merged and target interfaces shouldn't have common members, otherwise there
42 # would be duplicated declarations in generated Dart code.
43 # 2) Merged interface should be direct child of target interface, so the
44 # children of merged interface are not affected by the merge.
45 # As a consequence, target interface implementation and its direct children
46 # interface implementations should implement merged attribute accessors and
47 # operations. For example, SVGElement and Element implementation classes should
48 # implement HTMLElement.insertAdjacentElement(), HTMLElement.innerHTML, etc.
49 _merged_html_interfaces = {
50 'HTMLDocument': 'Document',
51 'HTMLElement': 'Element'
52 }
53 36
54 # Types that are accessible cross-frame in a limited fashion. 37 # Types that are accessible cross-frame in a limited fashion.
55 # In these cases, the base type (e.g., Window) provides restricted access 38 # In these cases, the base type (e.g., Window) provides restricted access
56 # while the subtype (e.g., LocalWindow) provides full access to the 39 # while the subtype (e.g., LocalWindow) provides full access to the
57 # corresponding objects if there are from the same frame. 40 # corresponding objects if there are from the same frame.
58 _secure_base_types = { 41 _secure_base_types = {
59 'LocalWindow': 'Window', 42 'LocalWindow': 'Window',
60 'LocalLocation': 'Location', 43 'LocalLocation': 'Location',
61 'LocalHistory': 'History', 44 'LocalHistory': 'History',
62 } 45 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 def __init__(self, options, library_emitter, event_generator, interface, 195 def __init__(self, options, library_emitter, event_generator, interface,
213 backend): 196 backend):
214 self._renamer = options.renamer 197 self._renamer = options.renamer
215 self._database = options.database 198 self._database = options.database
216 self._template_loader = options.templates 199 self._template_loader = options.templates
217 self._type_registry = options.type_registry 200 self._type_registry = options.type_registry
218 self._library_emitter = library_emitter 201 self._library_emitter = library_emitter
219 self._event_generator = event_generator 202 self._event_generator = event_generator
220 self._interface = interface 203 self._interface = interface
221 self._backend = backend 204 self._backend = backend
205 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
222 self._html_interface_name = options.renamer.RenameInterface(self._interface) 206 self._html_interface_name = options.renamer.RenameInterface(self._interface)
223 207
224 def Generate(self): 208 def Generate(self):
225 if 'Callback' in self._interface.ext_attrs: 209 if 'Callback' in self._interface.ext_attrs:
226 self.GenerateCallback() 210 self.GenerateCallback()
227 else: 211 else:
228 self.GenerateInterface() 212 self.GenerateInterface()
229 213
230 def GenerateCallback(self): 214 def GenerateCallback(self):
231 """Generates a typedef for the callback interface.""" 215 """Generates a typedef for the callback interface."""
232 handlers = [operation for operation in self._interface.operations 216 handlers = [operation for operation in self._interface.operations
233 if operation.id == 'handleEvent'] 217 if operation.id == 'handleEvent']
234 info = AnalyzeOperation(self._interface, handlers) 218 info = AnalyzeOperation(self._interface, handlers)
235 code = self._library_emitter.FileEmitter(self._interface.id) 219 code = self._library_emitter.FileEmitter(self._interface.id)
236 code.Emit(self._template_loader.Load('callback.darttemplate')) 220 code.Emit(self._template_loader.Load('callback.darttemplate'))
237 code.Emit('typedef $TYPE $NAME($PARAMS);\n', 221 code.Emit('typedef $TYPE $NAME($PARAMS);\n',
238 NAME=self._interface.id, 222 NAME=self._interface.id,
239 TYPE=self._DartType(info.type_name), 223 TYPE=self._DartType(info.type_name),
240 PARAMS=info.ParametersImplementationDeclaration(self._DartType)) 224 PARAMS=info.ParametersImplementationDeclaration(self._DartType))
241 self._backend.GenerateCallback(info) 225 self._backend.GenerateCallback(info)
242 226
243 def GenerateInterface(self): 227 def GenerateInterface(self):
244 interface_type_info = self._type_registry.TypeInfo(self._interface.id) 228 if (self._interface_type_info.has_generated_interface() and
245 if (not self._interface.id in _merged_html_interfaces and 229 not self._interface_type_info.merged_into()):
246 interface_type_info.has_generated_interface()):
247 interface_emitter = self._library_emitter.FileEmitter( 230 interface_emitter = self._library_emitter.FileEmitter(
248 self._html_interface_name) 231 self._html_interface_name)
249 else: 232 else:
250 interface_emitter = emitter.Emitter() 233 interface_emitter = emitter.Emitter()
251 234
252 template_file = 'interface_%s.darttemplate' % self._html_interface_name 235 template_file = 'interface_%s.darttemplate' % self._html_interface_name
253 interface_template = (self._template_loader.TryLoad(template_file) or 236 interface_template = (self._template_loader.TryLoad(template_file) or
254 self._template_loader.Load('interface.darttemplate')) 237 self._template_loader.Load('interface.darttemplate'))
255 238
256 typename = self._html_interface_name 239 typename = self._html_interface_name
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 (self._type_comment_emitter, 304 (self._type_comment_emitter,
322 self._members_emitter, 305 self._members_emitter,
323 self._top_level_emitter) = interface_emitter.Emit( 306 self._top_level_emitter) = interface_emitter.Emit(
324 interface_template + '$!TOP_LEVEL', 307 interface_template + '$!TOP_LEVEL',
325 ID=typename, 308 ID=typename,
326 EXTENDS=implements_str) 309 EXTENDS=implements_str)
327 310
328 self._type_comment_emitter.Emit("/// @domName $DOMNAME", 311 self._type_comment_emitter.Emit("/// @domName $DOMNAME",
329 DOMNAME=self._interface.doc_js_name) 312 DOMNAME=self._interface.doc_js_name)
330 313
331 if self._backend.HasImplementation(): 314 implementation_emitter = self._ImplementationEmitter()
332 if not self._interface.id in _merged_html_interfaces:
333 name = self._html_interface_name
334 basename = '%sImpl' % name
335 else:
336 basename = '%sImpl_Merged' % self._html_interface_name
337 implementation_emitter = self._library_emitter.FileEmitter(basename)
338 else:
339 implementation_emitter = emitter.Emitter()
340
341 base_class = self._backend.BaseClassName() 315 base_class = self._backend.BaseClassName()
342 interface_type_info = self._type_registry.TypeInfo(self._interface.id) 316 interface_type_info = self._type_registry.TypeInfo(self._interface.id)
343 implemented_interfaces = [interface_type_info.interface_name()] +\ 317 implemented_interfaces = [interface_type_info.interface_name()] +\
344 self._backend.AdditionalImplementedInterfaces() 318 self._backend.AdditionalImplementedInterfaces()
345 self._implementation_members_emitter = implementation_emitter.Emit( 319 self._implementation_members_emitter = implementation_emitter.Emit(
346 self._backend.ImplementationTemplate(), 320 self._backend.ImplementationTemplate(),
347 CLASSNAME=self._backend.ImplementationClassName(), 321 CLASSNAME=self._backend.ImplementationClassName(),
348 EXTENDS=' extends %s' % base_class if base_class else '', 322 EXTENDS=' extends %s' % base_class if base_class else '',
349 IMPLEMENTS=' implements ' + ', '.join(implemented_interfaces), 323 IMPLEMENTS=' implements ' + ', '.join(implemented_interfaces),
350 NATIVESPEC=self._backend.NativeSpec()) 324 NATIVESPEC=self._backend.NativeSpec())
(...skipping 23 matching lines...) Expand all
374 events_interface = self._event_generator.ProcessInterface( 348 events_interface = self._event_generator.ProcessInterface(
375 self._interface, self._html_interface_name, 349 self._interface, self._html_interface_name,
376 self._backend.CustomJSMembers(), 350 self._backend.CustomJSMembers(),
377 interface_emitter, implementation_emitter) 351 interface_emitter, implementation_emitter)
378 if events_interface: 352 if events_interface:
379 self._EmitEventGetter(events_interface, '_%sImpl' % events_interface) 353 self._EmitEventGetter(events_interface, '_%sImpl' % events_interface)
380 354
381 old_backend = self._backend 355 old_backend = self._backend
382 if not self._backend.ImplementsMergedMembers(): 356 if not self._backend.ImplementsMergedMembers():
383 self._backend = HtmlGeneratorDummyBackend() 357 self._backend = HtmlGeneratorDummyBackend()
384 for merged_interface in _merged_html_interfaces: 358 merged_interface = self._interface_type_info.merged_interface()
385 if _merged_html_interfaces[merged_interface] == self._interface.id: 359 if merged_interface:
386 merged_interface = self._database.GetInterface(merged_interface) 360 self.AddMembers(self._database.GetInterface(merged_interface))
387 self.AddMembers(merged_interface)
388 self._backend = old_backend 361 self._backend = old_backend
389 362
390 self.AddMembers(self._interface) 363 self.AddMembers(self._interface)
391 self.AddSecondaryMembers(self._interface) 364 self.AddSecondaryMembers(self._interface)
392 self._backend.FinishInterface() 365 self._backend.FinishInterface()
393 366
394 def AddMembers(self, interface): 367 def AddMembers(self, interface):
395 for const in sorted(interface.constants, ConstantOutputOrder): 368 for const in sorted(interface.constants, ConstantOutputOrder):
396 self.AddConstant(const) 369 self.AddConstant(const)
397 370
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 self._backend.SecondaryContext(interface) 498 self._backend.SecondaryContext(interface)
526 self.AddOperation(info, True) 499 self.AddOperation(info, True)
527 500
528 def AddConstant(self, constant): 501 def AddConstant(self, constant):
529 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) 502 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
530 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', 503 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n',
531 NAME=constant.id, 504 NAME=constant.id,
532 TYPE=type, 505 TYPE=type,
533 VALUE=constant.value) 506 VALUE=constant.value)
534 507
508 def _ImplementationEmitter(self):
509 if IsPureInterface(self._interface.id):
510 return emitter.Emitter()
511
512 if not self._interface_type_info.merged_into():
513 name = self._html_interface_name
514 basename = '%sImpl' % name
515 else:
516 if self._backend.ImplementsMergedMembers():
517 # Merged members are implemented in target interface implementation.
518 return emitter.Emitter()
519 basename = '%sImpl_Merged' % self._html_interface_name
520 return self._library_emitter.FileEmitter(basename)
521
535 def _EmitEventGetter(self, events_interface, events_class): 522 def _EmitEventGetter(self, events_interface, events_class):
536 self._members_emitter.Emit( 523 self._members_emitter.Emit(
537 '\n /**' 524 '\n /**'
538 '\n * @domName EventTarget.addEventListener, ' 525 '\n * @domName EventTarget.addEventListener, '
539 'EventTarget.removeEventListener, EventTarget.dispatchEvent' 526 'EventTarget.removeEventListener, EventTarget.dispatchEvent'
540 '\n */' 527 '\n */'
541 '\n $TYPE get on;\n', 528 '\n $TYPE get on;\n',
542 TYPE=events_interface) 529 TYPE=events_interface)
543 530
544 self._implementation_members_emitter.Emit( 531 self._implementation_members_emitter.Emit(
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 class Dart2JSBackend(object): 577 class Dart2JSBackend(object):
591 """Generates a dart2js class for the dart:html library from a DOM IDL 578 """Generates a dart2js class for the dart:html library from a DOM IDL
592 interface. 579 interface.
593 """ 580 """
594 581
595 def __init__(self, interface, options): 582 def __init__(self, interface, options):
596 self._interface = interface 583 self._interface = interface
597 self._database = options.database 584 self._database = options.database
598 self._template_loader = options.templates 585 self._template_loader = options.templates
599 self._type_registry = options.type_registry 586 self._type_registry = options.type_registry
587 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
600 self._html_interface_name = options.renamer.RenameInterface(self._interface) 588 self._html_interface_name = options.renamer.RenameInterface(self._interface)
601 self._current_secondary_parent = None 589 self._current_secondary_parent = None
602 590
603 def HasImplementation(self):
604 return not (IsPureInterface(self._interface.id) or
605 self._interface.id in _merged_html_interfaces)
606
607 def ImplementationClassName(self): 591 def ImplementationClassName(self):
608 return self._ImplClassName(self._html_interface_name) 592 return self._ImplClassName(self._html_interface_name)
609 593
610 def ImplementsMergedMembers(self): 594 def ImplementsMergedMembers(self):
611 return True 595 return True
612 596
613 def _ImplClassName(self, type_name): 597 def _ImplClassName(self, type_name):
614 return '_%sImpl' % type_name 598 return '_%sImpl' % type_name
615 599
616 def GenerateCallback(self, info): 600 def GenerateCallback(self, info):
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 self._AddAttributeUsingProperties(attribute, html_name, read_only) 712 self._AddAttributeUsingProperties(attribute, html_name, read_only)
729 return 713 return
730 714
731 # If the attribute is shadowing, we can't generate a shadowing 715 # If the attribute is shadowing, we can't generate a shadowing
732 # field (Issue 1633). 716 # field (Issue 1633).
733 # TODO(sra): _FindShadowedAttribute does not take into account the html 717 # TODO(sra): _FindShadowedAttribute does not take into account the html
734 # renaming. we should be looking for another attribute that has the same 718 # renaming. we should be looking for another attribute that has the same
735 # html_name. Two attributes with the same IDL name might not match if one 719 # html_name. Two attributes with the same IDL name might not match if one
736 # is renamed. 720 # is renamed.
737 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute( 721 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute(
738 attribute, _merged_html_interfaces) 722 attribute)
739 if super_attribute: 723 if super_attribute:
740 if read_only: 724 if read_only:
741 if attribute.type.id == super_attribute.type.id: 725 if attribute.type.id == super_attribute.type.id:
742 # Compatible attribute, use the superclass property. This works 726 # Compatible attribute, use the superclass property. This works
743 # because JavaScript will do its own dynamic dispatch. 727 # because JavaScript will do its own dynamic dispatch.
744 self._members_emitter.Emit( 728 self._members_emitter.Emit(
745 '\n' 729 '\n'
746 ' // Use implementation from $SUPER.\n' 730 ' // Use implementation from $SUPER.\n'
747 ' // final $TYPE $NAME;\n', 731 ' // final $TYPE $NAME;\n',
748 SUPER=super_attribute_interface, 732 SUPER=super_attribute_interface,
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 return type_name 1034 return type_name
1051 return self._type_registry.TypeInfo(type_name).narrow_dart_type() 1035 return self._type_registry.TypeInfo(type_name).narrow_dart_type()
1052 1036
1053 def _NarrowInputType(self, type_name): 1037 def _NarrowInputType(self, type_name):
1054 return self._NarrowToImplementationType(type_name) 1038 return self._NarrowToImplementationType(type_name)
1055 1039
1056 def _NarrowOutputType(self, type_name): 1040 def _NarrowOutputType(self, type_name):
1057 secure_name = SecureOutputType(self, type_name, True) 1041 secure_name = SecureOutputType(self, type_name, True)
1058 return self._NarrowToImplementationType(secure_name) 1042 return self._NarrowToImplementationType(secure_name)
1059 1043
1060 def _FindShadowedAttribute(self, attr, merged_interfaces={}): 1044 def _FindShadowedAttribute(self, attr):
1061 """Returns (attribute, superinterface) or (None, None).""" 1045 """Returns (attribute, superinterface) or (None, None)."""
1062 def FindInParent(interface): 1046 def FindInParent(interface):
1063 """Returns matching attribute in parent, or None.""" 1047 """Returns matching attribute in parent, or None."""
1064 if interface.parents: 1048 if interface.parents:
1065 parent = interface.parents[0] 1049 parent = interface.parents[0]
1066 if IsDartCollectionType(parent.type.id): 1050 if IsDartCollectionType(parent.type.id):
1067 return (None, None) 1051 return (None, None)
1068 if IsPureInterface(parent.type.id): 1052 if IsPureInterface(parent.type.id):
1069 return (None, None) 1053 return (None, None)
1070 if self._database.HasInterface(parent.type.id): 1054 if self._database.HasInterface(parent.type.id):
1071 interfaces_to_search_in = [] 1055 interfaces_to_search_in = []
1072 if parent.type.id in merged_interfaces: 1056 parent_interface_name = parent.type.id
1057 interfaces_to_search_in.append(parent_interface_name)
1058 parent_type_info = self._type_registry.TypeInfo(parent_interface_name)
1059 if parent_type_info.merged_into():
1073 # IDL parent was merged into another interface, which became a 1060 # IDL parent was merged into another interface, which became a
1074 # parent interface in Dart. 1061 # parent interface in Dart.
1075 interfaces_to_search_in.append(parent.type.id) 1062 parent_interface_name = parent_type_info.merged_into()
1076 parent_interface_name = merged_interfaces[parent.type.id] 1063 interfaces_to_search_in.append(parent_interface_name)
1077 else: 1064 elif parent_type_info.merged_interface():
1078 parent_interface_name = parent.type.id 1065 # IDL parent has another interface that was merged into it.
1066 interfaces_to_search_in.append(parent_type_info.merged_interface())
1079 1067
1080 for interface_name in merged_interfaces:
1081 if merged_interfaces[interface_name] == parent_interface_name:
1082 # IDL parent has another interface that was merged into it.
1083 interfaces_to_search_in.append(interface_name)
1084
1085 interfaces_to_search_in.append(parent_interface_name)
1086 for interface_name in interfaces_to_search_in: 1068 for interface_name in interfaces_to_search_in:
1087 interface = self._database.GetInterface(interface_name) 1069 interface = self._database.GetInterface(interface_name)
1088 attr2 = FindMatchingAttribute(interface, attr) 1070 attr2 = FindMatchingAttribute(interface, attr)
1089 if attr2: 1071 if attr2:
1090 return (attr2, parent_interface_name) 1072 return (attr2, parent_interface_name)
1091 1073
1092 return FindInParent( 1074 return FindInParent(
1093 self._database.GetInterface(parent_interface_name)) 1075 self._database.GetInterface(parent_interface_name))
1094 return (None, None) 1076 return (None, None)
1095 1077
(...skipping 27 matching lines...) Expand all
1123 1105
1124 library_emitter = self._multiemitter.FileEmitter(library_file_path) 1106 library_emitter = self._multiemitter.FileEmitter(library_file_path)
1125 library_file_dir = os.path.dirname(library_file_path) 1107 library_file_dir = os.path.dirname(library_file_path)
1126 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) 1108 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir)
1127 imports_emitter = library_emitter.Emit( 1109 imports_emitter = library_emitter.Emit(
1128 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) 1110 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir))
1129 for path in sorted(self._path_to_emitter.keys()): 1111 for path in sorted(self._path_to_emitter.keys()):
1130 relpath = os.path.relpath(path, library_file_dir) 1112 relpath = os.path.relpath(path, library_file_dir)
1131 imports_emitter.Emit( 1113 imports_emitter.Emit(
1132 "#source('$PATH');\n", PATH=massage_path(relpath)) 1114 "#source('$PATH');\n", PATH=massage_path(relpath))
OLDNEW
« no previous file with comments | « lib/html/scripts/generator.py ('k') | lib/html/scripts/systemnative.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698