// 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.

library dart2js.library_loader;

import 'dart:async';

import 'common.dart';
import 'common/names.dart' show Uris;
import 'common/tasks.dart' show CompilerTask;
import 'compiler.dart' show Compiler;
import 'elements/elements.dart'
    show
        CompilationUnitElement,
        Element,
        ImportElement,
        ExportElement,
        LibraryElement,
        PrefixElement;
import 'elements/modelx.dart'
    show
        CompilationUnitElementX,
        DeferredLoaderGetterElementX,
        ErroneousElementX,
        ExportElementX,
        ImportElementX,
        LibraryElementX,
        LibraryDependencyElementX,
        PrefixElementX,
        SyntheticImportElement;
import 'environment.dart';
import 'script.dart';
import 'serialization/serialization.dart' show LibraryDeserializer;
import 'tree/tree.dart';
import 'util/util.dart' show Link, LinkBuilder;

/**
 * [CompilerTask] for loading libraries and setting up the import/export scopes.
 *
 * The library loader uses four different kinds of URIs in different parts of
 * the loading process.
 *
 * ## User URI ##
 *
 * A 'user URI' is a URI provided by the user in code and as the main entry URI
 * at the command line. These generally come in 3 versions:
 *
 *   * A relative URI such as 'foo.dart', '../bar.dart', and 'baz/boz.dart'.
 *
 *   * A dart URI such as 'dart:core' and 'dart:_js_helper'.
 *
 *   * A package URI such as 'package:foo.dart' and 'package:bar/baz.dart'.
 *
 * A user URI can also be absolute, like 'file:///foo.dart' or
 * 'http://example.com/bar.dart', but such URIs cannot necessarily be used for
 * locating source files, since the scheme must be supported by the input
 * provider. The standard input provider for dart2js only supports the 'file'
 * and 'http' scheme.
 *
 * ## Resolved URI ##
 *
 * A 'resolved URI' is a (user) URI that has been resolved to an absolute URI
 * based on the readable URI (see below) from which it was loaded. A URI with an
 * explicit scheme (such as 'dart:', 'package:' or 'file:') is already resolved.
 * A relative URI like for instance '../foo/bar.dart' is translated into an
 * resolved URI in one of three ways:
 *
 *  * If provided as the main entry URI at the command line, the URI is resolved
 *    relative to the current working directory, say
 *    'file:///current/working/dir/', and the resolved URI is therefore
 *    'file:///current/working/foo/bar.dart'.
 *
 *  * If the relative URI is provided in an import, export or part tag, and the
 *    readable URI of the enclosing compilation unit is a file URI,
 *    'file://some/path/baz.dart', then the resolved URI is
 *    'file://some/foo/bar.dart'.
 *
 *  * If the relative URI is provided in an import, export or part tag, and the
 *    readable URI of the enclosing compilation unit is a package URI,
 *    'package:some/path/baz.dart', then the resolved URI is
 *    'package:some/foo/bar.dart'.
 *
 * The resolved URI thus preserves the scheme through resolution: A readable
 * file URI results in an resolved file URI and a readable package URI results
 * in an resolved package URI. Note that since a dart URI is not a readable URI,
 * import, export or part tags within platform libraries are not interpreted as
 * dart URIs but instead relative to the library source file location.
 *
 * The resolved URI of a library is also used as the canonical URI
 * ([LibraryElement.canonicalUri]) by which we identify which libraries are
 * identical. This means that libraries loaded through the 'package' scheme will
 * resolve to the same library when loaded from within using relative URIs (see
 * for instance the test 'standalone/package/package1_test.dart'). But loading a
 * platform library using a relative URI will _not_ result in the same library
 * as when loaded through the dart URI.
 *
 * ## Readable URI ##
 *
 * A 'readable URI' is an absolute URI whose scheme is either 'package' or
 * something supported by the input provider, normally 'file'. Dart URIs such as
 * 'dart:core' and 'dart:_js_helper' are not readable themselves but are instead
 * resolved into a readable URI using the library root URI provided from the
 * command line and the list of platform libraries found in
 * 'sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'. This is done
 * through a [ResolvedUriTranslator] provided from the compiler. The translator
 * checks whether a library by that name exists and in case of internal
 * libraries whether access is granted.
 *
 * ## Resource URI ##
 *
 * A 'resource URI' is an absolute URI with a scheme supported by the input
 * provider. For the standard implementation this means a URI with the 'file'
 * scheme. Readable URIs are converted into resource URIs as part of the
 * [Compiler.readScript] method. In the standard implementation the package URIs
 * are converted to file URIs using the package root URI provided on the
 * command line as base. If the package root URI is
 * 'file:///current/working/dir/' then the package URI 'package:foo/bar.dart'
 * will be resolved to the resource URI
 * 'file:///current/working/dir/foo/bar.dart'.
 *
 * The distinction between readable URI and resource URI is necessary to ensure
 * that these imports
 *
 *     import 'package:foo.dart' as a;
 *     import 'packages/foo.dart' as b;
 *
 * do _not_ resolve to the same library when the package root URI happens to
 * point to the 'packages' folder.
 *
 */
abstract class LibraryLoaderTask implements CompilerTask {
  factory LibraryLoaderTask(
      Compiler compiler,
      ResolvedUriTranslator uriTranslator,
      ScriptLoader scriptLoader,
      ElementScanner scriptScanner,
      LibraryDeserializer deserializer,
      LibraryLoaderListener listener,
      Environment environment) = _LibraryLoaderTask;

  /// Returns all libraries that have been loaded.
  Iterable<LibraryElement> get libraries;

  /// Looks up the library with the [canonicalUri].
  LibraryElement lookupLibrary(Uri canonicalUri);

  /// Loads the library specified by the [resolvedUri] and returns its
  /// [LibraryElement].
  ///
  /// If the library is not already loaded, the method creates the
  /// [LibraryElement] for the library and computes the import/export scope,
  /// loading and computing the import/export scopes of all required libraries
  /// in the process. The method handles cyclic dependency between libraries.
  ///
  /// If [skipFileWithPartOfTag] is `true`, `null` is returned if the
  /// compilation unit for [resolvedUri] contains a `part of` tag. This is only
  /// used for analysis through [Compiler.analyzeUri].
  Future<LibraryElement> loadLibrary(Uri resolvedUri,
      {bool skipFileWithPartOfTag: false});

