// Copyright (c) 2016, 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 kernel.analyzer.loader;

import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:kernel/application_root.dart';
import 'package:package_config/discovery.dart';
import 'package:package_config/packages.dart';

import 'package:kernel/ast.dart' as ast;
import 'package:kernel/target/targets.dart' show Target;
import 'package:kernel/type_algebra.dart';
import 'package:analyzer/src/kernel/ast_from_analyzer.dart';

/// Options passed to the Dart frontend.
class DartOptions {
  /// True if user code should be loaded in strong mode.
  bool strongMode;

  /// True if the Dart SDK should be loaded in strong mode.
  bool strongModeSdk;

  /// Path to the sdk sources, ignored if sdkSummary is provided.
  String sdk;

  /// Path to a summary of the sdk sources.
  String sdkSummary;

  /// Path to the `.packages` file.
  String packagePath;

  /// Root used to relativize app file-urls, making them machine agnostic.
  ApplicationRoot applicationRoot;

  Map<Uri, Uri> customUriMappings;

  /// Environment definitions provided via `-Dkey=value`.
  Map<String, String> declaredVariables;

  DartOptions(
      {bool strongMode: false,
      bool strongModeSdk,
      this.sdk,
      this.sdkSummary,
      this.packagePath,
      ApplicationRoot applicationRoot,
      Map<Uri, Uri> customUriMappings,
      Map<String, String> declaredVariables})
      : this.customUriMappings = customUriMappings ?? <Uri, Uri>{},
        this.declaredVariables = declaredVariables ?? <String, String>{},
        this.strongMode = strongMode,
        this.strongModeSdk = strongModeSdk ?? strongMode,
        this.applicationRoot = applicationRoot ?? new ApplicationRoot.none();
}

abstract class ReferenceLevelLoader {
  ast.Library getLibraryReference(LibraryElement element);
  ast.Class getClassReference(ClassElement element);
  ast.Member getMemberReference(Element element);
  ast.Class getRootClassReference();
  ast.Constructor getRootClassConstructorReference();
  ast.Class getCoreClassReference(String className);
  ast.Constructor getCoreClassConstructorReference(String className,
      {String constructorName, String library});
  ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element);
  ast.Class getSharedMixinApplicationClass(
      ast.Library library, ast.Class supertype, ast.Class mixin);
  bool get strongMode;

  /// Whether or not to include redirecting factories in the output.
  bool get ignoreRedirectingFactories;
}

class DartLoader implements ReferenceLevelLoader {
  final ast.Component component;
  final ApplicationRoot applicationRoot;
  final Bimap<ClassElement, ast.Class> _classes =
      new Bimap<ClassElement, ast.Class>();
  final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>();
  final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters =
      <TypeParameterElement, ast.TypeParameter>{};
  final Map<ast.Library, Map<String, ast.Class>> _mixinApplications =
      <ast.Library, Map<String, ast.Class>>{};
  final Map<LibraryElement, ast.Library> _libraries =
      <LibraryElement, ast.Library>{};
  final AnalysisContext context;
  LibraryElement _dartCoreLibrary;
  final List errors = [];
  final List libraryElements = [];

  /// Classes that have been referenced, and must be promoted to type level
  /// so as not to expose partially initialized classes.
  final List<ast.Class> temporaryClassWorklist = [];

  final Map<LibraryElement, List<ClassElement>> mixinLibraryWorklist = {};

  final bool ignoreRedirectingFactories;

  LibraryElement _libraryBeingLoaded = null;
  ClassElement _classBeingPromotedToMixin = null;

  bool get strongMode => context.analysisOptions.strongMode;

  DartLoader(this.component, DartOptions options, Packages packages,
      {DartSdk dartSdk,
      AnalysisContext context,
      this.ignoreRedirectingFactories: true})
      : this.context =
            context ?? createContext(options, packages, dartSdk: dartSdk),
        this.applicationRoot = options.applicationRoot;

  String getLibraryName(LibraryElement element) {
    return element.name.isEmpty ? null : element.name;
  }

  LibraryElement getLibraryElementFromUri(Uri uri) {
    var source = context.sourceFactory.forUri2(uri);
    if (source == null) return null;
    return context.computeLibraryElement(source);
  }

  ast.Library getLibraryReference(LibraryElement element) {
    var uri = applicationRoot.relativeUri(element.source.uri);
    var library = _libraries[element];
    if (library == null) {
      library = new ast.Library(uri)
        ..isExternal = true
        ..name = getLibraryName(element)
        ..fileUri = element.source.uri;
      component.libraries.add(library..parent = component);
      _libraries[element] = library;
    }
    return library;
  }

