| Index: pkg/compiler/lib/src/dart_backend/outputter.dart
 | 
| diff --git a/pkg/compiler/lib/src/dart_backend/outputter.dart b/pkg/compiler/lib/src/dart_backend/outputter.dart
 | 
| deleted file mode 100644
 | 
| index ce9022afe009326af0e269327da520c675426c0f..0000000000000000000000000000000000000000
 | 
| --- a/pkg/compiler/lib/src/dart_backend/outputter.dart
 | 
| +++ /dev/null
 | 
| @@ -1,576 +0,0 @@
 | 
| -// Copyright (c) 2014, 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.
 | 
| -
 | 
| -part of dart_backend;
 | 
| -
 | 
| -typedef bool IsSafeToRemoveTypeDeclarations(
 | 
| -    Map<ClassElement, Iterable<Element>> classMembers);
 | 
| -typedef void ElementCallback<E>(E element);
 | 
| -typedef void ElementPostProcessFunction(
 | 
| -    AstElement element,
 | 
| -    ElementAst elementAst,
 | 
| -    ElementCallback<TypedefElement> typedefCallback,
 | 
| -    ElementCallback<ClassElement> classCallback);
 | 
| -typedef ElementAst ComputeElementAstFunction(AstElement element);
 | 
| -typedef bool ElementFilter(Element element);
 | 
| -typedef List<Element> ElementSorter(Iterable<Element> elements);
 | 
| -
 | 
| -/// Output engine for dart2dart that is shared between the dart2js and the
 | 
| -/// analyzer implementations of dart2dart.
 | 
| -class DartOutputter {
 | 
| -  final DiagnosticReporter reporter;
 | 
| -  final CompilerOutputProvider outputProvider;
 | 
| -  final bool forceStripTypes;
 | 
| -
 | 
| -  // TODO(antonm): make available from command-line options.
 | 
| -  final bool outputAst = false;
 | 
| -  final bool enableMinification;
 | 
| -
 | 
| -  /// If `true`, libraries are generated into separate files.
 | 
| -  final bool multiFile;
 | 
| -
 | 
| -  /// Internal structures accessible for tests and logging.
 | 
| -  // TODO(johnniwinther): Clean this up.
 | 
| -  PlaceholderRenamer renamer;
 | 
| -  MainOutputGenerator output;
 | 
| -  LibraryInfo libraryInfo;
 | 
| -  ElementInfo elementInfo;
 | 
| -
 | 
| -  // TODO(johnniwinther): Support recompilation.
 | 
| -  DartOutputter(this.reporter, this.outputProvider,
 | 
| -      {bool this.forceStripTypes: false,
 | 
| -      bool this.enableMinification: false,
 | 
| -      bool this.multiFile: false});
 | 
| -
 | 
| -  /// Generate Dart code for the program starting at [mainFunction].
 | 
| -  ///
 | 
| -  /// [libraries] is the set of all libraries (user/package/sdk) that are
 | 
| -  /// referenced in the program.
 | 
| -  ///
 | 
| -  /// [instantiatedClasses] is the set of classes that are potentially
 | 
| -  /// instantiated in the program.
 | 
| -  ///
 | 
| -  /// [resolvedElements] is the set of methods, constructors, and fields that
 | 
| -  /// are potentially accessed/called in the program.
 | 
| -  ///
 | 
| -  /// The [sortElements] function is used to sort [instantiatedClasses] and
 | 
| -  /// [resolvedElements] in the generated output.
 | 
| -  ///
 | 
| -  /// Returns the total size of the generated code.
 | 
| -  int assembleProgram(
 | 
| -      {MirrorRenamer mirrorRenamer: const MirrorRenamer(),
 | 
| -      Iterable<LibraryElement> libraries,
 | 
| -      Iterable<Element> instantiatedClasses,
 | 
| -      Iterable<Element> resolvedElements,
 | 
| -      Iterable<ClassElement> usedTypeLiterals: const <ClassElement>[],
 | 
| -      FunctionElement mainFunction,
 | 
| -      Uri outputUri,
 | 
| -      ElementPostProcessFunction postProcessElementAst,
 | 
| -      ComputeElementAstFunction computeElementAst,
 | 
| -      ElementFilter shouldOutput,
 | 
| -      IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations,
 | 
| -      ElementSorter sortElements}) {
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, libraries != null,
 | 
| -        message: "'libraries' must be non-null."));
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, instantiatedClasses != null,
 | 
