|  | #!/usr/bin/python | 
|  | # Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | # for details. All rights reserved. Use of this source code is governed by a | 
|  | # BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | """This module generates Elemental APIs from the IDL database.""" | 
|  |  | 
|  | import emitter | 
|  | import idlnode | 
|  | import logging | 
|  | import multiemitter | 
|  | import os | 
|  | import re | 
|  | import shutil | 
|  | from generator_java import * | 
|  | from systembaseelemental import * | 
|  | from systemgwt import * | 
|  | from systemgwtjso import * | 
|  | from templateloader import TemplateLoader | 
|  |  | 
|  | _logger = logging.getLogger('elementalgenerator') | 
|  |  | 
|  | def MergeNodes(node, other): | 
|  | node.operations.extend(other.operations) | 
|  | for attribute in other.attributes: | 
|  | if not node.has_attribute(attribute): | 
|  | node.attributes.append(attribute) | 
|  |  | 
|  | node.constants.extend(other.constants) | 
|  |  | 
|  | class ElementalGenerator(object): | 
|  | """Utilities to generate Elemental APIs and corresponding JavaScript.""" | 
|  |  | 
|  | def __init__(self, auxiliary_dir, template_dir, base_package): | 
|  | """Constructor for the DartGenerator. | 
|  |  | 
|  | Args: | 
|  | auxiliary_dir -- location of auxiliary handwritten classes | 
|  | template_dir -- location of template files | 
|  | base_package -- the base package name for the generated code. | 
|  | """ | 
|  | self._auxiliary_dir = auxiliary_dir | 
|  | self._template_dir = template_dir | 
|  | self._base_package = base_package | 
|  | self._auxiliary_files = {} | 
|  | self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>') | 
|  |  | 
|  | self._emitters = None  # set later | 
|  |  | 
|  |  | 
|  | def _StripModules(self, type_name): | 
|  | return type_name.split('::')[-1] | 
|  |  | 
|  | def _IsCompoundType(self, database, type_name): | 
|  | if IsPrimitiveType(type_name): | 
|  | return True | 
|  |  | 
|  | striped_type_name = self._StripModules(type_name) | 
|  | if database.HasInterface(striped_type_name): | 
|  | return True | 
|  |  | 
|  | dart_template_match = self._dart_templates_re.match(type_name) | 
|  | if dart_template_match: | 
|  | # Dart templates | 
|  | parent_type_name = type_name[0 : dart_template_match.start(1) - 1] | 
|  | sub_type_name = dart_template_match.group(1) | 
|  | return (self._IsCompoundType(database, parent_type_name) and | 
|  | self._IsCompoundType(database, sub_type_name)) | 
|  | return False | 
|  |  | 
|  | def _IsDartType(self, type_name): | 
|  | return '.' in type_name | 
|  |  | 
|  | def LoadAuxiliary(self): | 
|  | def Visitor(_, dirname, names): | 
|  | for name in names: | 
|  | if name.endswith('.dart'): | 
|  | name = name[0:-5]  # strip off ".dart" | 
|  | self._auxiliary_files[name] = os.path.join(dirname, name) | 
|  | os.path.walk(self._auxiliary_dir, Visitor, None) | 
|  |  | 
|  | def RenameTypes(self, database, conversion_table, rename_javascript_binding_names): | 
|  | """Renames interfaces using the given conversion table. | 
|  |  | 
|  | References through all interfaces will be renamed as well. | 
|  |  | 
|  | Args: | 
|  | database: the database to apply the renames to. | 
|  | conversion_table: maps old names to new names. | 
|  | """ | 
|  |  | 
|  | if conversion_table is None: | 
|  | conversion_table = {} | 
|  |  | 
|  | # Rename interfaces: | 
|  | for old_name, new_name in conversion_table.items(): | 
|  | if database.HasInterface(old_name): | 
|  | _logger.info('renaming interface %s to %s' % (old_name, new_name)) | 
|  | interface = database.GetInterface(old_name) | 
|  | database.DeleteInterface(old_name) | 
|  | if not database.HasInterface(new_name): | 
|  | interface.id = new_name | 
|  | database.AddInterface(interface) | 
|  | else: | 
|  | new_interface = database.GetInterface(new_name) | 
|  | MergeNodes(new_interface, interface) | 
|  |  | 
|  | if rename_javascript_binding_names: | 
|  | interface.javascript_binding_name = new_name | 
|  | interface.doc_js_name = new_name | 
|  | for member in (interface.operations + interface.constants | 
|  | + interface.attributes): | 
|  | member.doc_js_interface_name = new_name | 
|  |  | 
|  |  | 
|  | # Fix references: | 
|  | for interface in database.GetInterfaces(): | 
|  | for idl_type in interface.all(idlnode.IDLType): | 
|  | type_name = self._StripModules(idl_type.id) | 
|  | if type_name in conversion_table: | 
|  | idl_type.id = conversion_table[type_name] | 
|  |  | 
|  | def FilterMembersWithUnidentifiedTypes(self, database): | 
|  | """Removes unidentified types. | 
|  |  | 
|  | Removes constants, attributes, operations and parents with unidentified | 
|  | types. | 
|  | """ | 
|  |  | 
|  | for interface in database.GetInterfaces(): | 
|  | def IsIdentified(idl_node): | 
|  | node_name = idl_node.id if idl_node.id else 'parent' | 
|  | for idl_type in idl_node.all(idlnode.IDLType): | 
|  | type_name = idl_type.id | 
|  | if (type_name is not None and | 
|  | self._IsCompoundType(database, type_name)): | 
|  | continue | 
|  | _logger.warn('removing %s in %s which has unidentified type %s' % | 
|  | (node_name, interface.id, type_name)) | 
|  | return False | 
|  | return True | 
|  |  | 
|  | interface.constants = filter(IsIdentified, interface.constants) | 
|  | interface.attributes = filter(IsIdentified, interface.attributes) | 
|  | interface.operations = filter(IsIdentified, interface.operations) | 
|  | interface.parents = filter(IsIdentified, interface.parents) | 
|  |  | 
|  | def FilterInterfaces(self, database, | 
|  | and_annotations=[], | 
|  | or_annotations=[], | 
|  | exclude_displaced=[], | 
|  | exclude_suppressed=[]): | 
|  | """Filters a database to remove interfaces and members that are missing | 
|  | annotations. | 
|  |  | 
|  | The FremontCut IDLs use annotations to specify implementation | 
|  | status in various platforms. For example, if a member is annotated | 
|  | with @WebKit, this means that the member is supported by WebKit. | 
|  |  | 
|  | Args: | 
|  | database -- the database to filter | 
|  | all_annotations -- a list of annotation names a member has to | 
|  | have or it will be filtered. | 
|  | or_annotations -- if a member has one of these annotations, it | 
|  | won't be filtered even if it is missing some of the | 
|  | all_annotations. | 
|  | exclude_displaced -- if a member has this annotation and it | 
|  | is marked as displaced it will always be filtered. | 
|  | exclude_suppressed -- if a member has this annotation and it | 
|  | is marked as suppressed it will always be filtered. | 
|  | """ | 
|  |  | 
|  | # Filter interfaces and members whose annotations don't match. | 
|  | for interface in database.GetInterfaces(): | 
|  | def HasAnnotations(idl_node): | 
|  | """Utility for determining if an IDLNode has all | 
|  | the required annotations""" | 
|  | for a in exclude_displaced: | 
|  | if (a in idl_node.annotations | 
|  | and 'via' in idl_node.annotations[a]): | 
|  | return False | 
|  | for a in exclude_suppressed: | 
|  | if (a in idl_node.annotations | 
|  | and 'suppressed' in idl_node.annotations[a]): | 
|  | return False | 
|  | for a in or_annotations: | 
|  | if a in idl_node.annotations: | 
|  | return True | 
|  | if and_annotations == []: | 
|  | return False | 
|  | for a in and_annotations: | 
|  | if a not in idl_node.annotations: | 
|  | return False | 
|  | return True | 
|  |  | 
|  | if HasAnnotations(interface): | 
|  | interface.constants = filter(HasAnnotations, interface.constants) | 
|  | interface.attributes = filter(HasAnnotations, interface.attributes) | 
|  | interface.operations = filter(HasAnnotations, interface.operations) | 
|  | interface.parents = filter(HasAnnotations, interface.parents) | 
|  | else: | 
|  | database.DeleteInterface(interface.id) | 
|  |  | 
|  | self.FilterMembersWithUnidentifiedTypes(database) | 
|  |  | 
|  |  | 
|  | def Generate(self, database, output_dir, | 
|  | module_source_preference=[], source_filter=None, | 
|  | super_database=None, common_prefix=None, super_map={}, | 
|  | html_map={}, lib_dir=None, systems=[]): | 
|  | """Generates Dart and JS files for the loaded interfaces. | 
|  |  | 
|  | Args: | 
|  | database -- database containing interfaces to generate code for. | 
|  | output_dir -- directory to write generated files to. | 
|  | module_source_preference -- priority order list of source annotations to | 
|  | use when choosing a module name, if none specified uses the module name | 
|  | from the database. | 
|  | source_filter -- if specified, only outputs interfaces that have one of | 
|  | these source annotation and rewrites the names of superclasses not | 
|  | marked with this source to use the common prefix. | 
|  | super_database -- database containing super interfaces that the generated | 
|  | interfaces should extend. | 
|  | common_prefix -- prefix for the common library, if any. | 
|  | lib_file_path -- filename for generated .lib file, None if not required. | 
|  | lib_template -- template file in this directory for generated lib file. | 
|  | """ | 
|  |  | 
|  | self._emitters = multiemitter.MultiEmitter() | 
|  | self._database = database | 
|  | self._output_dir = output_dir | 
|  |  | 
|  | self._FixEventTargets() | 
|  | self._ComputeInheritanceClosure() | 
|  |  | 
|  | self._systems = [] | 
|  |  | 
|  | # TODO(jmesserly): only create these if needed | 
|  | if ('gwtjso' in systems): | 
|  | jso_system = ElementalJsoSystem( | 
|  | TemplateLoader(self._template_dir, ['dom/jso', 'dom', '']), | 
|  | self._database, self._emitters, self._output_dir) | 
|  | self._systems.append(jso_system) | 
|  | if ('gwt' in systems): | 
|  | interface_system = ElementalInterfacesSystem( | 
|  | TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | 
|  | self._database, self._emitters, self._output_dir) | 
|  | self._systems.append(interface_system) | 
|  |  | 
|  | #    if 'gwt' in systems: | 
|  | #      elemental_system = ElementalSystem( | 
|  | #          TemplateLoader(self._template_dir, ['dom/elemental', 'dom', '']), | 
|  | #          self._database, self._emitters, self._output_dir) | 
|  |  | 
|  | #      elemental_system._interface_system = interface_system | 
|  | #      self._systems.append(elemental_system) | 
|  |  | 
|  |  | 
|  |  | 
|  | # Collect interfaces | 
|  | interfaces = [] | 
|  | for interface in database.GetInterfaces(): | 
|  | if not MatchSourceFilter(source_filter, interface): | 
|  | # Skip this interface since it's not present in the required source | 
|  | _logger.info('Omitting interface - %s' % interface.id) | 
|  | continue | 
|  | interfaces.append(interface) | 
|  |  | 
|  | # TODO(sra): Use this list of exception names to generate information to | 
|  | # tell Frog which exceptions can be passed from JS to Dart code. | 
|  | exceptions = self._CollectExceptions(interfaces) | 
|  |  | 
|  | mixins = self._ComputeMixins(self._PreOrderInterfaces(interfaces)) | 
|  | for system in self._systems: | 
|  | # give outputters a chance to see the mixin list before starting | 
|  | system.ProcessMixins(mixins) | 
|  |  | 
|  | # copy all mixin methods from every interface to this base interface | 
|  | self.PopulateMixinBase(self._database.GetInterface('ElementalMixinBase'), mixins) | 
|  |  | 
|  | # Render all interfaces into Dart and save them in files. | 
|  | for interface in self._PreOrderInterfaces(interfaces): | 
|  |  | 
|  | super_interface = None | 
|  | super_name = interface.id | 
|  |  | 
|  | if super_name in super_map: | 
|  | super_name = super_map[super_name] | 
|  |  | 
|  | if (super_database is not None and | 
|  | super_database.HasInterface(super_name)): | 
|  | super_interface = super_name | 
|  |  | 
|  | interface_name = interface.id | 
|  | auxiliary_file = self._auxiliary_files.get(interface_name) | 
|  | if auxiliary_file is not None: | 
|  | _logger.info('Skipping %s because %s exists' % ( | 
|  | interface_name, auxiliary_file)) | 
|  | continue | 
|  |  | 
|  | info = RecognizeCallback(interface) | 
|  | if info: | 
|  | for system in self._systems: | 
|  | system.ProcessCallback(interface, info) | 
|  | else: | 
|  | if 'Callback' in interface.ext_attrs: | 
|  | _logger.info('Malformed callback: %s' % interface.id) | 
|  | self._ProcessInterface(interface, super_interface, | 
|  | source_filter, common_prefix) | 
|  |  | 
|  | for system in self._systems: | 
|  | system.Finish() | 
|  |  | 
|  | def PopulateMixinBase(self, mixinbase, mixins): | 
|  | """Copy all mixin attributes and operations to mixin base class""" | 
|  | for mixin_name in mixins: | 
|  | if self._database.HasInterface(mixin_name): | 
|  | mixin = self._database.GetInterface(mixin_name) | 
|  | mixinbase.attributes.extend(mixin.attributes) | 
|  | mixinbase.operations.extend(mixin.operations) | 
|  | for extattr in mixin.ext_attrs.keys(): | 
|  | mixinbase.ext_attrs[extattr] = mixin.ext_attrs[extattr] | 
|  |  | 
|  | # compute all interfaces which are in disjoint type hierarchies | 
|  | # that is, cannot be SingleImplJSO without hoisting | 
|  | def _ComputeMixins(self, interfaces): | 
|  | implementors = {} | 
|  | mixins = {} | 
|  | parents = {} | 
|  | # first compute the set of all inherited super-interfaces of every interface | 
|  | for interface in interfaces: | 
|  | if interface.parents: | 
|  | # the first parent interface is the superclass | 
|  | parent = interface.parents[0] | 
|  | # if we haven't processed this one before | 
|  | if not interface.id in parents: | 
|  | # compute a list of all of the direct superclass this interface | 
|  | parents[interface.id] = [] | 
|  | parents[interface.id].append(parent) | 
|  | if parent.type.id in parents: | 
|  | # inherit all the super-interfaces | 
|  | parents[interface.id].extend(parents[parent.type.id]) | 
|  |  | 
|  | implemented_by = None | 
|  | for interface in interfaces: | 
|  | # now, examining secondary interfaces | 
|  | for secondary in interface.parents[1:]: | 
|  | if secondary.type.id in implementors: | 
|  | implemented_by = implementors[secondary.type.id] | 
|  | # if the interface is implemented by someone else who is not one of my parents, it is not SingleJsoImpl | 
|  | if not implemented_by in parents[interface.id]: | 
|  | mixins[secondary.type.id]=implemented_by | 
|  | print "Mixin detected %s, previously implemented by %s, but also implemented by %s" % (secondary.type.id, implemented_by, interface.id) | 
|  | # add all parents of the mixin as well | 
|  | superparents = [] | 
|  | superiface = secondary.type.id | 
|  | if self._database.HasInterface(superiface): | 
|  | self.getParents(self._database.GetInterface(superiface), superparents) | 
|  | for parent in superparents: | 
|  | mixins[parent.id]=implemented_by | 
|  | print "Super Mixin detected %s, previously implemented by %s, but also implemented by %s" % (parent.id, implemented_by, interface.id) | 
|  |  | 
|  | else: | 
|  | implementors[secondary.type.id] = interface.id | 
|  | # manual patch for outliers not picked up by this logic | 
|  | mixins['ElementTimeControl']=1 | 
|  | mixins['ElementTraversal']=1 | 
|  | return mixins.keys() | 
|  |  | 
|  | def _PreOrderInterfaces(self, interfaces): | 
|  | """Returns the interfaces in pre-order, i.e. parents first.""" | 
|  | seen = set() | 
|  | ordered = [] | 
|  | def visit(interface): | 
|  | if interface.id in seen: | 
|  | return | 
|  | seen.add(interface.id) | 
|  | for parent in interface.parents: | 
|  | if IsDartCollectionType(parent.type.id): | 
|  | continue | 
|  | if self._database.HasInterface(parent.type.id): | 
|  | parent_interface = self._database.GetInterface(parent.type.id) | 
|  | visit(parent_interface) | 
|  | ordered.append(interface) | 
|  |  | 
|  | for interface in interfaces: | 
|  | visit(interface) | 
|  | return ordered | 
|  |  | 
|  |  | 
|  | def _ProcessInterface(self, interface, super_interface_name, | 
|  | source_filter, | 
|  | common_prefix): | 
|  | """.""" | 
|  |  | 
|  | _logger.info('Generating %s' % interface.id) | 
|  |  | 
|  | generators = [system.InterfaceGenerator(interface, | 
|  | common_prefix, | 
|  | super_interface_name, | 
|  | source_filter) | 
|  | for system in self._systems] | 
|  | generators = filter(None, generators) | 
|  |  | 
|  |  | 
|  | mixinbase = self._database.GetInterface("ElementalMixinBase") | 
|  | parentops = [] | 
|  | parentattrs = [] | 
|  |  | 
|  |  | 
|  | directParents = [] | 
|  | mixinOps = [] | 
|  | # compute the immediate parents of each interface (not including secondary interfaces) | 
|  | self.getParents(interface, directParents) | 
|  |  | 
|  | # if not the mixin base, add its parents | 
|  | if interface.id != 'ElementalMixinBase': | 
|  | self.getParents(mixinbase, directParents) | 
|  | # add the mixin base class itself as the parent of everything | 
|  | directParents.insert(0, mixinbase) | 
|  |  | 
|  | # for each parent interface | 
|  | for pint in directParents: | 
|  | for op in pint.operations: | 
|  | # compute unique method signatures for each operation                                                                                                           : | 
|  | op_name = op.ext_attrs.get('DartName', op.id) | 
|  | sig = "%s %s(" % (op.type.id, op_name) | 
|  | for arg in op.arguments: | 
|  | sig += arg.type.id | 
|  | parentops.append(sig) | 
|  | for attr in pint.attributes: | 
|  | # compute attributes | 
|  | if attr.is_fc_getter: | 
|  | parentattrs.append("getter_" + DartDomNameOfAttribute(attr)) | 
|  | if attr.is_fc_setter: | 
|  | parentattrs.append("setter_" + DartDomNameOfAttribute(attr)) | 
|  |  | 
|  | for generator in generators: | 
|  | generator.StartInterface() | 
|  |  | 
|  | for const in sorted(interface.constants, ConstantOutputOrder): | 
|  | for generator in generators: | 
|  | generator.AddConstant(const) | 
|  |  | 
|  | attributes = [attr for attr in interface.attributes] | 
|  |  | 
|  | for (getter, setter) in  _PairUpAttributes(attributes): | 
|  | for generator in generators: | 
|  | # detect if attribute is inherited (as opposed to just redeclared) | 
|  | inheritedGetter = ("getter_" + DartDomNameOfAttribute(getter)) in parentattrs | 
|  | inheritedSetter = setter and ("setter_" + DartDomNameOfAttribute(setter)) in parentattrs | 
|  | generator.AddAttribute(getter, setter, inheritedGetter, inheritedSetter) | 
|  |  | 
|  | # The implementation should define an indexer if the interface directly | 
|  | # extends List. | 
|  | element_type = MaybeListElementType(interface) | 
|  | if element_type: | 
|  | for generator in generators: | 
|  | generator.AddIndexer(element_type) | 
|  |  | 
|  | # Generate operations | 
|  | alreadyGenerated = [] | 
|  | for operation in interface.operations: | 
|  | op_name = operation.ext_attrs.get('DartName', operation.id) | 
|  | sig = "%s %s(" % (operation.type.id, op_name) | 
|  | for arg in operation.arguments: | 
|  | sig += arg.type.id | 
|  | if sig in alreadyGenerated: | 
|  | continue | 
|  | alreadyGenerated.append(sig) | 
|  |  | 
|  | # hacks, should be able to compute this from IDL database | 
|  | if operation.id == 'toString': | 
|  | # implemented on JSO.toString() | 
|  | continue | 
|  | operations = [] | 
|  | operations.append(operation) | 
|  | info = AnalyzeOperation(interface, operations) | 
|  | for generator in generators: | 
|  | # don't override stuff hoisted to mixin base in implementors | 
|  | inherited = sig in parentops | 
|  | if info.IsStatic(): | 
|  | generator.AddStaticOperation(info, inherited) | 
|  | else: | 
|  | generator.AddOperation(info, inherited) | 
|  |  | 
|  | # With multiple inheritance, attributes and operations of non-first | 
|  | # interfaces need to be added.  Sometimes the attribute or operation is | 
|  | # defined in the current interface as well as a parent.  In that case we | 
|  | # avoid making a duplicate definition and pray that the signatures match. | 
|  |  | 
|  | for parent_interface in self._TransitiveSecondaryParents(interface): | 
|  | if isinstance(parent_interface, str):  # IsDartCollectionType(parent_interface) | 
|  | continue | 
|  | attributes = [attr for attr in parent_interface.attributes | 
|  | if not FindMatchingAttribute(interface, attr)] | 
|  | for (getter, setter) in _PairUpAttributes(attributes): | 
|  | for generator in generators: | 
|  | generator.AddSecondaryAttribute(parent_interface, getter, setter) | 
|  |  | 
|  | # Group overloaded operations by id | 
|  | operationsById = {} | 
|  | for operation in parent_interface.operations: | 
|  | if operation.id not in operationsById: | 
|  | operationsById[operation.id] = [] | 
|  | operationsById[operation.id].append(operation) | 
|  |  | 
|  | # Generate operations | 
|  | for id in sorted(operationsById.keys()): | 
|  | if not any(op.id == id for op in interface.operations): | 
|  | operations = operationsById[id] | 
|  | info = AnalyzeOperation(interface, operations) | 
|  | for generator in generators: | 
|  | generator.AddSecondaryOperation(parent_interface, info) | 
|  |  | 
|  | for generator in generators: | 
|  | generator.FinishInterface() | 
|  | return | 
|  |  | 
|  | def getParents(self, interface, results): | 
|  | if interface.parents: | 
|  | pid = interface.parents[0].type.id | 
|  | if self._database.HasInterface(pid): | 
|  | pint = self._database.GetInterface(interface.parents[0].type.id) | 
|  | results.append(pint) | 
|  | self.getParents(pint, results) | 
|  |  | 
|  | def _TransitiveSecondaryParents(self, interface): | 
|  | """Returns a list of all non-primary parents. | 
|  |  | 
|  | The list contains the interface objects for interfaces defined in the | 
|  | database, and the name for undefined interfaces. | 
|  | """ | 
|  | def walk(parents): | 
|  | for parent in parents: | 
|  | if IsDartCollectionType(parent.type.id): | 
|  | result.append(parent.type.id) | 
|  | continue | 
|  | if self._database.HasInterface(parent.type.id): | 
|  | parent_interface = self._database.GetInterface(parent.type.id) | 
|  | result.append(parent_interface) | 
|  | walk(parent_interface.parents) | 
|  |  | 
|  | result = [] | 
|  | walk(interface.parents[1:]) | 
|  | return result; | 
|  |  | 
|  |  | 
|  | def _CollectExceptions(self, interfaces): | 
|  | """Returns the names of all exception classes raised.""" | 
|  | exceptions = set() | 
|  | for interface in interfaces: | 
|  | for attribute in interface.attributes: | 
|  | if attribute.get_raises: | 
|  | exceptions.add(attribute.get_raises.id) | 
|  | if attribute.set_raises: | 
|  | exceptions.add(attribute.set_raises.id) | 
|  | for operation in interface.operations: | 
|  | if operation.raises: | 
|  | exceptions.add(operation.raises.id) | 
|  | return exceptions | 
|  |  | 
|  |  | 
|  | def Flush(self): | 
|  | """Write out all pending files.""" | 
|  | _logger.info('Flush...') | 
|  | self._emitters.Flush() | 
|  |  | 
|  | def _FixEventTargets(self): | 
|  | for interface in self._database.GetInterfaces(): | 
|  | # Create fake EventTarget parent interface for interfaces that have | 
|  | # 'EventTarget' extended attribute. | 
|  | if 'EventTarget' in interface.ext_attrs: | 
|  | ast = [('Annotation', [('Id', 'WebKit')]), | 
|  | ('InterfaceType', ('ScopedName', 'EventTarget'))] | 
|  | interface.parents.append(idlnode.IDLParentInterface(ast)) | 
|  |  | 
|  | def _ComputeInheritanceClosure(self): | 
|  | def Collect(interface, seen, collected): | 
|  | name = interface.id | 
|  | if '<' in name: | 
|  | # TODO(sra): Handle parameterized types. | 
|  | return | 
|  | if not name in seen: | 
|  | seen.add(name) | 
|  | collected.append(name) | 
|  | for parent in interface.parents: | 
|  | # TODO(sra): Handle parameterized types. | 
|  | if not '<' in parent.type.id: | 
|  | if self._database.HasInterface(parent.type.id): | 
|  | Collect(self._database.GetInterface(parent.type.id), | 
|  | seen, collected) | 
|  |  | 
|  | self._inheritance_closure = {} | 
|  | for interface in self._database.GetInterfaces(): | 
|  | seen = set() | 
|  | collected = [] | 
|  | Collect(interface, seen, collected) | 
|  | self._inheritance_closure[interface.id] = collected | 
|  |  | 
|  | def _AllImplementedInterfaces(self, interface): | 
|  | """Returns a list of the names of all interfaces implemented by 'interface'. | 
|  | List includes the name of 'interface'. | 
|  | """ | 
|  | return self._inheritance_closure[interface.id] | 
|  |  | 
|  | def _PairUpAttributes(attributes): | 
|  | """Returns a list of (getter, setter) pairs sorted by name. | 
|  |  | 
|  | One element of the pair may be None. | 
|  | """ | 
|  | names = sorted(set(attr.id for attr in attributes)) | 
|  | getters = {} | 
|  | setters = {} | 
|  | for attr in attributes: | 
|  | if attr.is_fc_getter: | 
|  | getters[attr.id] = attr | 
|  | elif attr.is_fc_setter and 'Replaceable' not in attr.ext_attrs: | 
|  | setters[attr.id] = attr | 
|  | return [(getters.get(id), setters.get(id)) for id in names] | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | class DummyImplementationSystem(SystemElemental): | 
|  | """Generates a dummy implementation for use by the editor analysis. | 
|  |  | 
|  | All the code comes from hand-written library files. | 
|  | """ | 
|  |  | 
|  | def __init__(self, templates, database, emitters, output_dir): | 
|  | super(DummyImplementationSystem, self).__init__( | 
|  | templates, database, emitters, output_dir) | 
|  | factory_providers_file = os.path.join(self._output_dir, 'src', 'dummy', | 
|  | 'RegularFactoryProviders.dart') | 
|  | self._factory_providers_emitter = self._emitters.FileEmitter( | 
|  | factory_providers_file) | 
|  | self._impl_file_paths = [factory_providers_file] | 
|  |  | 
|  | def InterfaceGenerator(self, | 
|  | interface, | 
|  | common_prefix, | 
|  | super_interface_name, | 
|  | source_filter): | 
|  | return DummyInterfaceGenerator(self, interface) | 
|  |  | 
|  | def ProcessCallback(self, interface, info): | 
|  | pass | 
|  |  | 
|  | def GenerateLibraries(self, lib_dir): | 
|  | # Library generated for implementation. | 
|  | self._GenerateLibFile( | 
|  | 'dom_dummy.darttemplate', | 
|  | os.path.join(lib_dir, 'dom_dummy.dart'), | 
|  | (self._interface_system._dart_interface_file_paths + | 
|  | self._interface_system._dart_callback_file_paths + | 
|  | self._impl_file_paths)) | 
|  |  | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | class DummyInterfaceGenerator(object): | 
|  | """Generates dummy implementation.""" | 
|  |  | 
|  | def __init__(self, system, interface): | 
|  | self._system = system | 
|  | self._interface = interface | 
|  |  | 
|  | def StartInterface(self): | 
|  | # There is no implementation to match the interface, but there might be a | 
|  | # factory constructor for the Dart interface. | 
|  | constructor_info = AnalyzeConstructor(self._interface) | 
|  | if constructor_info: | 
|  | dart_interface_name = self._interface.id | 
|  | self._EmitFactoryProvider(dart_interface_name, constructor_info) | 
|  |  | 
|  | def _EmitFactoryProvider(self, interface_name, constructor_info): | 
|  | factory_provider = '_' + interface_name + 'FactoryProvider' | 
|  | self._system._factory_providers_emitter.Emit( | 
|  | self._system._templates.Load('factoryprovider.darttemplate'), | 
|  | FACTORYPROVIDER=factory_provider, | 
|  | CONSTRUCTOR=interface_name, | 
|  | PARAMETERS=constructor_info.ParametersImplementationDeclaration()) | 
|  |  | 
|  | def FinishInterface(self): | 
|  | pass | 
|  |  | 
|  | def AddConstant(self, constant): | 
|  | pass | 
|  |  | 
|  | def AddAttribute(self, getter, setter, inheritedGetter, inheritedSetter): | 
|  | pass | 
|  |  | 
|  | def AddSecondaryAttribute(self, interface, getter, setter): | 
|  | pass | 
|  |  | 
|  | def AddSecondaryOperation(self, interface, info): | 
|  | pass | 
|  |  | 
|  | def AddIndexer(self, element_type): | 
|  | pass | 
|  |  | 
|  | def AddTypedArrayConstructors(self, element_type): | 
|  | pass | 
|  |  | 
|  | def AddOperation(self, info, inherited): | 
|  | pass | 
|  |  | 
|  | def AddStaticOperation(self, info, inherited): | 
|  | pass | 
|  |  | 
|  | def AddEventAttributes(self, event_attrs): | 
|  | pass |