  ast.Library getLibraryReferenceFromUri(Uri uri) {
    return getLibraryReference(getLibraryElementFromUri(uri));
  }

  void _buildTopLevelMember(
      ast.Member member, Element element, Declaration astNode) {
    assert(member.parent != null);
    new MemberBodyBuilder(this, member, element).build(astNode);
  }

  /// True if [element] is in the process of being loaded by
  /// [_buildLibraryBody].
  ///
  /// If this is the case, we should avoid adding new members to the classes
  /// in the library, since the AST builder will rebuild the member lists.
  bool isLibraryBeingLoaded(LibraryElement element) {
    return _libraryBeingLoaded == element;
  }

  bool isClassBeingPromotedToMixin(ClassElement element) {
    return _classBeingPromotedToMixin == element;
  }

  void _buildLibraryBody(LibraryElement element, ast.Library library,
      List<CompilationUnit> units) {
    assert(_libraryBeingLoaded == null);
    _libraryBeingLoaded = element;
    var classes = <ast.Class>[];
    var procedures = <ast.Procedure>[];
    var fields = <ast.Field>[];

    void loadClass(NamedCompilationUnitMember declaration) {
      // [declaration] can be a ClassDeclaration, EnumDeclaration, or a
      // ClassTypeAlias.
      ClassElement element = declaration.element;
      var node = getClassReference(element);
      promoteToBodyLevel(node, element, declaration);
      classes.add(node);
    }

    void loadProcedure(FunctionDeclaration declaration) {
      var element = declaration.element;
      var node = getMemberReference(element);
      _buildTopLevelMember(node, element, declaration);
      procedures.add(node);
    }

    void loadField(TopLevelVariableDeclaration declaration) {
      for (var field in declaration.variables.variables) {
        var element = field.element;
        // Ignore fields inserted through error recovery.
        if (element.name == '') continue;
        var node = getMemberReference(element);
        _buildTopLevelMember(node, element, field);
        fields.add(node);
      }
    }

    for (var unit in units) {
      for (CompilationUnitMember declaration in unit.declarations) {
        if (declaration is ClassDeclaration ||
            declaration is EnumDeclaration ||
            declaration is ClassTypeAlias) {
          loadClass(declaration);
        } else if (declaration is FunctionDeclaration) {
          loadProcedure(declaration);
        } else if (declaration is TopLevelVariableDeclaration) {
          loadField(declaration);
        } else if (declaration is FunctionTypeAlias) {
          // Nothing to do. Typedefs are handled lazily while constructing type
          // references.
        } else {
          throw "unexpected node: ${declaration.runtimeType} $declaration";
        }
      }
    }
    libraryElements.add(element);
    _iterateTemporaryClassWorklist();
    // Ensure everything is stored in the original declaration order.
    library.classes
      ..clear()
      ..addAll(classes)
      ..addAll(_mixinApplications[library]?.values ?? const []);
    library.fields
      ..clear()
      ..addAll(fields);
    library.procedures
      ..clear()
      ..addAll(procedures);
    _libraryBeingLoaded = null;
  }

  LibraryElement getDartCoreLibrary() {
    return _dartCoreLibrary ??= _findLibraryElement('dart:core');
  }

  LibraryElement _findLibraryElement(String uri) {
    var source = context.sourceFactory.forUri(uri);
    if (source == null) return null;
    return context.computeLibraryElement(source);
  }

  ast.Class getRootClassReference() {
    return getCoreClassReference('Object');
  }

  ast.Constructor getRootClassConstructorReference() {
    var element = getDartCoreLibrary().getType('Object').constructors[0];
    return getMemberReference(element);
  }

  ast.Class getCoreClassReference(String className) {
    return getClassReference(getDartCoreLibrary().getType(className));
  }

  ast.Constructor getCoreClassConstructorReference(String className,
      {String constructorName, String library}) {
    LibraryElement libraryElement =
        library != null ? _findLibraryElement(library) : getDartCoreLibrary();
    ClassElement element = libraryElement.getType(className);
    if (element == null) {
      throw 'Missing core class $className from ${libraryElement.name}';
    }
    var constructor = element.constructors.firstWhere((constructor) {
      return (constructorName == null)
          ? (constructor.nameLength == 0)
          : (constructor.name == constructorName);
    });
    return getMemberReference(constructor);
  }