| -        message: "'instantiatedClasses' must be non-null."));
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, resolvedElements != null,
 | 
| -        message: "'resolvedElements' must be non-null."));
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, mainFunction != null,
 | 
| -        message: "'mainFunction' must be non-null."));
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, computeElementAst != null,
 | 
| -        message: "'computeElementAst' must be non-null."));
 | 
| -    assert(invariant(NO_LOCATION_SPANNABLE, shouldOutput != null,
 | 
| -        message: "'shouldOutput' must be non-null."));
 | 
| -    assert(invariant(
 | 
| -        NO_LOCATION_SPANNABLE, isSafeToRemoveTypeDeclarations != null,
 | 
| -        message: "'isSafeToRemoveTypeDeclarations' must be non-null."));
 | 
| -
 | 
| -    if (sortElements == null) {
 | 
| -      // Ensure deterministic output order.
 | 
| -      sortElements = (Iterable<Element> elements) {
 | 
| -        List<Element> list = elements.toList();
 | 
| -        list.sort((Element a, Element b) => a.name.compareTo(b.name));
 | 
| -        return list;
 | 
| -      };
 | 
| -    }
 | 
| -
 | 
| -    libraryInfo =
 | 
| -        LibraryInfo.processLibraries(reporter, libraries, resolvedElements);
 | 
| -
 | 
| -    elementInfo = ElementInfoProcessor.createElementInfo(
 | 
| -        instantiatedClasses, resolvedElements, usedTypeLiterals,
 | 
| -        postProcessElementAst: postProcessElementAst,
 | 
| -        parseElementAst: computeElementAst,
 | 
| -        shouldOutput: shouldOutput,
 | 
| -        sortElements: sortElements);
 | 
| -
 | 
| -    PlaceholderCollector collector = collectPlaceholders(
 | 
| -        reporter, mirrorRenamer, mainFunction, libraryInfo, elementInfo);
 | 
| -
 | 
| -    renamer = createRenamer(collector, libraryInfo, elementInfo,
 | 
| -        enableMinification: enableMinification,
 | 
| -        forceStripTypes: forceStripTypes,
 | 
| -        isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations);
 | 
| -
 | 