  /// Reset the library loader task to prepare for compilation. If provided,
  /// libraries matching [reuseLibrary] are reused.
  ///
  /// This method is used for incremental compilation.
  void reset({bool reuseLibrary(LibraryElement library)});

  /// Asynchronous version of [reset].
  Future resetAsync(Future<bool> reuseLibrary(LibraryElement library));
}

/// Handle for creating synthesized/patch libraries during library loading.
abstract class LibraryLoader {
  /// This method must be called when a new synthesized/patch library has been
  /// created to ensure that [library] will part of library dependency graph
  /// used for computing import/export scopes.
  void registerNewLibrary(LibraryElement library);

  /// This method must be called when a new synthesized/patch library has been
  /// scanned in order to process the library tags in [library] and thus handle
  /// imports/exports/parts in the synthesized/patch library.
  Future processLibraryTags(LibraryElement library);
}

/**
 * [CombinatorFilter] is a succinct representation of a list of combinators from
 * a library dependency tag.
 */
class CombinatorFilter {
  const CombinatorFilter();

  /**
   * Returns [:true:] if [element] is excluded by this filter.
   */
  bool exclude(Element element) => false;

  /**
   * Creates a filter based on the combinators of [tag].
   */
  factory CombinatorFilter.fromTag(LibraryDependency tag) {
    if (tag == null || tag.combinators == null) {
      return const CombinatorFilter();
    }

    // If the list of combinators contain at least one [:show:] we can create
    // a positive list of elements to include, otherwise we create a negative
    // list of elements to exclude.
    bool show = false;
    Set<String> nameSet;
    for (Combinator combinator in tag.combinators) {
      if (combinator.isShow) {
        show = true;
        var set = new Set<String>();
        for (Identifier identifier in combinator.identifiers) {
          set.add(identifier.source);
        }
        if (nameSet == null) {
          nameSet = set;
        } else {
          nameSet = nameSet.intersection(set);
        }
      }
    }
    if (nameSet == null) {
      nameSet = new Set<String>();
    }
    for (Combinator combinator in tag.combinators) {
      if (combinator.isHide) {
        for (Identifier identifier in combinator.identifiers) {
          if (show) {
            // We have a positive list => Remove hidden elements.
            nameSet.remove(identifier.source);
          } else {
            // We have no positive list => Accumulate hidden elements.
            nameSet.add(identifier.source);
          }
        }
      }
    }
    return show ? new ShowFilter(nameSet) : new HideFilter(nameSet);
  }
}

/**
 * A list of combinators represented as a list of element names to include.
 */
class ShowFilter extends CombinatorFilter {
  final Set<String> includedNames;

  ShowFilter(this.includedNames);

  bool exclude(Element element) => !includedNames.contains(element.name);
}

/**
 * A list of combinators represented as a list of element names to exclude.
 */
class HideFilter extends CombinatorFilter {
  final Set<String> excludedNames;

  HideFilter(this.excludedNames);

  bool exclude(Element element) => excludedNames.contains(element.name);
}