  ClassElement getClassElement(ast.Class node) {
    return _classes.inverse[node];
  }

  void addMixinClassToLibrary(ast.Class class_, ast.Library library) {
    assert(class_.parent == null);
    library.addClass(class_);
    var map =
        _mixinApplications.putIfAbsent(library, () => <String, ast.Class>{});
    map[class_.name] = class_;
  }

  /// Returns the IR for a class, at a temporary loading level.
  ///
  /// The returned class has the correct name, flags, type parameter arity,
  /// and enclosing library.
  ast.Class getClassReference(ClassElement element) {
    var classNode = _classes[element];
    if (classNode != null) return classNode;
    _classes[element] = classNode = new ast.Class(
        name: element.name,
        isAbstract: element.isAbstract,
        fileUri: element.source.uri)
      ..fileOffset = element.nameOffset;
    classNode.level = ast.ClassLevel.Temporary;
    var library = getLibraryReference(element.library);
    library.addClass(classNode);
    // Initialize type parameter list without bounds.
    for (var parameter in element.typeParameters) {
      var parameterNode = new ast.TypeParameter(parameter.name);
      _classTypeParameters[parameter] = parameterNode;
      classNode.typeParameters.add(parameterNode);
      parameterNode.parent = classNode;
    }
    // Ensure the class is at least promoted to type level before exposing it
    // to kernel consumers.
    temporaryClassWorklist.add(classNode);
    return classNode;
  }

  /// Ensures the supertypes and type parameter bounds have been generated for
  /// the given class.
  void promoteToTypeLevel(ast.Class classNode) {
    if (classNode.level.index >= ast.ClassLevel.Type.index) return;
    classNode.level = ast.ClassLevel.Type;
    var element = getClassElement(classNode);
    assert(element != null);
    var library = getLibraryReference(element.library);
    var scope = new ClassScope(this, library);
    // Initialize bounds on type parameters.
    for (int i = 0; i < classNode.typeParameters.length; ++i) {
      var parameter = element.typeParameters[i];
      var parameterNode = classNode.typeParameters[i];
      parameterNode.bound = parameter.bound == null
          ? scope.defaultTypeParameterBound
          : scope.buildType(parameter.bound);
    }
    // Initialize supertypes.
    Iterable<InterfaceType> mixins = element.mixins;
    if (element.isMixinApplication && mixins.isNotEmpty) {
      classNode.mixedInType = scope.buildSupertype(mixins.last);
      mixins = mixins.take(mixins.length - 1);
    }
    if (element.supertype != null) {
      ast.Supertype supertype = scope.buildSupertype(element.supertype);
      bool useSharedMixin = true;
      for (var mixin in mixins) {
        var mixinType = scope.buildSupertype(mixin);
        if (useSharedMixin &&
            areDistinctUnboundTypeVariables(supertype, mixinType)) {
          // Use a shared mixin application class for this library.
          var mixinClass = getSharedMixinApplicationClass(
              scope.currentLibrary, supertype.classNode, mixinType.classNode);
          if (mixinClass.fileOffset < 0) {
            mixinClass.fileOffset = element.nameOffset;
          }
          supertype = new ast.Supertype(
              mixinClass,
              supertype.typeArguments.length > mixinType.typeArguments.length
                  ? supertype.typeArguments
                  : mixinType.typeArguments);
        } else {
          // Generate a new class specific for this mixin application.
          var freshParameters =
              getFreshTypeParameters(classNode.typeParameters);
          var mixinClass = new ast.Class(
              name: '${classNode.name}^${mixinType.classNode.name}',
              isAbstract: true,
              typeParameters: freshParameters.freshTypeParameters,
              supertype: freshParameters.substituteSuper(supertype),
              mixedInType: freshParameters.substituteSuper(mixinType),
              fileUri: classNode.fileUri)
            ..fileOffset = element.nameOffset;
          mixinClass.level = ast.ClassLevel.Type;
          addMixinClassToLibrary(mixinClass, classNode.enclosingLibrary);
          supertype = new ast.Supertype(mixinClass,
              classNode.typeParameters.map(makeTypeParameterType).toList());
          // This class cannot be used from anywhere else, so don't try to
          // generate shared mixin applications using it.
          useSharedMixin = false;
        }
      }
      classNode.supertype = supertype;
      for (var implementedType in element.interfaces) {
        classNode.implementedTypes.add(scope.buildSupertype(implementedType));
      }
    }
  }

