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

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

Issue 11045020: Merge BaseGenerator into HtmlDartInterfaceGenerator. (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/systembase.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 10 import os
11 from systembase import * 11 from generator import *
12 12
13 _js_custom_members = set([ 13 _js_custom_members = set([
14 'AudioBufferSourceNode.start', 14 'AudioBufferSourceNode.start',
15 'AudioBufferSourceNode.stop', 15 'AudioBufferSourceNode.stop',
16 'CSSStyleDeclaration.setProperty', 16 'CSSStyleDeclaration.setProperty',
17 'Element.insertAdjacentElement', 17 'Element.insertAdjacentElement',
18 'Element.insertAdjacentHTML', 18 'Element.insertAdjacentHTML',
19 'Element.insertAdjacentText', 19 'Element.insertAdjacentText',
20 'Element.remove', 20 'Element.remove',
21 'ElementEvents.mouseWheel', 21 'ElementEvents.mouseWheel',
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 RETURN_TYPE=constructor_info.type_name, 177 RETURN_TYPE=constructor_info.type_name,
178 CONSTRUCTOR=constructor_info.ConstructorFactoryName(DartType), 178 CONSTRUCTOR=constructor_info.ConstructorFactoryName(DartType),
179 CLASS=class_name, 179 CLASS=class_name,
180 TAG=info.tag, 180 TAG=info.tag,
181 PARAMS=constructor_info.ParametersInterfaceDeclaration(DartType)) 181 PARAMS=constructor_info.ParametersInterfaceDeclaration(DartType))
182 for param in constructor_info.param_infos: 182 for param in constructor_info.param_infos:
183 inits.Emit(' if ($E != null) _e.$E = $E;\n', E=param.name) 183 inits.Emit(' if ($E != null) _e.$E = $E;\n', E=param.name)
184 184
185 # ------------------------------------------------------------------------------ 185 # ------------------------------------------------------------------------------
186 186
187 class HtmlDartInterfaceGenerator(BaseGenerator): 187 class HtmlDartInterfaceGenerator(object):
188 """Generates dart interface and implementation for the DOM IDL interface.""" 188 """Generates dart interface and implementation for the DOM IDL interface."""
189 189
190 def __init__(self, options, library_emitter, event_generator, interface, 190 def __init__(self, options, library_emitter, event_generator, interface,
191 backend): 191 backend):
192 super(HtmlDartInterfaceGenerator, self).__init__(None, None, interface)
193 self._renamer = options.renamer 192 self._renamer = options.renamer
194 self._database = options.database 193 self._database = options.database
195 self._template_loader = options.templates 194 self._template_loader = options.templates
196 self._type_registry = options.type_registry 195 self._type_registry = options.type_registry
197 self._library_emitter = library_emitter 196 self._library_emitter = library_emitter
198 self._event_generator = event_generator 197 self._event_generator = event_generator
198 self._interface = interface
199 self._backend = backend 199 self._backend = backend
200 self._html_interface_name = options.renamer.RenameInterface(self._interface) 200 self._html_interface_name = options.renamer.RenameInterface(self._interface)
201 201
202 def GenerateCallback(self, info): 202 def Generate(self):
203 if 'Callback' in self._interface.ext_attrs:
204 self.GenerateCallback()
205 else:
206 self.GenerateInterface()
207
208 def GenerateCallback(self):
203 """Generates a typedef for the callback interface.""" 209 """Generates a typedef for the callback interface."""
210 handlers = [operation for operation in self._interface.operations
211 if operation.id == 'handleEvent']
212 info = AnalyzeOperation(self._interface, handlers)
204 code = self._library_emitter.FileEmitter(self._interface.id) 213 code = self._library_emitter.FileEmitter(self._interface.id)
205 code.Emit(self._template_loader.Load('callback.darttemplate')) 214 code.Emit(self._template_loader.Load('callback.darttemplate'))
206 code.Emit('typedef $TYPE $NAME($PARAMS);\n', 215 code.Emit('typedef $TYPE $NAME($PARAMS);\n',
207 NAME=self._interface.id, 216 NAME=self._interface.id,
208 TYPE=DartType(info.type_name), 217 TYPE=DartType(info.type_name),
209 PARAMS=info.ParametersImplementationDeclaration(DartType)) 218 PARAMS=info.ParametersImplementationDeclaration(DartType))
210 self._backend.GenerateCallback(info) 219 self._backend.GenerateCallback(info)
211 220
212 def StartInterface(self): 221 def GenerateInterface(self):
213 if (not self._interface.id in _merged_html_interfaces and 222 if (not self._interface.id in _merged_html_interfaces and
214 # Don't re-generate types that have been converted to native dart types. 223 # Don't re-generate types that have been converted to native dart types.
215 self._html_interface_name not in nativified_classes): 224 self._html_interface_name not in nativified_classes):
216 self._interface_emitter = self._library_emitter.FileEmitter( 225 self._interface_emitter = self._library_emitter.FileEmitter(
217 self._html_interface_name) 226 self._html_interface_name)
218 else: 227 else:
219 self._interface_emitter = emitter.Emitter() 228 self._interface_emitter = emitter.Emitter()
220 229
221 template_file = 'interface_%s.darttemplate' % self._html_interface_name 230 template_file = 'interface_%s.darttemplate' % self._html_interface_name
222 interface_template = (self._template_loader.TryLoad(template_file) or 231 interface_template = (self._template_loader.TryLoad(template_file) or
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 344
336 old_backend = self._backend 345 old_backend = self._backend
337 if not self._backend.ImplementsMergedMembers(): 346 if not self._backend.ImplementsMergedMembers():
338 self._backend = HtmlGeneratorDummyBackend() 347 self._backend = HtmlGeneratorDummyBackend()
339 for merged_interface in _merged_html_interfaces: 348 for merged_interface in _merged_html_interfaces:
340 if _merged_html_interfaces[merged_interface] == self._interface.id: 349 if _merged_html_interfaces[merged_interface] == self._interface.id:
341 merged_interface = self._database.GetInterface(merged_interface) 350 merged_interface = self._database.GetInterface(merged_interface)
342 self.AddMembers(merged_interface) 351 self.AddMembers(merged_interface)
343 self._backend = old_backend 352 self._backend = old_backend
344 353
354 self.AddMembers(self._interface)
355 self.AddSecondaryMembers(self._interface)
356 self._backend.FinishInterface()
357
358 def AddMembers(self, interface):
359 for const in sorted(interface.constants, ConstantOutputOrder):
360 self.AddConstant(const)
361
362 for attr in sorted(interface.attributes, ConstantOutputOrder):
363 if attr.type.id != 'EventListener':
364 self.AddAttribute(attr)
365
366 # The implementation should define an indexer if the interface directly
367 # extends List.
368 (element_type, requires_indexer) = ListImplementationInfo(
369 interface, self._database)
370 if element_type:
371 if requires_indexer:
372 self.AddIndexer(element_type)
373 else:
374 self.AmendIndexer(element_type)
375 # Group overloaded operations by id
376 operationsById = {}
377 for operation in interface.operations:
378 if operation.id not in operationsById:
379 operationsById[operation.id] = []
380 operationsById[operation.id].append(operation)
381
382 # Generate operations
383 for id in sorted(operationsById.keys()):
384 operations = operationsById[id]
385 info = AnalyzeOperation(interface, operations)
386 self.AddOperation(info)
387
388 def AddSecondaryMembers(self, interface):
389 # With multiple inheritance, attributes and operations of non-first
390 # interfaces need to be added. Sometimes the attribute or operation is
391 # defined in the current interface as well as a parent. In that case we
392 # avoid making a duplicate definition and pray that the signatures match.
393 secondary_parents = self._TransitiveSecondaryParents(interface)
394 for parent_interface in secondary_parents:
395 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter face)
396 continue
397 for attr in sorted(parent_interface.attributes, ConstantOutputOrder):
398 if not FindMatchingAttribute(interface, attr):
399 self.AddSecondaryAttribute(parent_interface, attr)
400
401 # Group overloaded operations by id
402 operationsById = {}
403 for operation in parent_interface.operations:
404 if operation.id not in operationsById:
405 operationsById[operation.id] = []
406 operationsById[operation.id].append(operation)
407
408 # Generate operations
409 for id in sorted(operationsById.keys()):
410 if not any(op.id == id for op in interface.operations):
411 operations = operationsById[id]
412 info = AnalyzeOperation(interface, operations)
413 self.AddSecondaryOperation(parent_interface, info)
414
345 def AddIndexer(self, element_type): 415 def AddIndexer(self, element_type):
346 self._backend.AddIndexer(element_type) 416 self._backend.AddIndexer(element_type)
347 417
348 def AmendIndexer(self, element_type): 418 def AmendIndexer(self, element_type):
349 self._backend.AmendIndexer(element_type) 419 self._backend.AmendIndexer(element_type)
350 420
351 def AddAttribute(self, attribute, is_secondary=False): 421 def AddAttribute(self, attribute, is_secondary=False):
352 dom_name = DartDomNameOfAttribute(attribute) 422 dom_name = DartDomNameOfAttribute(attribute)
353 html_name = self._renamer.RenameMember( 423 html_name = self._renamer.RenameMember(
354 self._interface.id, dom_name, 'get:') 424 self._interface.id, dom_name, 'get:')
355 if not html_name or self._IsPrivate(html_name): 425 if not html_name or self._IsPrivate(html_name):
356 return 426 return
357 427
358 428
359 html_setter_name = self._renamer.RenameMember( 429 html_setter_name = self._renamer.RenameMember(
360 self._interface.id, dom_name, 'set:') 430 self._interface.id, dom_name, 'set:')
361 read_only = IsReadOnly(attribute) or not html_setter_name 431 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs
432 or not html_setter_name)
362 433
363 # We don't yet handle inconsistent renames of the getter and setter yet. 434 # We don't yet handle inconsistent renames of the getter and setter yet.
364 assert(not html_setter_name or html_name == html_setter_name) 435 assert(not html_setter_name or html_name == html_setter_name)
365 436
366 if not is_secondary: 437 if not is_secondary:
367 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', 438 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */',
368 DOMINTERFACE=attribute.doc_js_interface_name, 439 DOMINTERFACE=attribute.doc_js_interface_name,
369 DOMNAME=dom_name) 440 DOMNAME=dom_name)
370 if read_only: 441 if read_only:
371 template = '\n abstract $TYPE get $NAME;\n' 442 template = '\n abstract $TYPE get $NAME;\n'
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 ' $TYPE $NAME($PARAMS);\n', 482 ' $TYPE $NAME($PARAMS);\n',
412 TYPE=self._DartType(info.type_name), 483 TYPE=self._DartType(info.type_name),
413 NAME=html_name, 484 NAME=html_name,
414 PARAMS=info.ParametersInterfaceDeclaration(sel f._DartType)) 485 PARAMS=info.ParametersInterfaceDeclaration(sel f._DartType))
415 self._backend.AddOperation(info, html_name) 486 self._backend.AddOperation(info, html_name)
416 487
417 def AddSecondaryOperation(self, interface, info): 488 def AddSecondaryOperation(self, interface, info):
418 self._backend.SecondaryContext(interface) 489 self._backend.SecondaryContext(interface)
419 self.AddOperation(info, True) 490 self.AddOperation(info, True)
420 491
421 def FinishInterface(self):
422 self._backend.FinishInterface()
423
424 def AddConstant(self, constant): 492 def AddConstant(self, constant):
425 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) 493 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
426 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', 494 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n',
427 NAME=constant.id, 495 NAME=constant.id,
428 TYPE=type, 496 TYPE=type,
429 VALUE=constant.value) 497 VALUE=constant.value)
430 498
431 def _EmitEventGetter(self, events_interface, events_class): 499 def _EmitEventGetter(self, events_interface, events_class):
432 self._members_emitter.Emit( 500 self._members_emitter.Emit(
433 '\n /**' 501 '\n /**'
434 '\n * @domName EventTarget.addEventListener, ' 502 '\n * @domName EventTarget.addEventListener, '
435 'EventTarget.removeEventListener, EventTarget.dispatchEvent' 503 'EventTarget.removeEventListener, EventTarget.dispatchEvent'
436 '\n */' 504 '\n */'
437 '\n $TYPE get on;\n', 505 '\n $TYPE get on;\n',
438 TYPE=events_interface) 506 TYPE=events_interface)
439 507
440 self._implementation_members_emitter.Emit( 508 self._implementation_members_emitter.Emit(
441 '\n $TYPE get on =>\n new $TYPE(this);\n', 509 '\n $TYPE get on =>\n new $TYPE(this);\n',
442 TYPE=events_class) 510 TYPE=events_class)
443 511
512 def _TransitiveSecondaryParents(self, interface):
513 """Returns a list of all non-primary parents.
514
515 The list contains the interface objects for interfaces defined in the
516 database, and the name for undefined interfaces.
517 """
518 def walk(parents):
519 for parent in parents:
520 if IsDartCollectionType(parent.type.id):
521 result.append(parent.type.id)
522 continue
523 if self._database.HasInterface(parent.type.id):
524 parent_interface = self._database.GetInterface(parent.type.id)
525 result.append(parent_interface)
526 walk(parent_interface.parents)
527
528 result = []
529 if interface.parents:
530 parent = interface.parents[0]
531 if IsPureInterface(parent.type.id):
532 walk(interface.parents)
533 else:
534 walk(interface.parents[1:])
535 return result
536
537 def _DartType(self, type_name):
538 return self._type_registry.DartType(type_name)
539
444 def _IsPrivate(self, name): 540 def _IsPrivate(self, name):
445 return name.startswith('_') 541 return name.startswith('_')
446 542
447 543
448 class HtmlGeneratorDummyBackend(object): 544 class HtmlGeneratorDummyBackend(object):
449 def AddAttribute(self, attribute, html_name, read_only): 545 def AddAttribute(self, attribute, html_name, read_only):
450 pass 546 pass
451 547
452 def AddOperation(self, info, html_name): 548 def AddOperation(self, info, html_name):
453 pass 549 pass
454 550
455 551
456 # ------------------------------------------------------------------------------ 552 # ------------------------------------------------------------------------------
457 553
458 class Dart2JSBackend(BaseGenerator): 554 class Dart2JSBackend(object):
459 """Generates a dart2js class for the dart:html library from a DOM IDL 555 """Generates a dart2js class for the dart:html library from a DOM IDL
460 interface. 556 interface.
461 """ 557 """
462 558
463 def __init__(self, interface, options): 559 def __init__(self, interface, options):
464 super(Dart2JSBackend, self).__init__(None, None, interface) 560 self._interface = interface
465 self._database = options.database 561 self._database = options.database
466 self._template_loader = options.templates 562 self._template_loader = options.templates
467 self._type_registry = options.type_registry 563 self._type_registry = options.type_registry
468 self._html_interface_name = options.renamer.RenameInterface(self._interface) 564 self._html_interface_name = options.renamer.RenameInterface(self._interface)
469 self._current_secondary_parent = None 565 self._current_secondary_parent = None
470 566
471 def HasImplementation(self): 567 def HasImplementation(self):
472 return not (IsPureInterface(self._interface.id) or 568 return not (IsPureInterface(self._interface.id) or
473 self._interface.id in _merged_html_interfaces) 569 self._interface.id in _merged_html_interfaces)
474 570
475 def ImplementationClassName(self): 571 def ImplementationClassName(self):
476 return self._ImplClassName(self._html_interface_name) 572 return self._ImplClassName(self._html_interface_name)
477 573
478 def SetImplementationEmitter(self, implementation_emitter): 574 def SetImplementationEmitter(self, implementation_emitter):
479 self._dart_code = implementation_emitter 575 self._dart_code = implementation_emitter
480 576
481 def ImplementsMergedMembers(self): 577 def ImplementsMergedMembers(self):
482 return True 578 return True
483 579
484 def _ImplClassName(self, type_name): 580 def _ImplClassName(self, type_name):
485 name = type_name 581 name = type_name
486 if type_name in nativified_classes: 582 if type_name in nativified_classes:
487 name = nativified_classes[type_name] 583 name = nativified_classes[type_name]
488 return '_%sImpl' % name 584 return '_%sImpl' % name
489 585
586 def GenerateCallback(self, info):
587 pass
588
490 def StartInterface(self): 589 def StartInterface(self):
491 interface = self._interface 590 interface = self._interface
492 interface_name = interface.id 591 interface_name = interface.id
493 592
494 self._class_name = self._ImplClassName(self._html_interface_name) 593 self._class_name = self._ImplClassName(self._html_interface_name)
495 594
496 base = None 595 base = None
497 if interface.parents: 596 if interface.parents:
498 supertype = interface.parents[0].type.id 597 supertype = interface.parents[0].type.id
499 if IsDartCollectionType(supertype): 598 if IsDartCollectionType(supertype):
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 ' this._$HTML_NAME = $CONVERT(value); }' 802 ' this._$HTML_NAME = $CONVERT(value); }'
704 '\n void set _$HTML_NAME(/*$NATIVE_TYPE*/ value)' 803 '\n void set _$HTML_NAME(/*$NATIVE_TYPE*/ value)'
705 ' native "this.$NAME = value;";' 804 ' native "this.$NAME = value;";'
706 '\n', 805 '\n',
707 CONVERT=conversion.function_name, 806 CONVERT=conversion.function_name,
708 HTML_NAME=html_name, 807 HTML_NAME=html_name,
709 NAME=attr.id, 808 NAME=attr.id,
710 INPUT_TYPE=conversion.input_type, 809 INPUT_TYPE=conversion.input_type,
711 NATIVE_TYPE=conversion.output_type) 810 NATIVE_TYPE=conversion.output_type)
712 811
812 def AmendIndexer(self, element_type):
813 pass
713 814
714 def AddOperation(self, info, html_name): 815 def AddOperation(self, info, html_name):
715 """ 816 """
716 Arguments: 817 Arguments:
717 info: An OperationInfo object. 818 info: An OperationInfo object.
718 """ 819 """
719 if self._HasCustomImplementation(info.name): 820 if self._HasCustomImplementation(info.name):
720 return 821 return
721 822
722 # Any conversions needed? 823 # Any conversions needed?
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 attr2 = FindMatchingAttribute(interface, attr) 1084 attr2 = FindMatchingAttribute(interface, attr)
984 if attr2: 1085 if attr2:
985 return (attr2, parent_interface_name) 1086 return (attr2, parent_interface_name)
986 1087
987 return FindInParent( 1088 return FindInParent(
988 self._database.GetInterface(parent_interface_name)) 1089 self._database.GetInterface(parent_interface_name))
989 return (None, None) 1090 return (None, None)
990 1091
991 return FindInParent(self._interface) if attr else (None, None) 1092 return FindInParent(self._interface) if attr else (None, None)
992 1093
1094 def _DartType(self, type_name):
Anton Muhin 2012/10/03 13:37:49 I am slightly uneasy about duplication of this cod
podivilov1 2012/10/03 15:57:37 I'm somewhat reluctant to accessing private fields
1095 return self._type_registry.DartType(type_name)
1096
993 # ------------------------------------------------------------------------------ 1097 # ------------------------------------------------------------------------------
994 1098
995 class DartLibraryEmitter(): 1099 class DartLibraryEmitter():
996 def __init__(self, multiemitter, template, dart_sources_dir): 1100 def __init__(self, multiemitter, template, dart_sources_dir):
997 self._multiemitter = multiemitter 1101 self._multiemitter = multiemitter
998 self._template = template 1102 self._template = template
999 self._dart_sources_dir = dart_sources_dir 1103 self._dart_sources_dir = dart_sources_dir
1000 self._path_to_emitter = {} 1104 self._path_to_emitter = {}
1001 1105
1002 def FileEmitter(self, basename, template=None): 1106 def FileEmitter(self, basename, template=None):
(...skipping 12 matching lines...) Expand all
1015 1119
1016 library_emitter = self._multiemitter.FileEmitter(library_file_path) 1120 library_emitter = self._multiemitter.FileEmitter(library_file_path)
1017 library_file_dir = os.path.dirname(library_file_path) 1121 library_file_dir = os.path.dirname(library_file_path)
1018 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) 1122 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir)
1019 imports_emitter = library_emitter.Emit( 1123 imports_emitter = library_emitter.Emit(
1020 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) 1124 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir))
1021 for path in sorted(self._path_to_emitter.keys()): 1125 for path in sorted(self._path_to_emitter.keys()):
1022 relpath = os.path.relpath(path, library_file_dir) 1126 relpath = os.path.relpath(path, library_file_dir)
1023 imports_emitter.Emit( 1127 imports_emitter.Emit(
1024 "#source('$PATH');\n", PATH=massage_path(relpath)) 1128 "#source('$PATH');\n", PATH=massage_path(relpath))
OLDNEW
« no previous file with comments | « lib/html/scripts/systembase.py ('k') | lib/html/scripts/systemnative.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698