/// Implementation class for [LibraryLoaderTask]. The distinction between
/// [LibraryLoaderTask] and [_LibraryLoaderTask] is made to hide internal
/// members from the [LibraryLoaderTask] interface.
class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
  /// Translates internal uris (like dart:core) to a disk location.
  final ResolvedUriTranslator uriTranslator;

  /// Loads the contents of a script file (a .dart file). Used when loading
  /// libraries from source.
  final ScriptLoader scriptLoader;

  /// Provides a diet element model from a script file containing information
  /// about imports and exports. Used when loading libraries from source.
  final ElementScanner scanner;

  /// Provides a diet element model for a library. Used when loading libraries
  /// from a serialized form.
  final LibraryDeserializer deserializer;

  /// Hooks to inform others about progress done by this loader.
  // TODO(sigmund): move away from this.
  final LibraryLoaderListener listener;

  /// Definitions provided via the `-D` command line flags. Used to resolve
  /// conditional imports.
  final Environment environment;

  _LibraryLoaderTask(Compiler compiler, this.uriTranslator, this.scriptLoader,
      this.scanner, this.deserializer, this.listener, this.environment)
      // TODO(sigmund): make measurements separate from compiler
      : super(compiler);

  String get name => 'LibraryLoader';

  final Map<Uri, LibraryElement> libraryCanonicalUriMap =
      new Map<Uri, LibraryElement>();
  final Map<Uri, LibraryElement> libraryResourceUriMap =
      new Map<Uri, LibraryElement>();
  final Map<String, LibraryElement> libraryNames =
      new Map<String, LibraryElement>();

  LibraryDependencyHandler currentHandler;

  Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values;

  LibraryElement lookupLibrary(Uri canonicalUri) {
    return libraryCanonicalUriMap[canonicalUri];
  }

  void reset({bool reuseLibrary(LibraryElement library)}) {
    measure(() {
      assert(currentHandler == null);

      Iterable<LibraryElement> reusedLibraries = null;
      if (reuseLibrary != null) {
        // TODO(sigmund): make measurements separate from compiler
        reusedLibraries = compiler.reuseLibraryTask.measure(() {
          // Call [toList] to force eager calls to [reuseLibrary].
          return libraryCanonicalUriMap.values.where(reuseLibrary).toList();
        });
      }

      resetImplementation(reusedLibraries);
    });
  }

  void resetImplementation(Iterable<LibraryElement> reusedLibraries) {
    measure(() {
      libraryCanonicalUriMap.clear();
      libraryResourceUriMap.clear();
      libraryNames.clear();

      if (reusedLibraries != null) {
        reusedLibraries.forEach(mapLibrary);
      }
    });
  }

  Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) {
    return measure(() {
      assert(currentHandler == null);

      wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null);
      List<Future<LibraryElement>> reusedLibrariesFuture =
          // TODO(sigmund): make measurements separate from compiler
          compiler.reuseLibraryTask.measure(
              () => libraryCanonicalUriMap.values.map(wrapper).toList());

      return Future
          .wait(reusedLibrariesFuture)
          .then((List<LibraryElement> reusedLibraries) {
        resetImplementation(reusedLibraries.where((e) => e != null));
      });
    });
  }

  /// Insert [library] in the internal maps. Used for compiler reuse.
  void mapLibrary(LibraryElement library) {
    libraryCanonicalUriMap[library.canonicalUri] = library;

    Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
    libraryResourceUriMap[resourceUri] = library;

    if (library.hasLibraryName) {
      String name = library.libraryName;
      libraryNames[name] = library;
    }
  }

  Future<LibraryElement> loadLibrary(Uri resolvedUri,
      {bool skipFileWithPartOfTag: false}) {
    return measure(() {
      assert(currentHandler == null);
      // TODO(johnniwinther): Ensure that currentHandler correctly encloses the
      // loading of a library cluster.
      currentHandler = new LibraryDependencyHandler(this);
      return createLibrary(currentHandler, null, resolvedUri,
              skipFileWithPartOfTag: skipFileWithPartOfTag)
          .then((LibraryElement library) {
        if (library == null) {
          currentHandler = null;
          return null;
        }
        return reporter.withCurrentElement(library, () {
          return measure(() {
            currentHandler.computeExports();
            LoadedLibraries loadedLibraries = new _LoadedLibraries(library,
                currentHandler.newLibraries, currentHandler.nodeMap, this);
            currentHandler = null;
            return listener
                .onLibrariesLoaded(loadedLibraries)
                .then((_) => library);
          });
        });
      });
    });
  }

  /**
   * Processes the library tags in [library].
   *
   * The imported/exported libraries are loaded and processed recursively but
   * the import/export scopes are not set up.
   */
  Future processLibraryTags(
      LibraryDependencyHandler handler, LibraryElementX library) {
    TagState tagState = new TagState();

    bool importsDartCore = false;
    LinkBuilder<LibraryDependencyElementX> libraryDependencies =
        new LinkBuilder<LibraryDependencyElementX>();
    Uri base = library.entryCompilationUnit.script.readableUri;

    return Future.forEach(library.tags, (LibraryTag tag) {
      return reporter.withCurrentElement(library, () {
        Uri computeUri(LibraryDependency node) {
          StringNode uriNode = node.uri;
          if (node.conditionalUris != null) {
            for (ConditionalUri conditionalUri in node.conditionalUris) {
              String key = conditionalUri.key.slowNameString;
              String value = conditionalUri.value == null
                  ? "true"
                  : conditionalUri.value.dartString.slowToString();
              String actual = environment.valueOf(key);
              if (value == actual) {
                uriNode = conditionalUri.uri;
                break;
              }
            }
          }
          String tagUriString = uriNode.dartString.slowToString();
          try {
            return Uri.parse(tagUriString);
          } on FormatException {
            reporter.reportErrorMessage(
                node.uri, MessageKind.INVALID_URI, {'uri': tagUriString});
            return null;
          }
        }

        if (tag.isImport) {
          Uri uri = computeUri(tag);
          if (uri == null) {
            // Skip this erroneous import.
            return new Future.value();
          }
          // TODO(johnniwinther): Create imports during parsing.
          ImportElementX import =
              new ImportElementX(library.entryCompilationUnit, tag, uri);
          tagState.checkTag(TagState.IMPORT_OR_EXPORT, import.node, reporter);
          if (import.uri == Uris.dart_core) {
            importsDartCore = true;
          }
          library.addImportDeclaration(import);
          libraryDependencies.addLast(import);
        } else if (tag.isExport) {
          Uri uri = computeUri(tag);
          if (uri == null) {
            // Skip this erroneous export.
            return new Future.value();
          }
          // TODO(johnniwinther): Create exports during parsing.
          ExportElementX export =
              new ExportElementX(library.entryCompilationUnit, tag, uri);
          tagState.checkTag(TagState.IMPORT_OR_EXPORT, export.node, reporter);
          library.addExportDeclaration(export);
          libraryDependencies.addLast(export);
        } else if (tag.isLibraryName) {
          tagState.checkTag(TagState.LIBRARY, tag, reporter);
          if (library.libraryTag == null) {
            // Use the first if there are multiple (which is reported as an
            // error in [TagState.checkTag]).
            library.libraryTag = tag;
          }
        } else if (tag.isPart) {
          Part part = tag;
          StringNode uri = part.uri;
          Uri resolvedUri = base.resolve(uri.dartString.slowToString());
          tagState.checkTag(TagState.PART, part, reporter);
          return scanPart(part, resolvedUri, library);
        } else {
          reporter.internalError(tag, "Unhandled library tag.");
        }
      });
    }).then((_) {
      return listener.onLibraryScanned(library, handler);
    }).then((_) {
      return reporter.withCurrentElement(library, () {
        checkDuplicatedLibraryName(library);

        // Import dart:core if not already imported.
        if (!importsDartCore && library.canonicalUri != Uris.dart_core) {
          return createLibrary(handler, null, Uris.dart_core)
              .then((LibraryElement coreLibrary) {
            handler.registerDependency(
                library,
                new SyntheticImportElement(
                    library.entryCompilationUnit, Uris.dart_core),
                coreLibrary);
          });
        }
      });
    }).then((_) {
      return Future.forEach(libraryDependencies.toList(),
          (LibraryDependencyElementX libraryDependency) {
        return reporter.withCurrentElement(library, () {
          return registerLibraryFromImportExport(
              handler, library, libraryDependency);
        });
      });
    });
  }

  void checkDuplicatedLibraryName(LibraryElement library) {
    if (library.isInternalLibrary) return;
    Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
    LibraryElement existing =
        libraryResourceUriMap.putIfAbsent(resourceUri, () => library);
    if (!identical(existing, library)) {
      if (library.hasLibraryName) {
        reporter.withCurrentElement(library, () {
          reporter.reportWarningMessage(
              library, MessageKind.DUPLICATED_LIBRARY_RESOURCE, {
            'libraryName': library.libraryName,
            'resourceUri': resourceUri,
            'canonicalUri1': library.canonicalUri,
            'canonicalUri2': existing.canonicalUri
          });
        });
      } else {
        reporter.reportHintMessage(library, MessageKind.DUPLICATED_RESOURCE, {
          'resourceUri': resourceUri,
          'canonicalUri1': library.canonicalUri,
          'canonicalUri2': existing.canonicalUri
        });
      }
    } else if (library.hasLibraryName) {
      String name = library.libraryName;
      existing = libraryNames.putIfAbsent(name, () => library);
      if (!identical(existing, library)) {
        reporter.withCurrentElement(library, () {
          reporter.reportWarningMessage(library,
              MessageKind.DUPLICATED_LIBRARY_NAME, {'libraryName': name});
        });
        reporter.withCurrentElement(existing, () {
          reporter.reportWarningMessage(existing,
              MessageKind.DUPLICATED_LIBRARY_NAME, {'libraryName': name});
        });
      }
    }
  }

  /**
   * Handle a part tag in the scope of [library]. The [resolvedUri] given is
   * used as is, any URI resolution should be done beforehand.
   */
  Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
    if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
    Uri readableUri = uriTranslator.translate(library, resolvedUri, part);
    if (readableUri == null) return new Future.value();
    return reporter.withCurrentElement(library, () {
      return scriptLoader.readScript(readableUri, part).then((Script script) {
        if (script == null) return;
        createUnitSync(script, library);
      });
    });
  }

  /**
   * Handle an import/export tag by loading the referenced library and
   * registering its dependency in [handler] for the computation of the import/
   * export scope. If the tag does not contain a valid URI, then its dependency
   * is not registered in [handler].
   */
  Future<Null> registerLibraryFromImportExport(LibraryDependencyHandler handler,
      LibraryElement library, LibraryDependencyElementX libraryDependency) {
    Uri base = library.canonicalUri;
    Uri resolvedUri = base.resolveUri(libraryDependency.uri);
    return createLibrary(handler, library, resolvedUri, node: libraryDependency)
        .then((LibraryElement loadedLibrary) {
      if (loadedLibrary == null) return;
      reporter.withCurrentElement(library, () {
        libraryDependency.libraryDependency = loadedLibrary;
        handler.registerDependency(library, libraryDependency, loadedLibrary);
      });
    });
  }

  /// Loads the deserialized [library] with the [handler].
  ///
  /// All libraries imported or exported transitively from [library] will be
  /// loaded as well.
  Future<LibraryElement> loadDeserializedLibrary(
      LibraryDependencyHandler handler, LibraryElement library) {
    libraryCanonicalUriMap[library.canonicalUri] = library;
    handler.registerNewLibrary(library);
    return listener.onLibraryScanned(library, handler).then((_) {
      return Future.forEach(library.imports, (ImportElement import) {
        return createLibrary(handler, library, import.uri);
      }).then((_) {
        return Future.forEach(library.exports, (ExportElement export) {
          return createLibrary(handler, library, export.uri);
        }).then((_) => library);
      });
    });
  }

  Future<Script> _readScript(
      Spannable spannable, Uri readableUri, Uri resolvedUri) {
    if (readableUri == null) {
      return new Future.value(new Script.synthetic(resolvedUri));
    } else {
      return scriptLoader.readScript(readableUri, spannable);
    }
  }

  /**
   * Create (or reuse) a library element for the library specified by the
   * [resolvedUri].
   *
   * If a new library is created, the [handler] is notified.
   */
  Future<LibraryElement> createLibrary(LibraryDependencyHandler handler,
      LibraryElement importingLibrary, Uri resolvedUri,
      {Spannable node, bool skipFileWithPartOfTag: false}) {
    Uri readableUri =
        uriTranslator.translate(importingLibrary, resolvedUri, node);
    LibraryElement library = libraryCanonicalUriMap[resolvedUri];
    if (library != null) {
      return new Future.value(library);
    }
    return deserializer.readLibrary(resolvedUri).then((LibraryElement library) {
      if (library != null) {
        return loadDeserializedLibrary(handler, library);
      }
      return reporter.withCurrentElement(importingLibrary, () {
        return _readScript(node, readableUri, resolvedUri)
            .then((Script script) {
          if (script == null) return null;
          LibraryElement element =
              createLibrarySync(handler, script, resolvedUri);
          CompilationUnitElementX compilationUnit =
              element.entryCompilationUnit;
          if (compilationUnit.partTag != null) {
            if (skipFileWithPartOfTag) {
              // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated]
              // for this library.
              libraryCanonicalUriMap.remove(resolvedUri);
              return null;
            }
            if (importingLibrary == null) {
              DiagnosticMessage error = reporter.withCurrentElement(
                  compilationUnit,
                  () => reporter.createMessage(
                      compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
              reporter.reportError(error);
            } else {
              DiagnosticMessage error = reporter.withCurrentElement(
                  compilationUnit,
                  () => reporter.createMessage(
                      compilationUnit.partTag, MessageKind.IMPORT_PART_OF));
              DiagnosticMessage info = reporter.withCurrentElement(
                  importingLibrary,
                  () => reporter.createMessage(
                      node, MessageKind.IMPORT_PART_OF_HERE));
              reporter.reportError(error, [info]);
            }
          }
          return processLibraryTags(handler, element).then((_) {
            reporter.withCurrentElement(element, () {
              handler.registerLibraryExports(element);
            });
            return element;
          });
        });
      });
    });
  }

  LibraryElement createLibrarySync(
      LibraryDependencyHandler handler, Script script, Uri resolvedUri) {
    LibraryElement element = new LibraryElementX(script, resolvedUri);
    return reporter.withCurrentElement(element, () {
      if (handler != null) {
        handler.registerNewLibrary(element);
        libraryCanonicalUriMap[resolvedUri] = element;
      }
      scanner.scanLibrary(element);
      return element;
    });
  }

  CompilationUnitElement createUnitSync(Script script, LibraryElement library) {
    CompilationUnitElementX unit = new CompilationUnitElementX(script, library);
    reporter.withCurrentElement(unit, () {
      scanner.scanUnit(unit);
      if (unit.partTag == null && !script.isSynthesized) {
        reporter.reportErrorMessage(unit, MessageKind.MISSING_PART_OF_TAG);
      }
    });
    return unit;
  }
}

/// A state machine for checking script tags come in the correct order.
class TagState {
  /// Initial state.
  static const int NO_TAG_SEEN = 0;

  /// Passed to [checkTag] when a library declaration (the syntax "library
  /// name;") has been seen. Not an actual state.
  static const int LIBRARY = 1;

  /// The state after the first library declaration.
  static const int AFTER_LIBRARY_DECLARATION = 2;

  /// The state after a import or export declaration has been seen, but before
  /// a part tag has been seen.
  static const int IMPORT_OR_EXPORT = 3;

  /// The state after a part tag has been seen.
  static const int PART = 4;

  /// Encodes transition function for state machine.
  static const List<int> NEXT = const <int>[
    NO_TAG_SEEN,
    AFTER_LIBRARY_DECLARATION, // Only one library tag is allowed.
    IMPORT_OR_EXPORT,
    IMPORT_OR_EXPORT,
    PART,
  ];

  int tagState = TagState.NO_TAG_SEEN;

  bool hasLibraryDeclaration = false;

  /// If [value] is less than [tagState] complain. Regardless, update
  /// [tagState] using transition function for state machine.
  void checkTag(int value, LibraryTag tag, DiagnosticReporter reporter) {
    if (tagState > value) {
      MessageKind kind;
      switch (value) {
        case LIBRARY:
          if (hasLibraryDeclaration) {
            kind = MessageKind.ONLY_ONE_LIBRARY_TAG;
          } else {
            kind = MessageKind.LIBRARY_TAG_MUST_BE_FIRST;
          }
          break;

        case IMPORT_OR_EXPORT:
          if (tag.isImport) {
            kind = MessageKind.IMPORT_BEFORE_PARTS;
          } else if (tag.isExport) {
            kind = MessageKind.EXPORT_BEFORE_PARTS;
          } else {
            reporter.internalError(tag, "Expected import or export.");
          }
          break;

        default:
          reporter.internalError(tag, "Unexpected order of library tags.");
      }
      reporter.reportErrorMessage(tag, kind);
    }
    tagState = NEXT[value];
    if (value == LIBRARY) {
      hasLibraryDeclaration = true;
    }
  }
}

/**
 * An [import] tag and the [importedLibrary] imported through [import].
 */
class ImportLink {
  final ImportElementX import;
  final LibraryElement importedLibrary;

  ImportLink(this.import, this.importedLibrary);

  /**
   * Imports the library into the [importingLibrary].
   */
  void importLibrary(
      DiagnosticReporter reporter, LibraryElementX importingLibrary) {
    assert(invariant(importingLibrary, importedLibrary.exportsHandled,
        message: 'Exports not handled on $importedLibrary'));
    Import tag = import.node;
    CombinatorFilter combinatorFilter = new CombinatorFilter.fromTag(tag);
    if (tag != null && tag.prefix != null) {
      String prefix = tag.prefix.source;
      Element existingElement = importingLibrary.find(prefix);
      PrefixElementX prefixElement;
      if (existingElement == null || !existingElement.isPrefix) {
        prefixElement = new PrefixElementX(
            prefix,
            importingLibrary.entryCompilationUnit,
            tag.getBeginToken(),
            tag.isDeferred ? import : null);
      } else {
        prefixElement = existingElement;
      }
      importingLibrary.addToScope(prefixElement, reporter);
      importedLibrary.forEachExport((Element element) {
        if (combinatorFilter.exclude(element)) return;
        prefixElement.addImport(element, import, reporter);
      });
      import.prefix = prefixElement;
      if (prefixElement.isDeferred) {
        prefixElement.addImport(
            new DeferredLoaderGetterElementX(prefixElement), import, reporter);
      }
    } else {
      importedLibrary.forEachExport((Element element) {
        reporter.withCurrentElement(importingLibrary, () {
          if (combinatorFilter.exclude(element)) return;
          importingLibrary.addImport(element, import, reporter);
        });
      });
    }
  }
}

/**
 * The combinator filter computed from an export tag and the library dependency
 * node for the library that declared the export tag. This represents an edge in
 * the library dependency graph.
 */
class ExportLink {
  final ExportElementX export;
  final CombinatorFilter combinatorFilter;
  final LibraryDependencyNode exportNode;

  ExportLink(ExportElementX export, LibraryDependencyNode this.exportNode)
      : this.export = export,
        this.combinatorFilter = new CombinatorFilter.fromTag(export.node);

  /**
   * Exports [element] to the dependent library unless [element] is filtered by
   * the export combinators. Returns [:true:] if the set pending exports of the
   * dependent library was modified.
   */
  bool exportElement(Element element) {
    if (combinatorFilter.exclude(element)) return false;
    return exportNode.addElementToPendingExports(element, export);
  }
}

/**
 * A node in the library dependency graph.
 *
 * This class is used to collect the library dependencies expressed through
 * import and export tags, and as the work-list entry in computations of library
 * exports performed in [LibraryDependencyHandler.computeExports].
 */
class LibraryDependencyNode {
  final LibraryElementX library;

  // TODO(ahe): Remove [hashCodeCounter] and [hashCode] when
  // VM implementation of Object.hashCode is not slow.
  final int hashCode = ++hashCodeCounter;
  static int hashCodeCounter = 0;

  /**
   * A linked list of the import tags that import [library] mapped to the
   * corresponding libraries. This is used to propagate exports into imports
   * after the export scopes have been computed.
   */
  Link<ImportLink> imports = const Link<ImportLink>();

  /// A linked list of all libraries directly exported by [library].
  Link<LibraryElement> exports = const Link<LibraryElement>();

  /**
   * A linked list of the export tags the dependent upon this node library.
   * This is used to propagate exports during the computation of export scopes.
   */
  Link<ExportLink> dependencies = const Link<ExportLink>();

  /**
   * The export scope for [library] which is gradually computed by the work-list
   * computation in [LibraryDependencyHandler.computeExports].
   */
  Map<String, Element> exportScope = <String, Element>{};

  /// Map from exported elements to the export directives that exported them.
  Map<Element, Link<ExportElement>> exporters =
      <Element, Link<ExportElement>>{};

  /**
   * The set of exported elements that need to be propageted to dependent
   * libraries as part of the work-list computation performed in
   * [LibraryDependencyHandler.computeExports]. Each export element is mapped
   * to a list of exports directives that export it.
   */
  Map<Element, Link<ExportElement>> pendingExportMap =
      <Element, Link<ExportElement>>{};

  LibraryDependencyNode(this.library);

  /**
   * Registers that the library of this node imports [importLibrary] through the
   * [import] tag.
   */
  void registerImportDependency(
      ImportElementX import, LibraryElement importedLibrary) {
    imports = imports.prepend(new ImportLink(import, importedLibrary));
  }

  /**
   * Registers that the library of this node is exported by
   * [exportingLibraryNode] through the [export] tag.
   */
  void registerExportDependency(
      ExportElementX export, LibraryDependencyNode exportingLibraryNode) {
    // Register the exported library in the exporting library node.
    exportingLibraryNode.exports =
        exportingLibraryNode.exports.prepend(library);
    // Register the export in the exported library node.
    dependencies =
        dependencies.prepend(new ExportLink(export, exportingLibraryNode));
  }

  /**
   * Registers all non-private locally declared members of the library of this
   * node to be exported. This forms the basis for the work-list computation of
   * the export scopes performed in [LibraryDependencyHandler.computeExports].
   */
  void registerInitialExports() {
    for (Element element in library.getNonPrivateElementsInScope()) {
      pendingExportMap[element] = const Link<ExportElement>();
    }
  }

  /// Register the already computed export scope of [exportedLibraryElement] to
  /// export from the library of this node through the [export]  declaration
  /// with the given combination [filter].
  ///
  /// Additionally, check that all names in the show/hide combinators are in the
  /// export scope of [exportedLibraryElement].
  void registerHandledExports(
      DiagnosticReporter reporter,
      LibraryElement exportedLibraryElement,
      ExportElementX export,
      CombinatorFilter filter) {
    assert(invariant(library, exportedLibraryElement.exportsHandled));
    exportedLibraryElement.forEachExport((Element exportedElement) {
      if (!filter.exclude(exportedElement)) {
        Link<ExportElement> exports = pendingExportMap.putIfAbsent(
            exportedElement, () => const Link<ExportElement>());
        pendingExportMap[exportedElement] = exports.prepend(export);
      }
    });
    if (!reporter.options.suppressHints) {
      reporter.withCurrentElement(library, () {
        checkLibraryDependency(reporter, export.node, exportedLibraryElement);
      });
    }
  }

  /**
   * Registers the compute export scope with the node library.
   */
  void registerExports() {
    library.setExports(exportScope.values.toList());
  }

  /**
   * Registers the imports of the node library.
   */
  void registerImports(DiagnosticReporter reporter) {
    for (ImportLink link in imports) {
      link.importLibrary(reporter, library);
    }
  }

  /**
   * Copies and clears pending export set for this node.
   */
  Map<Element, Link<ExportElement>> pullPendingExports() {
    Map<Element, Link<ExportElement>> pendingExports =
        new Map<Element, Link<ExportElement>>.from(pendingExportMap);
    pendingExportMap.clear();
    return pendingExports;
  }

  /**
   * Adds [element] to the export scope for this node. If the [element] name
   * is a duplicate, an error element is inserted into the export scope.
   */
  Element addElementToExportScope(DiagnosticReporter reporter, Element element,
      Link<ExportElement> exports) {
    String name = element.name;
    DiagnosticMessage error;
    List<DiagnosticMessage> infos = <DiagnosticMessage>[];

    void createDuplicateExportMessage(
        Element duplicate, Link<ExportElement> duplicateExports) {
      assert(invariant(library, !duplicateExports.isEmpty,
          message: "No export for $duplicate from ${duplicate.library} "
              "in $library."));
      reporter.withCurrentElement(library, () {
        for (ExportElement export in duplicateExports) {
          if (error == null) {
            error = reporter.createMessage(
                export, MessageKind.DUPLICATE_EXPORT, {'name': name});
          } else {
            infos.add(reporter.createMessage(
                export, MessageKind.DUPLICATE_EXPORT_CONT, {'name': name}));
          }
        }
      });
    }

    void createDuplicateExportDeclMessage(
        Element duplicate, Link<ExportElement> duplicateExports) {
      assert(invariant(library, !duplicateExports.isEmpty,
          message: "No export for $duplicate from ${duplicate.library} "
              "in $library."));
      infos.add(reporter.createMessage(
          duplicate,
          MessageKind.DUPLICATE_EXPORT_DECL,
          {'name': name, 'uriString': duplicateExports.head.uri}));
    }

    Element existingElement = exportScope[name];
    if (existingElement != null && existingElement != element) {
      if (existingElement.isMalformed) {
        createDuplicateExportMessage(element, exports);
        createDuplicateExportDeclMessage(element, exports);
        element = existingElement;
      } else if (existingElement.library == library) {
        // Do nothing. [existingElement] hides [element].
      } else if (element.library == library) {
        // [element] hides [existingElement].
        exportScope[name] = element;
        exporters[element] = exports;
      } else {
        // Declared elements hide exported elements.
        Link<ExportElement> existingExports = exporters[existingElement];
        createDuplicateExportMessage(existingElement, existingExports);
        createDuplicateExportMessage(element, exports);
        createDuplicateExportDeclMessage(existingElement, existingExports);
        createDuplicateExportDeclMessage(element, exports);
        element = exportScope[name] = new ErroneousElementX(
            MessageKind.DUPLICATE_EXPORT, {'name': name}, name, library);
      }
    } else {
      exportScope[name] = element;
      exporters[element] = exports;
    }
    if (error != null) {
      reporter.reportError(error, infos);
    }
    return element;
  }

  /**
   * Propagates the exported [element] to all library nodes that depend upon
   * this node. If the propagation updated any pending exports, [:true:] is
   * returned.
   */
  bool propagateElement(Element element) {
    bool change = false;
    for (ExportLink link in dependencies) {
      if (link.exportElement(element)) {
        change = true;
      }
    }
    return change;
  }

  /**
   * Adds [element] to the pending exports of this node and returns [:true:] if
   * the pending export set was modified. The combinators of [export] are used
   * to filter the element.
   */
  bool addElementToPendingExports(Element element, ExportElement export) {
    bool changed = false;
    if (!identical(exportScope[element.name], element)) {
      Link<ExportElement> exports = pendingExportMap.putIfAbsent(element, () {
        changed = true;
        return const Link<ExportElement>();
      });
      pendingExportMap[element] = exports.prepend(export);
    }
    return changed;
  }

  /// Check that all names in the show/hide combinators of imports and exports
  /// are in the export scope of the imported/exported libraries.
  void checkCombinators(DiagnosticReporter reporter) {
    reporter.withCurrentElement(library, () {
      for (ImportLink importLink in imports) {
        checkLibraryDependency(
            reporter, importLink.import.node, importLink.importedLibrary);
      }
    });
    for (ExportLink exportLink in dependencies) {
      reporter.withCurrentElement(exportLink.exportNode.library, () {
        checkLibraryDependency(reporter, exportLink.export.node, library);
      });
    }
  }

  /// Check that all names in the show/hide combinators of [tag] are in the
  /// export scope of [library].
  void checkLibraryDependency(DiagnosticReporter reporter,
      LibraryDependency tag, LibraryElement library) {
    if (tag == null || tag.combinators == null) return;
    for (Combinator combinator in tag.combinators) {
      for (Identifier identifier in combinator.identifiers) {
        String name = identifier.source;
        Element element = library.findExported(name);
        if (element == null) {
          if (combinator.isHide) {
            if (library.isPackageLibrary &&
                reporter.options.hidePackageWarnings) {
              // Only report hide hint on packages if we show warnings on these:
              // The hide may be non-empty in some versions of the package, in
              // which case you shouldn't remove the combinator.
              continue;
            }
            reporter.reportHintMessage(identifier, MessageKind.EMPTY_HIDE,
                {'uri': library.canonicalUri, 'name': name});
          } else {
            reporter.reportHintMessage(identifier, MessageKind.EMPTY_SHOW,
                {'uri': library.canonicalUri, 'name': name});
          }
        }
      }
    }
  }
}

/**
 * Helper class used for computing the possibly cyclic import/export scopes of
 * a set of libraries.
 *
 * This class is used by [ScannerTask.scanLibrary] to collect all newly loaded
 * libraries and to compute their import/export scopes through a fixed-point
 * algorithm.
 */
class LibraryDependencyHandler implements LibraryLoader {
  final _LibraryLoaderTask task;
  final List<LibraryElement> _newLibraries = <LibraryElement>[];

  /**
   * Newly loaded libraries and their corresponding node in the library
   * dependency graph. Libraries that have already been fully loaded are not
   * part of the dependency graph of this handler since their export scopes have
   * already been computed.
   */
  Map<LibraryElement, LibraryDependencyNode> nodeMap =
      new Map<LibraryElement, LibraryDependencyNode>();

  LibraryDependencyHandler(this.task);

  DiagnosticReporter get reporter => task.reporter;

  /// The libraries created with this handler.
  Iterable<LibraryElement> get newLibraries => _newLibraries;

  /**
   * Performs a fixed-point computation on the export scopes of all registered
   * libraries and creates the import/export of the libraries based on the
   * fixed-point.
   */
  void computeExports() {
    bool changed = true;
    while (changed) {
      changed = false;
      Map<LibraryDependencyNode, Map<Element, Link<ExportElement>>> tasks =
          new Map<LibraryDependencyNode, Map<Element, Link<ExportElement>>>();

      // Locally defined elements take precedence over exported
      // elements.  So we must propagate local elements first.  We
      // ensure this by pulling the pending exports before
      // propagating.  This enforces that we handle exports
      // breadth-first, with locally defined elements being level 0.
      nodeMap.forEach((_, LibraryDependencyNode node) {
        Map<Element, Link<ExportElement>> pendingExports =
            node.pullPendingExports();
        tasks[node] = pendingExports;
      });
      tasks.forEach((LibraryDependencyNode node,
          Map<Element, Link<ExportElement>> pendingExports) {
        pendingExports.forEach((Element element, Link<ExportElement> exports) {
          element = node.addElementToExportScope(reporter, element, exports);
          if (node.propagateElement(element)) {
            changed = true;
          }
        });
      });
    }

    // Setup export scopes. These have to be set before computing the import
    // scopes to avoid accessing uncomputed export scopes during handling of
    // imports.
    nodeMap.forEach((LibraryElement library, LibraryDependencyNode node) {
      node.registerExports();
    });

    // Setup import scopes.
    nodeMap.forEach((LibraryElement library, LibraryDependencyNode node) {
      node.registerImports(reporter);
    });

    if (!reporter.options.suppressHints) {
      nodeMap.forEach((LibraryElement library, LibraryDependencyNode node) {
        node.checkCombinators(reporter);
      });
    }
  }

  /// Registers that [library] depends on [loadedLibrary] through
  /// [libraryDependency].
  void registerDependency(
      LibraryElementX library,
      LibraryDependencyElementX libraryDependency,
      LibraryElement loadedLibrary) {
    if (libraryDependency.isExport) {
      // [loadedLibrary] is exported by [library].
      LibraryDependencyNode exportingNode = nodeMap[library];
      if (loadedLibrary.exportsHandled) {
        // Export scope already computed on [loadedLibrary].
        CombinatorFilter combinatorFilter =
            new CombinatorFilter.fromTag(libraryDependency.node);
        exportingNode.registerHandledExports(
            reporter, loadedLibrary, libraryDependency, combinatorFilter);
        return;
      }
      LibraryDependencyNode exportedNode = nodeMap[loadedLibrary];
      assert(invariant(loadedLibrary, exportedNode != null,
          message: "$loadedLibrary has not been registered"));
      assert(invariant(library, exportingNode != null,
          message: "$library has not been registered"));
      exportedNode.registerExportDependency(libraryDependency, exportingNode);
    } else if (libraryDependency == null || libraryDependency.isImport) {
      // [loadedLibrary] is imported by [library].
      LibraryDependencyNode importingNode = nodeMap[library];
      assert(invariant(library, importingNode != null,
          message: "$library has not been registered"));
      importingNode.registerImportDependency(libraryDependency, loadedLibrary);
    }
  }

  /**
   * Registers [library] for the processing of its import/export scope.
   */
  void registerNewLibrary(LibraryElement library) {
    task.listener.onLibraryCreated(library);
    _newLibraries.add(library);
    if (!library.exportsHandled) {
      nodeMap[library] = new LibraryDependencyNode(library);
    }
  }

  /**
   * Registers all top-level entities of [library] as starting point for the
   * fixed-point computation of the import/export scopes.
   */
  void registerLibraryExports(LibraryElement library) {
    nodeMap[library].registerInitialExports();
  }

  Future processLibraryTags(LibraryElement library) {
    return task.processLibraryTags(this, library);
  }
}

/// Information on the bulk of newly loaded libraries through a call to
/// [LibraryLoader.loadLibrary].
abstract class LoadedLibraries {
  /// The uri passed to [LibraryLoader.loadLibrary].
  Uri get rootUri;

  /// Returns `true` if a library with canonical [uri] was loaded in this bulk.
  bool containsLibrary(Uri uri);

  /// Returns the library with canonical [uri] that was loaded in this bulk.
  LibraryElement getLibrary(Uri uri);

  /// Applies all libraries in this bulk to [f].
  void forEachLibrary(f(LibraryElement library));

  /// Applies all imports chains of [uri] in this bulk to [callback].
  ///
  /// The argument [importChainReversed] to [callback] contains the chain of
  /// imports uris that lead to importing [uri] starting in [uri] and ending in
  /// [rootUri].
  ///
  /// [callback] is called once for each chain of imports leading to [uri] until
  /// [callback] returns `false`.
  void forEachImportChain(Uri uri,
      {bool callback(Link<Uri> importChainReversed)});
}

class _LoadedLibraries implements LoadedLibraries {
  final _LibraryLoaderTask task;
  final LibraryElement rootLibrary;
  final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
  final Map<LibraryElement, LibraryDependencyNode> nodeMap;

  _LoadedLibraries(this.rootLibrary, Iterable<LibraryElement> libraries,
      this.nodeMap, this.task) {
    libraries.forEach((LibraryElement loadedLibrary) {
      loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
    });
  }

  Uri get rootUri => rootLibrary.canonicalUri;

  bool containsLibrary(Uri uri) => loadedLibraries.containsKey(uri);

  LibraryElement getLibrary(Uri uri) => loadedLibraries[uri];

  void forEachLibrary(f(LibraryElement library)) => nodeMap.keys.forEach(f);

  void forEachImportChain(Uri targetUri,
      {bool callback(Link<Uri> importChainReversed)}) {
    bool aborted = false;

    /// Map from libraries to the set of (unreversed) paths to [uri].
    Map<LibraryElement, Iterable<Link<Uri>>> suffixChainMap =
        <LibraryElement, Iterable<Link<Uri>>>{};

    /// Computes the set of (unreversed) paths to [targetUri].
    ///
    /// Finds all paths (suffixes) from the current library to [uri] and stores
    /// it in [suffixChainMap].
    ///
    /// For every found suffix it prepends the given [prefix] and the canonical
    /// uri of [library] and invokes the [callback] with the concatenated chain.
    void computeSuffixes(LibraryElement library, Link<Uri> prefix) {
      if (aborted) return;

      Uri canonicalUri = library.canonicalUri;
      prefix = prefix.prepend(canonicalUri);
      if (suffixChainMap.containsKey(library)) return;
      suffixChainMap[library] = const <Link<Uri>>[];
      List<Link<Uri>> suffixes = [];
      if (targetUri != canonicalUri) {
        LibraryDependencyNode node = nodeMap[library];

        /// Process the import (or export) of [importedLibrary].
        void processLibrary(LibraryElement importedLibrary) {
          bool suffixesArePrecomputed =
              suffixChainMap.containsKey(importedLibrary);

          if (!suffixesArePrecomputed) {
            computeSuffixes(importedLibrary, prefix);
            if (aborted) return;
          }

          for (Link<Uri> suffix in suffixChainMap[importedLibrary]) {
            suffixes.add(suffix.prepend(canonicalUri));

            if (suffixesArePrecomputed) {
              // Only report chains through [import] if the suffixes had already
              // been computed, otherwise [computeSuffixes] have reported the
              // paths through [prefix].
              Link<Uri> chain = prefix;
              while (!suffix.isEmpty) {
                chain = chain.prepend(suffix.head);
                suffix = suffix.tail;
              }
              if (!callback(chain)) {
                aborted = true;
                return;
              }
            }
          }
        }

        for (ImportLink import in node.imports.reverse()) {
          processLibrary(import.importedLibrary);
          if (aborted) return;
        }
        for (LibraryElement exportedLibrary in node.exports.reverse()) {
          processLibrary(exportedLibrary);
          if (aborted) return;
        }
      } else {
        // Here `targetUri == canonicalUri`.
        if (!callback(prefix)) {
          aborted = true;
          return;
        }
        suffixes.add(const Link<Uri>().prepend(canonicalUri));
      }
      suffixChainMap[library] = suffixes;
      return;
    }

    computeSuffixes(rootLibrary, const Link<Uri>());
  }

  String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
}

/// API used by the library loader to translate internal SDK URIs into file
/// system readable URIs.
abstract class ResolvedUriTranslator {
  // TODO(sigmund): move here the comments from library loader.
  /// Translate the resolved [uri] in the context of [importingLibrary].
  ///
  /// Use [spannable] for error reporting.
  Uri translate(LibraryElement importingLibrary, Uri uri,
      [Spannable spannable]);
}

// TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
// rather low-level. It might be more practical to split the library-loading
// task itself.  The task would continue to do the work of recursively loading
// dependencies, but it can delegate to a set of subloaders how to do the actual
// loading. We would then have a list of subloaders that use different
// implementations: in-memory cache, deserialization, scanning from files.
//
// For example, the API might look like this:
//
// /// APIs to create [LibraryElement] and [CompilationUnitElements] given it's
// /// URI.
// abstract class SubLoader {
//   /// Return the library corresponding to the script at [uri].
//   ///
//   /// Use [spannable] for error reporting.
//   Future<LibraryElement> createLibrary(Uri uri, [Spannable spannable]);
//
//   /// Return the compilation unit at [uri] that is a part of [library].
//   Future<CompilationUnitElement> createUnit(Uri uri, LibraryElement library,
//       [Spannable spannable]);
// }
//
// /// A [SubLoader] that parses a serialized form of the element model to
// /// produce the results.
// class DeserializingUnitElementCreator implements SubLoader {
// ...
// }
//
// /// A [SubLoader] that finds the script sources and does a diet parse
// /// on them to produces the results.
// class ScanningUnitElementCreator implements SubLoader {
// ...
// }
//
// Each subloader would internally create what they need (a scanner, a
// deserializer), and we wouldn't need to create abstractions to pass in
// something that is only used by the loader.

/// API used by the library loader to request scripts from the compiler system.
abstract class ScriptLoader {
  /// Load script from a readable [uri], report any errors using the location of
  /// the given [spannable].
  Future<Script> readScript(Uri uri, [Spannable spannable]);
}

/// API used by the library loader to synchronously scan a library or
/// compilation unit and ensure that their library tags are computed.
abstract class ElementScanner {
  void scanLibrary(LibraryElement library);
  void scanUnit(CompilationUnitElement unit);
}

/// TODO(sigmund): remove this abstraction. Ideally the loader can produce the
/// LoadedLibraries results once, and the compiler and choose what to do with
/// it instead.
abstract class LibraryLoaderListener {
  /// Called after a request to load a library. The [results] will include all
  /// transitive libraries loaded as a result of the initial request.
  Future onLibrariesLoaded(LoadedLibraries results);

  /// Called whenever a library element is created.
  void onLibraryCreated(LibraryElement library);

  /// Called whenever a library is scanned from a script file.
  Future onLibraryScanned(LibraryElement library, LibraryLoader loader);
}