  void promoteToHierarchyLevel(ast.Class classNode) {
    if (classNode.level.index >= ast.ClassLevel.Hierarchy.index) return;
    promoteToTypeLevel(classNode);
    classNode.level = ast.ClassLevel.Hierarchy;
    var element = getClassElement(classNode);
    if (element != null) {
      // Ensure all instance members are at present.
      for (var field in element.fields) {
        if (!field.isStatic && !field.isSynthetic) {
          getMemberReference(field);
        }
      }
      for (var accessor in element.accessors) {
        if (!accessor.isStatic && !accessor.isSynthetic) {
          getMemberReference(accessor);
        }
      }
      for (var method in element.methods) {
        if (!method.isStatic && !method.isSynthetic) {
          getMemberReference(method);
        }
      }
    }
    for (var supertype in classNode.supers) {
      promoteToHierarchyLevel(supertype.classNode);
    }
  }

  void promoteToMixinLevel(ast.Class classNode, ClassElement element,
      NamedCompilationUnitMember astNode) {
    if (classNode.level.index >= ast.ClassLevel.Mixin.index) return;
    _classBeingPromotedToMixin = element;
    promoteToHierarchyLevel(classNode);
    classNode.level = ast.ClassLevel.Mixin;
    // Clear out the member references that were put in the class.
    // The AST builder will load them all put back in the right order.
    classNode..fields.clear()..procedures.clear()..constructors.clear();
    new ClassBodyBuilder(this, classNode, element).build(astNode);
    _classBeingPromotedToMixin = null;

    // Ensure mixed-in classes are available.
    for (var mixin in element.mixins) {
      _ensureMixinBecomesLoaded(mixin.element);
    }
  }

  /// Ensures that [element] eventually becomes loaded at least at mixin level.
  void _ensureMixinBecomesLoaded(ClassElement element) {
    if (isClassBeingPromotedToMixin(element)) {
      return;
    }
    var class_ = getClassReference(element);
    if (class_.level.index >= ast.ClassLevel.Mixin.index) {
      return;
    }
    var list = mixinLibraryWorklist[element.library] ??= <ClassElement>[];
    list.add(element);
  }