| -    if (outputAst) {
 | 
| -      String code = astOutput(reporter, elementInfo);
 | 
| -      outputProvider("", "dart")
 | 
| -        ..add(code)
 | 
| -        ..close();
 | 
| -      return code.length;
 | 
| -    } else {
 | 
| -      output = new MainOutputGenerator();
 | 
| -      return output.generateCode(libraryInfo, elementInfo, collector, renamer,
 | 
| -          mainFunction, outputUri, outputProvider, mirrorRenamer,
 | 
| -          multiFile: multiFile,
 | 
| -          forceStripTypes: forceStripTypes,
 | 
| -          enableMinification: enableMinification);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  static PlaceholderCollector collectPlaceholders(
 | 
| -      DiagnosticReporter reporter,
 | 
| -      MirrorRenamer mirrorRenamer,
 | 
| -      FunctionElement mainFunction,
 | 
| -      LibraryInfo libraryInfo,
 | 
| -      ElementInfo elementInfo) {
 | 
| -    // Create all necessary placeholders.
 | 
| -    PlaceholderCollector collector = new PlaceholderCollector(
 | 
| -        reporter,
 | 
| -        mirrorRenamer,
 | 
| -        libraryInfo.fixedDynamicNames,
 | 
| -        elementInfo.elementAsts,
 | 
| -        mainFunction);
 | 
| -
 | 
| -    makePlaceholders(element) {
 | 
| -      collector.collect(element);
 | 
| -
 | 
| -      if (element.isClass && !element.isEnumClass) {
 | 
| -        elementInfo.classMembers[element].forEach(makePlaceholders);
 | 
| -      }
 | 
| -    }
 | 
| -    elementInfo.topLevelElements.forEach(makePlaceholders);
 | 
| -    return collector;
 | 
| -  }
 | 
| -
 | 
| -  static PlaceholderRenamer createRenamer(PlaceholderCollector collector,
 | 
| -      LibraryInfo libraryInfo, ElementInfo elementInfo,
 | 
| -      {bool enableMinification: false,
 | 
| -      bool forceStripTypes: false,
 | 
| -      isSafeToRemoveTypeDeclarations}) {
 | 
| -    // Create renames.
 | 
| -    bool shouldCutDeclarationTypes = forceStripTypes ||
 | 
| -        (enableMinification &&
 | 
| -            isSafeToRemoveTypeDeclarations(elementInfo.classMembers));
 | 
| -
 | 
| -    PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer(
 | 
| -        libraryInfo.fixedDynamicNames,
 | 
| -        libraryInfo.fixedStaticNames,
 | 
| -        libraryInfo.reexportingLibraries,
 | 
| -        cutDeclarationTypes: shouldCutDeclarationTypes,
 | 
| -        enableMinification: enableMinification);
 | 
| -
 | 
| -    placeholderRenamer.computeRenames(collector);
 | 
| -    return placeholderRenamer;
 | 
| -  }
 | 
| -
 | 
| -  static String astOutput(
 | 
| -      DiagnosticReporter reporter, ElementInfo elementInfo) {
 | 
| -    // TODO(antonm): Ideally XML should be a separate backend.
 | 
| -    // TODO(antonm): obey renames and minification, at least as an option.
 | 
| -    StringBuffer sb = new StringBuffer();
 | 
| -    outputElement(element) {
 | 
| -      sb.write(element.parseNode(reporter).toDebugString());
 | 
| -    }
 | 
| -
 | 
| -    // Emit XML for AST instead of the program.
 | 
| -    for (Element topLevel in elementInfo.topLevelElements) {
 | 
| -      if (topLevel.isClass &&
 | 
| -          !elementInfo.emitNoMembersFor.contains(topLevel)) {
 | 
| -        // TODO(antonm): add some class info.
 | 
| -        elementInfo.classMembers[topLevel].forEach(outputElement);
 | 
| -      } else {
 | 
| -        outputElement(topLevel);
 | 
| -      }
 | 
| -    }
 | 
| -    return '<Program>\n$sb</Program>\n';
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -class LibraryInfo {
 | 
| -  final Set<String> fixedStaticNames;
 | 
| -  final Set<String> fixedDynamicNames;
 | 
| -  final Map<Element, LibraryElement> reexportingLibraries;
 | 
| -  final List<LibraryElement> userLibraries;
 | 
| -
 | 
| -  LibraryInfo(this.fixedStaticNames, this.fixedDynamicNames,
 | 
| -      this.reexportingLibraries, this.userLibraries);
 | 
| -
 | 
| -  static LibraryInfo processLibraries(
 | 
| -      DiagnosticReporter reporter,
 | 
| -      Iterable<LibraryElement> libraries,
 | 
| -      Iterable<AstElement> resolvedElements) {
 | 
| -    Set<String> fixedStaticNames = new Set<String>();
 | 
| -    Set<String> fixedDynamicNames = new Set<String>();
 | 
| -    Map<Element, LibraryElement> reexportingLibraries =
 | 
| -        <Element, LibraryElement>{};
 | 
| -    List<LibraryElement> userLibraries = <LibraryElement>[];
 | 
| -    // Conservatively traverse all platform libraries and collect member names.
 | 
| -    // TODO(antonm): ideally we should only collect names of used members,
 | 
| -    // however as of today there are problems with names of some core library
 | 
| -    // interfaces, most probably for interfaces of literals.
 | 
| -
 | 
| -    for (LibraryElement library in libraries) {
 | 
| -      if (!library.isPlatformLibrary) {
 | 
| -        userLibraries.add(library);
 | 
| -        continue;
 | 
| -      }
 | 
| -      library.forEachLocalMember((Element element) {
 | 
| -        if (element.isClass) {
 | 
| -          ClassElement classElement = element;
 | 
| -          assert(invariant(classElement, classElement.isResolved,
 | 
| -              message: "Unresolved platform class."));
 | 
| -          classElement.forEachLocalMember((member) {
 | 
| -            if (member.isInstanceMember) {
 | 
| -              fixedDynamicNames.add(member.name);
 | 
| -            } else {
 | 
| -              fixedStaticNames.add(member.name);
 | 
| -            }
 | 
| -          });
 | 
| -        }
 | 
| -        // Even class names are added due to a delicate problem we have:
 | 
| -        // if one imports dart:core with a prefix, we cannot tell prefix.name
 | 
| -        // from dynamic invocation (alas!).  So we'd better err on preserving
 | 
| -        // those names.
 | 
| -        fixedStaticNames.add(element.name);
 | 
| -      });
 | 
| -
 | 
| -      library.forEachExport((Element export) {
 | 
| -        if (!library.isInternalLibrary && export.library.isInternalLibrary) {
 | 
| -          // If an element of an internal library is reexported by a platform
 | 
| -          // library, we have to import the reexporting library instead of the
 | 
| -          // internal library, because the internal library is an
 | 
| -          // implementation detail of dart2js.
 | 
| -          reexportingLibraries[export] = library;
 | 
| -        }
 | 
| -      });
 | 
| -    }
 | 
| -
 | 
| -    // Map to keep track of names of enum classes. Since these cannot be renamed
 | 
| -    // we ensure that they are unique.
 | 
| -    Map<String, ClassElement> enumClassMap = <String, ClassElement>{};
 | 
| -
 | 
| -    // As of now names of named optionals are not renamed. Therefore add all
 | 
| -    // field names used as named optionals into [fixedMemberNames].
 | 
| -    for (final element in resolvedElements) {
 | 
| -      if (!element.isConstructor) continue;
 | 
| -      for (ParameterElement parameter in element.parameters) {
 | 
| -        if (parameter.isInitializingFormal && parameter.isNamed) {
 | 
| -          fixedDynamicNames.add(parameter.name);
 | 
| -        }
 | 
| -      }
 | 
| -      ClassElement cls = element.enclosingClass;
 | 
| -      if (cls != null && cls.isEnumClass) {
 | 
| -        fixedDynamicNames.add('index');
 | 
| -
 | 
| -        ClassElement existingEnumClass =
 | 
| -            enumClassMap.putIfAbsent(cls.name, () => cls);
 | 
| -        if (existingEnumClass != cls) {
 | 
| -          reporter.reportError(
 | 
| -              reporter.createMessage(cls, MessageKind.GENERIC, {
 | 
| -                'text': "Duplicate enum names are not supported "
 | 
| -                    "in dart2dart."
 | 
| -              }),
 | 
| -              <DiagnosticMessage>[
 | 
| -                reporter.createMessage(existingEnumClass, MessageKind.GENERIC, {
 | 
| -                  'text': "This is the other declaration of '${cls.name}'."
 | 
| -                }),
 | 
| -              ]);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    fixedStaticNames.addAll(enumClassMap.keys);
 | 
| -
 | 
| -    // The VM will automatically invoke the call method of objects
 | 
| -    // that are invoked as functions. Make sure to not rename that.
 | 
| -    fixedDynamicNames.add('call');
 | 
| -
 | 
| -    return new LibraryInfo(fixedStaticNames, fixedDynamicNames,
 | 
| -        reexportingLibraries, userLibraries);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -class ElementInfo {
 | 
| -  final Map<Element, ElementAst> elementAsts;
 | 
| -  final Iterable<Element> topLevelElements;
 | 
| -  final Map<ClassElement, Iterable<Element>> classMembers;
 | 
| -  final Iterable<ClassElement> emitNoMembersFor;
 | 
| -
 | 
| -  ElementInfo(this.elementAsts, this.topLevelElements, this.classMembers,
 | 
| -      this.emitNoMembersFor);
 | 
| -}
 | 
| -
 | 
| -class ElementInfoProcessor implements ElementInfo {
 | 
| -  final Map<Element, ElementAst> elementAsts = new Map<Element, ElementAst>();
 | 
| -  final Set<Element> topLevelElements = new Set<Element>();
 | 
| -  final Map<ClassElement, Set<Element>> classMembers =
 | 
| -      new Map<ClassElement, Set<Element>>();
 | 
| -  final Set<ClassElement> emitNoMembersFor = new Set<ClassElement>();
 | 
| -  final ElementPostProcessFunction postProcessElementAst;
 | 
| -  final ComputeElementAstFunction parseElementAst;
 | 
| -  final ElementFilter shouldOutput;
 | 
| -
 | 
| -  ElementInfoProcessor(
 | 
| -      {this.postProcessElementAst, this.parseElementAst, this.shouldOutput});
 | 
| -
 | 
| -  static ElementInfo createElementInfo(
 | 
| -      Iterable<ClassElement> instantiatedClasses,
 | 
| -      Iterable<AstElement> resolvedElements,
 | 
| -      Iterable<ClassElement> usedTypeLiterals,
 | 
| -      {ElementPostProcessFunction postProcessElementAst,
 | 
| -      ComputeElementAstFunction parseElementAst,
 | 
| -      ElementFilter shouldOutput,
 | 
| -      ElementSorter sortElements}) {
 | 
| -    ElementInfoProcessor processor = new ElementInfoProcessor(
 | 
| -        postProcessElementAst: postProcessElementAst,
 | 
| -        parseElementAst: parseElementAst,
 | 
| -        shouldOutput: shouldOutput);
 | 
| -    return processor.process(
 | 
| -        instantiatedClasses, resolvedElements, usedTypeLiterals,
 | 
| -        sortElements: sortElements);
 | 
| -  }
 | 
| -
 | 
| -  ElementInfo process(
 | 
| -      Iterable<ClassElement> instantiatedClasses,
 | 
| -      Iterable<AstElement> resolvedElements,
 | 
| -      Iterable<ClassElement> usedTypeLiterals,
 | 
| -      {ElementSorter sortElements}) {
 | 
| -    // Build all top level elements to emit and necessary class members.
 | 
| -    instantiatedClasses.where(shouldOutput).forEach(addClass);
 | 
| -    resolvedElements.where(shouldOutput).forEach(addMember);
 | 
| -    usedTypeLiterals.forEach((ClassElement element) {
 | 
| -      if (shouldOutput(element)) {
 | 
| -        if (!topLevelElements.contains(element)) {
 | 
| -          // The class is only referenced by type literals.
 | 
| -          emitNoMembersFor.add(element);
 | 
| -        }
 | 
| -        addClass(element);
 | 
| -      }
 | 
| -    });
 | 
| -
 | 
| -    // Sort elements.
 | 
| -    List<Element> sortedTopLevels = sortElements(topLevelElements);
 | 
| -    Map<ClassElement, List<Element>> sortedClassMembers =
 | 
| -        new Map<ClassElement, List<Element>>();
 | 
| -    classMembers.forEach((classElement, members) {
 | 
| -      sortedClassMembers[classElement] = sortElements(members);
 | 
| -    });
 | 
| -
 | 
| -    return new ElementInfo(
 | 
| -        elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor);
 | 
| -  }
 | 
| -
 | 
| -  void processElement(Element element, ElementAst elementAst) {
 | 
| -    if (postProcessElementAst != null) {
 | 
| -      postProcessElementAst(element, elementAst, newTypedefElementCallback,
 | 
| -          newClassElementCallback);
 | 
| -    }
 | 
| -    elementAsts[element] = elementAst;
 | 
| -  }
 | 
| -
 | 
| -  void addTopLevel(AstElement element, ElementAst elementAst) {
 | 
| -    if (topLevelElements.contains(element)) return;
 | 
| -    topLevelElements.add(element);
 | 
| -    processElement(element, elementAst);
 | 
| -  }
 | 
| -
 | 
| -  void addClass(ClassElement classElement) {
 | 
| -    TreeElements treeElements = new TreeElementMapping(classElement);
 | 
| -    backend2frontend.TreePrinter treePrinter =
 | 
| -        new backend2frontend.TreePrinter(treeElements);
 | 
| -    Node node = treePrinter.makeNodeForClassElement(classElement);
 | 
| -    addTopLevel(classElement, new ElementAst(node, treeElements));
 | 
| -    classMembers.putIfAbsent(classElement, () => new Set());
 | 
| -  }
 | 
| -
 | 
| -  void newTypedefElementCallback(TypedefElement element) {
 | 
| -    if (!shouldOutput(element)) return;
 | 
| -    TreeElements treeElements = new TreeElementMapping(element);
 | 
| -    backend2frontend.TreePrinter treePrinter =
 | 
| -        new backend2frontend.TreePrinter(treeElements);
 | 
| -    Node node = treePrinter.makeTypedef(element);
 | 
| -    addTopLevel(element, new ElementAst(node, treeElements));
 | 
| -  }
 | 
| -
 | 
| -  void newClassElementCallback(ClassElement classElement) {
 | 
| -    if (!shouldOutput(classElement)) return;
 | 
| -    addClass(classElement);
 | 
| -  }
 | 
| -
 | 
| -  void addMember(element) {
 | 
| -    if (element.isClassMember) {
 | 
| -      ClassElement enclosingClass = element.enclosingClass;
 | 
| -      assert(enclosingClass.isClass);
 | 
| -      assert(shouldOutput(enclosingClass));
 | 
| -      addClass(enclosingClass);
 | 
| -      classMembers[enclosingClass].add(element);
 | 
| -      if (enclosingClass.isEnumClass) return;
 | 
| -      processElement(element, parseElementAst(element));
 | 
| -    } else {
 | 
| -      if (element.isTopLevel) {
 | 
| -        addTopLevel(element, parseElementAst(element));
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/// Main output generator for [DartOutputter] that emits dart code through a
 | 
| -/// [CompilerOutputProvider].
 | 
| -class MainOutputGenerator {
 | 
| -  final Map<ClassNode, List<Node>> memberNodes =
 | 
| -      new Map<ClassNode, List<Node>>();
 | 
| -  final List<Node> topLevelNodes = <Node>[];
 | 
| -
 | 
| -  /// Generates the code and returns the total size.
 | 
| -  int generateCode(
 | 
| -      LibraryInfo libraryInfo,
 | 
| -      ElementInfo elementInfo,
 | 
| -      PlaceholderCollector collector,
 | 
| -      PlaceholderRenamer placeholderRenamer,
 | 
| -      FunctionElement mainFunction,
 | 
| -      Uri outputUri,
 | 
| -      CompilerOutputProvider outputProvider,
 | 
| -      MirrorRenamer mirrorRenamer,
 | 
| -      {bool multiFile: false,
 | 
| -      bool forceStripTypes: false,
 | 
| -      bool enableMinification: false}) {
 | 
| -    for (Element element in elementInfo.topLevelElements) {
 | 
| -      topLevelNodes.add(elementInfo.elementAsts[element].ast);
 | 
| -      if (element.isClass) {
 | 
| -        ClassElement cls = element;
 | 
| -        if (cls.isMixinApplication || cls.isEnumClass) {
 | 
| -          continue;
 | 
| -        }
 | 
| -        final members = <Node>[];
 | 
| -        for (Element member in elementInfo.classMembers[cls]) {
 | 
| -          members.add(elementInfo.elementAsts[member].ast);
 | 
| -        }
 | 
| -        memberNodes[elementInfo.elementAsts[cls].ast] = members;
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    mirrorRenamer.addRenames(
 | 
| -        placeholderRenamer.renames, topLevelNodes, collector);
 | 
| -
 | 
| -    Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>();
 | 
| -    Map<LibraryElement, EmitterUnparser> unparsers =
 | 
| -        new Map<LibraryElement, EmitterUnparser>();
 | 
| -
 | 
| -    // The single unparser used if we collect all the output in one file.
 | 
| -    EmitterUnparser mainUnparser = multiFile
 | 
| -        ? null
 | 
| -        : new EmitterUnparser(placeholderRenamer.renames,
 | 
| -            stripTypes: forceStripTypes, minify: enableMinification);
 | 
| -
 | 
| -    if (multiFile) {
 | 
| -      // TODO(sigurdm): Factor handling of library-paths out from emitting.
 | 
| -      String mainName = outputUri.pathSegments.last;
 | 
| -      String mainBaseName = mainName.endsWith(".dart")
 | 
| -          ? mainName.substring(0, mainName.length - 5)
 | 
| -          : mainName;
 | 
| -      // Map each library to a path based on the uri of the original
 | 
| -      // library and [compiler.options.outputUri].
 | 
| -      Set<String> usedLibraryPaths = new Set<String>();
 | 
| -      for (LibraryElement library in libraryInfo.userLibraries) {
 | 
| -        if (library == mainFunction.library) {
 | 
| -          outputPaths[library] = mainBaseName;
 | 
| -        } else {
 | 
| -          List<String> names =
 | 
| -              library.canonicalUri.pathSegments.last.split(".");
 | 
| -          if (names.last == "dart") {
 | 
| -            names = names.sublist(0, names.length - 1);
 | 
| -          }
 | 
| -          outputPaths[library] =
 | 
| -              "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}";
 | 
| -        }
 | 
| -      }
 | 
| -
 | 
| -      /// Rewrites imports/exports to refer to the paths given in [outputPaths].
 | 
| -      for (LibraryElement outputLibrary in libraryInfo.userLibraries) {
 | 
| -        EmitterUnparser unparser = new EmitterUnparser(
 | 
| -            placeholderRenamer.renames,
 | 
| -            stripTypes: forceStripTypes,
 | 
| -            minify: enableMinification);
 | 
| -        unparsers[outputLibrary] = unparser;
 | 
| -        if (outputLibrary.hasLibraryName) {
 | 
| -          unparser.unparseLibraryName(outputLibrary.libraryName);
 | 
| -        }
 | 
| -        for (ImportElement import in outputLibrary.imports) {
 | 
| -          LibraryElement libraryElement = import.importedLibrary;
 | 
| -          String uri = outputPaths.containsKey(libraryElement)
 | 
| -              ? "${outputPaths[libraryElement]}.dart"
 | 
| -              : libraryElement.canonicalUri.toString();
 | 
| -          unparser.unparseImportTag(uri);
 | 
| -        }
 | 
| -        for (ExportElement export in outputLibrary.exports) {
 | 
| -          LibraryElement libraryElement = export.exportedLibrary;
 | 
| -          String uri = outputPaths.containsKey(libraryElement)
 | 
| -              ? "${outputPaths[libraryElement]}.dart"
 | 
| -              : libraryElement.canonicalUri.toString();
 | 
| -          unparser.unparseExportTag(uri);
 | 
| -        }
 | 
| -      }
 | 
| -    } else {
 | 
| -      placeholderRenamer.platformImports
 | 
| -          .forEach((LibraryElement library, String prefix) {
 | 
| -        assert(library.isPlatformLibrary && !library.isInternalLibrary);
 | 
| -        mainUnparser.unparseImportTag(library.canonicalUri.toString());
 | 
| -        if (prefix != null) {
 | 
| -          // Adding a prefixed import because (some) top-level access need
 | 
| -          // it to avoid shadowing.
 | 
| -          // TODO(johnniwinther): Avoid prefix-less import if not needed.
 | 
| -          mainUnparser.unparseImportTag(library.canonicalUri.toString(),
 | 
| -              prefix: prefix);
 | 
| -        }
 | 
| -      });
 | 
| -    }
 | 
| -
 | 
| -    for (int i = 0; i < elementInfo.topLevelElements.length; i++) {
 | 
| -      Element element = elementInfo.topLevelElements.elementAt(i);
 | 
| -      Node node = topLevelNodes[i];
 | 
| -      Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser;
 | 
| -      if (node is ClassNode) {
 | 
| -        // TODO(smok): Filter out default constructors here.
 | 
| -        unparser.unparseClassWithBody(node, memberNodes[node]);
 | 
| -      } else {
 | 
| -        unparser.unparse(node);
 | 
| -      }
 | 
| -      unparser.newline();
 | 
| -    }
 | 
| -
 | 
| -    int totalSize = 0;
 | 
| -    if (multiFile) {
 | 
| -      for (LibraryElement outputLibrary in libraryInfo.userLibraries) {
 | 
| -        // TODO(sigurdm): Make the unparser output directly into the buffer
 | 
| -        // instead of caching in `.result`.
 | 
| -        String code = unparsers[outputLibrary].result;
 | 
| -        totalSize += code.length;
 | 
| -        outputProvider(outputPaths[outputLibrary], "dart")
 | 
| -          ..add(code)
 | 
| -          ..close();
 | 
| -      }
 | 
| -    } else {
 | 
| -      String code = mainUnparser.result;
 | 
| -      outputProvider("", "dart")
 | 
| -        ..add(code)
 | 
| -        ..close();
 | 
| -
 | 
| -      totalSize = code.length;
 | 
| -    }
 | 
| -
 | 
| -    return totalSize;
 | 
| -  }
 | 
| -}
 | 
| 
 |