| #!/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 |