  void promoteToBodyLevel(ast.Class classNode, ClassElement element,
      NamedCompilationUnitMember astNode) {
    if (classNode.level == ast.ClassLevel.Body) return;
    promoteToMixinLevel(classNode, element, astNode);
    classNode.level = ast.ClassLevel.Body;
    // This frontend delivers the same contents for classes at body and mixin
    // levels, even though as specified, the mixin level does not require all
    // the static members to be present.  So no additional work is needed.
  }

  ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) {
    return _classTypeParameters[element];
  }

  Element getMemberElement(ast.Member node) {
    return _members.inverse[node];
  }

  ast.Member getMemberReference(Element element) {
    assert(element != null);
    assert(element is! Member); // Use the "base element".
    return _members[element] ??= _buildMemberReference(element);
  }

  ast.Member _buildMemberReference(Element element) {
    assert(element != null);
    var member = _buildOrphanedMemberReference(element);
    // Set the parent pointer and store it in the enclosing class or library.
    // If the enclosing library is being built from the AST, do not add the
    // member, since the AST builder will put it in there.
    var parent = element.enclosingElement;
    if (parent is ClassElement) {
      var class_ = getClassReference(parent);
      member.parent = class_;
      if (!isLibraryBeingLoaded(element.library)) {
        class_.addMember(member);
      }
    } else {
      var library = getLibraryReference(element.library);
      member.parent = library;
      if (!isLibraryBeingLoaded(element.library)) {
        library.addMember(member);
      }
    }
    return member;
  }

  ast.Member _buildOrphanedMemberReference(Element element) {
    assert(element != null);
    ClassElement classElement = element.enclosingElement is ClassElement
        ? element.enclosingElement
        : null;
    TypeScope scope = classElement != null
        ? new ClassScope(this, getLibraryReference(element.library))
        : new TypeScope(this);
    if (classElement != null) {
      getClassReference(classElement);
    }
    switch (element.kind) {
      case ElementKind.CONSTRUCTOR:
        ConstructorElement constructor = element;
        if (constructor.isFactory) {
          return new ast.Procedure(
              _nameOfMember(constructor),
              ast.ProcedureKind.Factory,
              scope.buildFunctionInterface(constructor),
              isAbstract: false,
              isStatic: true,
              isExternal: constructor.isExternal,
              isConst: constructor.isConst,
              fileUri: element.source.uri)
            ..fileOffset = element.nameOffset;
        }
        return new ast.Constructor(scope.buildFunctionInterface(constructor),
            name: _nameOfMember(element),
            isConst: constructor.isConst,
            isExternal: constructor.isExternal,
            isSynthetic: constructor.isSynthetic)
          ..fileOffset = element.nameOffset;

      case ElementKind.FIELD:
      case ElementKind.TOP_LEVEL_VARIABLE:
        VariableElement variable = element;
        return new ast.Field(_nameOfMember(variable),
            isStatic: variable.isStatic,
            isFinal: variable.isFinal,
            isConst: variable.isConst,
            type: scope.buildType(variable.type),
            fileUri: element.source.uri)
          ..fileOffset = element.nameOffset;

      case ElementKind.METHOD:
      case ElementKind.GETTER:
      case ElementKind.SETTER:
      case ElementKind.FUNCTION:
        if (element is FunctionElement &&
            element.enclosingElement is! CompilationUnitElement) {
          throw 'Function $element is nested in ${element.enclosingElement} '
              'and hence is not a member';
        }
        ExecutableElement executable = element;
        return new ast.Procedure(
            _nameOfMember(element),
            _procedureKindOf(executable),
            scope.buildFunctionInterface(executable),
            isAbstract: executable.isAbstract,
            isStatic: executable.isStatic,
            isExternal: executable.isExternal,
            fileUri: element.source.uri)
          ..fileOffset = element.nameOffset;

      default:
        throw 'Unexpected member kind: $element';
    }
  }

  ast.ProcedureKind _procedureKindOf(ExecutableElement element) {
    if (element is PropertyAccessorElement) {
      return element.isGetter
          ? ast.ProcedureKind.Getter
          : ast.ProcedureKind.Setter;
    }
    if (element is MethodElement) {
      if (element.isOperator) return ast.ProcedureKind.Operator;
      return ast.ProcedureKind.Method;
    }
    if (element is FunctionElement) {
      return ast.ProcedureKind.Method;
    }
    if (element is ConstructorElement) {
      assert(element.isFactory);
      return ast.ProcedureKind.Factory;
    }
    throw 'Unexpected procedure: $element';
  }

  ast.Name _nameOfMember(Element element) {
    // Use 'displayName' to avoid a trailing '=' for setters and 'name' to
    // ensure unary minus is called 'unary-'.
    String name =
        element is PropertyAccessorElement ? element.displayName : element.name;
    return new ast.Name(name, getLibraryReference(element.library));
  }

  /// True if the two types have form `C<T1 ... Tm>` and `D<T1 ... Tn>`, and
  /// `T1 ... TN` are distinct type variables with no upper bound, where
  /// `N = max(m,n)`.
  bool areDistinctUnboundTypeVariables(
      ast.Supertype first, ast.Supertype second) {
    var seen = new Set<ast.TypeParameter>();
    if (first.typeArguments.length < second.typeArguments.length) {
      var tmp = first;
      first = second;
      second = tmp;
    }
    for (int i = 0; i < first.typeArguments.length; ++i) {
      var firstArg = first.typeArguments[i];
      if (!(firstArg is ast.TypeParameterType &&
          seen.add(firstArg.parameter) &&
          firstArg.parameter.bound is ast.DynamicType)) {
        return false;
      }
      if (i < second.typeArguments.length &&
          firstArg != second.typeArguments[i]) {
        return false;
      }
    }
    return true;
  }

  /// Returns the canonical mixin application of two classes, instantiated with
  /// the same list of unbound type variables.
  ///
  /// Given two classes:
  ///     class C<C1 ... Cm>
  ///     class D<D1 ... Dn>
  ///
  /// This creates or reuses a mixin application class in the library of form:
  ///
  ///     abstract class C&D<T1 ... TN> = C<T1 ... Tm> with D<T1 ... Tn>
  ///
  /// where `N = max(m,n)`.
  ///
  /// Such a class can in general contain type errors due to incompatible
  /// inheritance from `C` and `D`.  This method therefore should only be called
  /// if a mixin application `C<S1 ... Sm> with D<S1 ... Sn>` is seen, where
  /// `S1 ... SN` are distinct, unbound type variables.
  ast.Class getSharedMixinApplicationClass(
      ast.Library library, ast.Class superclass, ast.Class mixedInClass) {
    // TODO(asgerf): Avoid potential name clash due to associativity.
    // As it is, these mixins get the same name:
    //   (A with B) with C
    //   A with (B with C)
    String name = '${superclass.name}&${mixedInClass.name}';
    return _mixinApplications
        .putIfAbsent(library, () => <String, ast.Class>{})
        .putIfAbsent(name, () {
      var fresh =
          superclass.typeParameters.length >= mixedInClass.typeParameters.length
              ? getFreshTypeParameters(superclass.typeParameters)
              : getFreshTypeParameters(mixedInClass.typeParameters);
      var typeArguments =
          fresh.freshTypeParameters.map(makeTypeParameterType).toList();
      var superArgs = typeArguments.length != superclass.typeParameters.length
          ? typeArguments.sublist(0, superclass.typeParameters.length)
          : typeArguments;
      var mixinArgs = typeArguments.length != mixedInClass.typeParameters.length
          ? typeArguments.sublist(0, mixedInClass.typeParameters.length)
          : typeArguments;
      var result = new ast.Class(
          name: name,
          isAbstract: true,
          typeParameters: fresh.freshTypeParameters,
          supertype: new ast.Supertype(superclass, superArgs),
          mixedInType: new ast.Supertype(mixedInClass, mixinArgs),
          fileUri: library.fileUri);
      result.level = ast.ClassLevel.Type;
      library.addClass(result);
      return result;
    });
  }

  String formatErrorMessage(
      AnalysisError error, String filename, LineInfo lines) {
    var location = lines.getLocation(error.offset);
    return '[error] ${error.message} ($filename, '
        'line ${location.lineNumber}, '
        'col ${location.columnNumber})';
  }

  void ensureLibraryIsLoaded(ast.Library node) {
    _ensureLibraryIsLoaded(node);
    _iterateMixinLibraryWorklist();
  }

  void _ensureLibraryIsLoaded(ast.Library node) {
    if (!node.isExternal) return;
    node.isExternal = false;
    var source = context.sourceFactory
        .forUri2(applicationRoot.absoluteUri(node.importUri));
    assert(source != null);
    var element = context.computeLibraryElement(source);
    var units = <CompilationUnit>[];
    bool reportErrors = node.importUri.scheme != 'dart';
    var tree = context.resolveCompilationUnit(source, element);
    units.add(tree);
    if (reportErrors) _processErrors(source);
    for (var part in element.parts) {
      var source = part.source;
      units.add(context.resolveCompilationUnit(source, element));
      if (reportErrors) _processErrors(source);
    }
    for (var import in element.imports) {
      if (import.isDeferred && import.prefix != null) {
        node.addDependency(new ast.LibraryDependency.deferredImport(
            getLibraryReference(import.importedLibrary), import.prefix.name));
      } else {
        node.addDependency(new ast.LibraryDependency.import(
            getLibraryReference(import.importedLibrary),
            name: import.prefix?.name));
      }
    }
    for (var export in element.exports) {
      node.addDependency(new ast.LibraryDependency.export(
          getLibraryReference(export.exportedLibrary)));
    }
    _buildLibraryBody(element, node, units);
  }

  void _processErrors(Source source) {
    LineInfo lines;
    for (var error in context.computeErrors(source)) {
      if (error.errorCode is CompileTimeErrorCode ||
          error.errorCode is ParserErrorCode ||
          error.errorCode is ScannerErrorCode ||
          error.errorCode is StrongModeCode) {
        lines ??= context.computeLineInfo(source);
        errors.add(formatErrorMessage(error, source.shortName, lines));
      }
    }
  }

  void loadSdkInterface(ast.Component component, Target target) {
    var requiredSdkMembers = target.requiredSdkClasses;
    for (var libraryUri in requiredSdkMembers.keys) {
      var source = context.sourceFactory.forUri2(Uri.parse(libraryUri));
      var libraryElement = context.computeLibraryElement(source);
      for (var member in requiredSdkMembers[libraryUri]) {
        var type = libraryElement.getType(member);
        if (type == null) {
          throw 'Could not find $member in $libraryUri';
        }
        promoteToTypeLevel(getClassReference(type));
      }
    }
    _iterateTemporaryClassWorklist();
    _iterateMixinLibraryWorklist();
  }

  void loadEverything({Target target, bool compileSdk}) {
    compileSdk ??= true;
    if (compileSdk) {
      ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary()));
      if (target != null) {
        for (var uri in target.extraRequiredLibraries) {
          var library = _findLibraryElement(uri);
          if (library == null) {
            errors.add('Could not find required library $uri');
            continue;
          }
          ensureLibraryIsLoaded(getLibraryReference(library));
        }
      }
    }
    for (int i = 0; i < component.libraries.length; ++i) {
      var library = component.libraries[i];
      if (compileSdk || library.importUri.scheme != 'dart') {
        ensureLibraryIsLoaded(library);
      }
    }
  }

  /// Builds a list of sources that have been loaded.
  ///
  /// This operation may be expensive and should only be used for diagnostics.
  List<String> getLoadedFileNames() {
    var list = <String>[];
    for (var library in component.libraries) {
      LibraryElement element = context.computeLibraryElement(context
          .sourceFactory
          .forUri2(applicationRoot.absoluteUri(library.importUri)));
      for (var unit in element.units) {
        list.add(unit.source.fullName);
      }
    }
    return list;
  }

  void _iterateTemporaryClassWorklist() {
    while (temporaryClassWorklist.isNotEmpty) {
      var element = temporaryClassWorklist.removeLast();
      promoteToTypeLevel(element);
    }
  }

  void _iterateMixinLibraryWorklist() {
    // The worklist groups classes in the same library together so that we
    // request resolved ASTs for each library only once.
    while (mixinLibraryWorklist.isNotEmpty) {
      LibraryElement library = mixinLibraryWorklist.keys.first;
      _libraryBeingLoaded = library;
      List<ClassElement> classes = mixinLibraryWorklist.remove(library);
      for (var class_ in classes) {
        var classNode = getClassReference(class_);
        promoteToMixinLevel(classNode, class_, class_.computeNode());
      }
      _libraryBeingLoaded = null;
    }
    _iterateTemporaryClassWorklist();
  }

  ast.Procedure _getMainMethod(Uri uri) {
    Source source = context.sourceFactory.forUri2(uri);
    LibraryElement library = context.computeLibraryElement(source);
    var mainElement = library.entryPoint;
    if (mainElement == null) return null;
    var mainMember = getMemberReference(mainElement);
    if (mainMember is ast.Procedure && !mainMember.isAccessor) {
      return mainMember;
    }
    // Top-level 'main' getters are not supported at the moment.
    return null;
  }

  ast.Procedure _makeMissingMainMethod(ast.Library library) {
    var main = new ast.Procedure(
        new ast.Name('main'),
        ast.ProcedureKind.Method,
        new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw(
            new ast.StringLiteral('Component has no main method')))),
        isStatic: true)
      ..fileUri = library.fileUri;
    library.addMember(main);
    return main;
  }

  void loadComponent(Uri mainLibrary, {Target target, bool compileSdk}) {
    ast.Library library = getLibraryReferenceFromUri(mainLibrary);
    ensureLibraryIsLoaded(library);
    var mainMethod = _getMainMethod(mainLibrary);
    loadEverything(target: target, compileSdk: compileSdk);
    if (mainMethod == null) {
      mainMethod = _makeMissingMainMethod(library);
    }
    component.mainMethod = mainMethod;
    for (LibraryElement libraryElement in libraryElements) {
      for (CompilationUnitElement compilationUnitElement
          in libraryElement.units) {
        var source = compilationUnitElement.source;
        LineInfo lineInfo = context.computeLineInfo(source);
        List<int> sourceCode;
        try {
          sourceCode =
              const Utf8Encoder().convert(context.getContents(source).data);
        } catch (e) {
          // The source's contents could not be accessed.
          sourceCode = const <int>[];
        }
        component.uriToSource[source.uri] =
            new ast.Source(lineInfo.lineStarts, sourceCode);
      }
    }
  }

  ast.Library loadLibrary(Uri uri) {
    ast.Library library = getLibraryReferenceFromUri(uri);
    ensureLibraryIsLoaded(library);
    return library;
  }
}

class Bimap<K, V> {
  final Map<K, V> nodeMap = <K, V>{};
  final Map<V, K> inverse = <V, K>{};

  bool containsKey(K key) => nodeMap.containsKey(key);

  V operator [](K key) => nodeMap[key];

  void operator []=(K key, V value) {
    assert(!nodeMap.containsKey(key));
    nodeMap[key] = value;
    inverse[value] = key;
  }
}

/// Creates [DartLoader]s for a given configuration, while reusing the
/// [DartSdk] and [Packages] object if possible.
class DartLoaderBatch {
  Packages packages;
  DartSdk dartSdk;

  String lastSdk;
  String lastPackagePath;
  bool lastStrongMode;

  Future<DartLoader> getLoader(ast.Component component, DartOptions options,
      {String packageDiscoveryPath}) async {
    if (dartSdk == null ||
        lastSdk != options.sdk ||
        lastStrongMode != options.strongMode) {
      lastSdk = options.sdk;
      lastStrongMode = options.strongMode;
      dartSdk = createDartSdk(options.sdk, strongMode: options.strongModeSdk);
    }
    if (packages == null ||
        lastPackagePath != options.packagePath ||
        packageDiscoveryPath != null) {
      lastPackagePath = options.packagePath;
      packages = await createPackages(options.packagePath,
          discoveryPath: packageDiscoveryPath);
    }
    return new DartLoader(component, options, packages, dartSdk: dartSdk);
  }
}

Future<Packages> createPackages(String packagePath,
    {String discoveryPath}) async {
  if (packagePath != null) {
    var absolutePath = new io.File(packagePath).absolute.path;
    if (await new io.Directory(packagePath).exists()) {
      return getPackagesDirectory(new Uri.file(absolutePath));
    } else if (await new io.File(packagePath).exists()) {
      return loadPackagesFile(new Uri.file(absolutePath));
    } else {
      throw 'Packages not found: $packagePath';
    }
  }
  if (discoveryPath != null) {
    return findPackagesFromFile(Uri.parse(discoveryPath));
  }
  return Packages.noPackages;
}

AnalysisOptions createAnalysisOptions(bool strongMode) {
  return new AnalysisOptionsImpl()
    ..strongMode = strongMode
    ..generateImplicitErrors = false
    ..generateSdkErrors = false
    ..preserveComments = false
    ..hint = false
    ..enableSuperMixins = true;
}

DartSdk createDartSdk(String path, {bool strongMode, bool isSummary}) {
  if (isSummary ?? false) {
    return new SummaryBasedDartSdk(path, strongMode);
  }
  var resources = PhysicalResourceProvider.INSTANCE;
  return new FolderBasedDartSdk(resources, resources.getFolder(path))
    ..context
        .analysisOptions
        .setCrossContextOptionsFrom(createAnalysisOptions(strongMode));
}

class CustomUriResolver extends UriResolver {
  final ResourceUriResolver _resourceUriResolver;
  final Map<Uri, Uri> _customUrlMappings;

  CustomUriResolver(this._resourceUriResolver, this._customUrlMappings);

  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    // TODO(kustermann): Once dartk supports configurable imports we should be
    // able to get rid of this.
    if (uri.toString() == 'package:mojo/src/internal_contract.dart') {
      uri = actualUri = Uri.parse('dart:mojo.internal');
    }

    Uri baseUri = uri;
    String relative;
    String path = uri.path;
    int index = path.indexOf('/');
    if (index > 0) {
      baseUri = uri.replace(path: path.substring(0, index));
      relative = path.substring(index + 1);
    }
    Uri baseMapped = _customUrlMappings[baseUri];
    if (baseMapped == null) return null;

    Uri mapped = relative != null ? baseMapped.resolve(relative) : baseMapped;
    return _resourceUriResolver.resolveAbsolute(mapped, actualUri);
  }

  Uri restoreAbsolute(Source source) {
    return _resourceUriResolver.restoreAbsolute(source);
  }
}

AnalysisContext createContext(DartOptions options, Packages packages,
    {DartSdk dartSdk}) {
  bool fromSummary = options.sdkSummary != null;
  dartSdk ??= createDartSdk(fromSummary ? options.sdkSummary : options.sdk,
      strongMode: options.strongModeSdk, isSummary: fromSummary);

  var resourceProvider = PhysicalResourceProvider.INSTANCE;
  var resourceUriResolver = new ResourceUriResolver(resourceProvider);
  List<UriResolver> resolvers = [];
  var customUriMappings = options.customUriMappings;
  if (customUriMappings != null && customUriMappings.length > 0) {
    resolvers
        .add(new CustomUriResolver(resourceUriResolver, customUriMappings));
  }
  resolvers.add(new DartUriResolver(dartSdk));
  resolvers.add(resourceUriResolver);

  if (packages != null) {
    var folderMap = <String, List<Folder>>{};
    packages.asMap().forEach((String packagePath, Uri uri) {
      String path = resourceProvider.pathContext.fromUri(uri);
      folderMap[packagePath] = [resourceProvider.getFolder(path)];
    });
    resolvers.add(new PackageMapUriResolver(resourceProvider, folderMap));
  }

  AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
    ..sourceFactory = new SourceFactory(resolvers)
    ..analysisOptions = createAnalysisOptions(options.strongMode);

  options.declaredVariables.forEach((String name, String value) {
    context.declaredVariables.define(name, value);
  });

  return context;
}
