// Copyright (c) 2018, 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.

import 'dart:core' hide MapEntry;
import 'dart:collection';
import 'package:analyzer/dart/element/element.dart' as a;
import 'package:analyzer/dart/element/type.dart' as a;
import 'package:analyzer/file_system/physical_file_system.dart' as a;
import 'package:analyzer/src/context/context.dart' as a;
import 'package:analyzer/src/dart/element/element.dart' as a;
import 'package:analyzer/src/dart/element/member.dart' as a;
import 'package:analyzer/src/dart/element/type.dart' as a;
import 'package:analyzer/src/generated/constant.dart' as a;
import 'package:analyzer/src/generated/engine.dart' as a;
import 'package:analyzer/src/generated/source.dart' as a;
import 'package:analyzer/src/generated/type_system.dart' as a;
import 'package:analyzer/src/summary/idl.dart' as a;
import 'package:analyzer/src/summary/package_bundle_reader.dart' as a;
import 'package:analyzer/src/summary/summary_sdk.dart' as a;
import 'package:analyzer/src/generated/resolver.dart' as a
    show NamespaceBuilder, TypeProvider;
import 'package:front_end/src/api_unstable/ddc.dart'
    show RedirectingFactoryBody;
import 'package:kernel/kernel.dart';
import 'package:kernel/type_algebra.dart';

import 'type_table.dart';

/// Converts an Analyzer summary file to a Kernel [Component].
///
/// The first step is to use Analyzer's [a.StoreBasedSummaryResynthesizer] to
/// deserialize the summary file into an [a.Element] model (that way we don't
/// depend directly on the file format). Once we have elements, we visit them
/// and construct the corresponding Kernel [Node]s.
///
/// The main entry points are [convertSdk] and [convertSummaries], which
/// convert the SDK and input summaries, respectively.
///
/// Because we only need to convert summaries, we do not need to handle method
/// bodies. This lets us avoid the complexity of converting Analyzer AST nodes
/// (e.g. expressions, statements).
///
/// For constants we use Analyzer's constant evaluator compute the value from
/// the data in the summary, and then create the appropriate Kernel node to
/// reconstruct the constant (e.g. ListLiteral, ConstructorInvocation, etc).
/// See [_visitConstant] for more information.
///
/// When something refers to an element, we normally create the [Reference] but
/// leave its corresponding [NamedNode] empty until that element is visited and
/// creates the Kernel node. This takes care of cycles, and avoids recursing too
/// deeply as we convert elements.
///
/// Sometimes we need to convert an element eagerly (e.g. if we need to call
/// members on an [InterfaceType] or [Supertype], we need to create its [Class]
/// node). In that case we handle cycles in the visit method (e.g.
/// [visitClassElement]) by creating the node and linking it to its reference
/// before visiting anything else that might recurse.
///
/// Special care must be taken to make sure we link up all [Reference]s with
/// their corresponding [NamedNode]. If we don't do this [verifyReferences]
/// will throw an error. The fix is to figure out why we didn't visit the
/// element for that reference (often this is due to Analyzer's synthetic
/// fields/accessor elements; care must be taken to always reference the real
/// element).
///
/// Because we're using Analyzer's summary resynthesizer, conversion is all or
/// nothing: all summaries must be in Analyzer format, including the SDK.
/// Now that we have this implementation, it may be possible to port code from
/// Analyzer and modify it to resynthesize directly into Kernel trees, if we
/// ever need to support a mix of Kernel and Analyzer summary files.
class AnalyzerToKernel {
  final a.StoreBasedSummaryResynthesizer _resynth;
  final a.SummaryDataStore _summaryData;
  final a.TypeProvider types;
  final a.Dart2TypeSystem rules;

  final _references = HashMap<a.Element, Reference>();
  final _typeParams = HashMap<a.TypeParameterElement, TypeParameter>();
  final _namespaceBuilder = a.NamespaceBuilder();

  AnalyzerToKernel._(this._resynth, this._summaryData)
      : types = _resynth.typeProvider,
        rules = _resynth.typeSystem as a.Dart2TypeSystem;

  /// Create an Analyzer summary to Kernel tree converter, using the provided
  /// [analyzerSdkSummary] and [summaryPaths].
  ///
  /// Once the converter is created, [convertSdk] should be called to convert
  /// & return the SDK, followed by [convertSummaries] to convert & return the
  /// converted summaries.
  factory AnalyzerToKernel(
      String analyzerSdkSummary, List<String> summaryPaths) {
    var summaryData = a.SummaryDataStore(summaryPaths,
        resourceProvider: a.PhysicalResourceProvider.INSTANCE,
        disallowOverlappingSummaries: false);
    var resynthesizer =
        _createSummaryResynthesizer(summaryData, analyzerSdkSummary);
    return AnalyzerToKernel._(resynthesizer, summaryData);
  }

  /// Converts the SDK summary to a Kernel component and returns it.
  Component convertSdk() {
    // _createContextForSummaries puts the SDK summary last in the summary data.
    var sdkBundle = _summaryData.bundles.last;
    assert(sdkBundle.linkedLibraryUris.every((u) => u.startsWith('dart:')));
    var result = _toComponent(sdkBundle);
    verifyReferences();
    return result;
  }

  /// Converts the input summaries to Kernel components and return them.
  ///
  /// [convertSdk] must be called before this.
  List<Component> convertSummaries() {
    // Take all summaries except the SDK one, which is placed last in the list
    // by _createContextForSummaries.
    var bundles = _summaryData.bundles.take(_summaryData.bundles.length - 1);
    var result = bundles.map(_toComponent).toList();
    verifyReferences(); // assumption: convertSdk() is called first
    return result;
  }

  /// Dispose the Analysis Context used for summary conversion.
  void dispose() => _resynth.context.dispose();

  void verifyReferences() {
    _references.forEach((element, reference) {
      // Ensure each reference has a corresponding node.
      //
      // If it's missing a node, CFE will fail and it is difficult to debug at
      // that point because the name and element cannot be accessed.
      //
      // Typically this error means:
      // - we didn't visit an element.
      // - we didn't set the `reference: _reference(e)` for the Kernel node.
      // - we referenced a synthetic element by mistake, such as referencing the
      //   synthetic getter/setter, when we should've used the field.
      if (reference.node == null) {
        throw StateError('missing node for reference, element was: $element' +
            (element.isSynthetic ? ' (synthetic)' : ''));
      }
    });
  }

  Component _toComponent(a.PackageBundle bundle) {
    var libraries = <Library>[];
    var uriToSource = <Uri, Source>{};

    void addCompilationUnit(a.CompilationUnitElement unit) {
      uriToSource[unit.source.uri] = Source(
          unit.lineInfo.lineStarts,
          [],
          unit.uri != null ? Uri.base.resolve(unit.uri) : unit.source.uri,
          unit.source.uri);
    }

    for (var uri in bundle.unlinkedUnitUris) {
      var unitInfo = _resynth.getUnlinkedSummary(uri);
      if (unitInfo.isPartOf) {
        // Library parts are handled by their corresponding library.
        continue;
      }

      var element = _resynth.getLibraryElement(uri);
      libraries.add(visitLibraryElement(element));
      addCompilationUnit(element.definingCompilationUnit);
      element.parts.forEach(addCompilationUnit);
    }
    return Component(libraries: libraries, uriToSource: uriToSource);
  }

  Class visitClassElement(a.ClassElement e, [Library library]) {
    var ref = _reference(e);
    if (ref.node != null) return ref.asClass;

    // Construct the Class first and link the reference. This ensures the
    // (not yet finished) Class node will be returned on the line above, if we
    // happen to re-enter this visit method.
    var class_ = Class(
        name: e.name,
        isAbstract: e.isAbstract,
        fileUri: e.source.uri,
        reference: ref);

    // Classes can be visited before their library (e.g. because they're a
    // supertype of another class), so make sure to visit the library now.
    library ??= visitLibraryElement(e.library);
    library.addClass(class_);

    class_.isMixinDeclaration = e.isMixin;
    class_.typeParameters
        .addAll(e.typeParameters.map(visitTypeParameterElement));

    setParents(class_.typeParameters, class_);
    class_.implementedTypes.addAll(e.interfaces.map(_typeToSupertype));

    var fields = class_.fields;
    var constructors = class_.constructors;
    var procedures = class_.procedures;

    fields.addAll(e.fields.where((f) => !f.isSynthetic).map(visitFieldElement));

    var redirectingFactories = <Procedure>[];
    for (var ctor in e.constructors) {
      if (ctor.isFactory) {
        var factory_ = _visitFactory(ctor);
        procedures.add(factory_);
        if (ctor.redirectedConstructor != null) {
          redirectingFactories.add(factory_);
        }
      } else {
        constructors.add(visitConstructorElement(ctor));
      }
    }
    if (redirectingFactories.isNotEmpty) {
      fields.add(_createRedirectingFactoryField(redirectingFactories, e));
    }
    procedures.addAll(e.methods.map(visitMethodElement));
    procedures.addAll(e.accessors
        .where((a) => !a.isSynthetic)
        .map(visitPropertyAccessorElement));

    setParents(fields, class_);
    setParents(constructors, class_);
    setParents(procedures, class_);

    if (e.isMixinApplication) {
      class_.mixedInType = _typeToSupertype(e.mixins.last);
    }

    var supertype = _typeToSupertype(e.supertype);
    class_.supertype = _unrollMixinClasses(e, supertype, library);
    _visitAnnotations(e.metadata, class_.addAnnotation);

    // TODO(jmesserly): do we need covariance check stubs? We may be okay as
    // since we're only handling dependencies here.
    //
    // But this may lead to redundant stubs (if CFE doesn't see one on a
    // superclass) and/or break some assumptions in CFE.
    return class_;
  }

  Supertype _unrollMixinClasses(
      a.ClassElement e, Supertype supertype, Library library) {
    // TODO(jmesserly): is this enough for mixin desugaring? It only does
    // enough to create the intermediate classes.

    // Documentation below assumes the given mixin application is in one of
    // these forms:
    //
    //     class C extends S with M1, M2, M3;
    //     class Named = S with M1, M2, M3;
    //
    // When we refer to the subclass, we mean `C` or `Named`.

    /// The number of mixin classes to unroll.
    ///
    /// Named mixin applications have one less class. This can be illustrated
    /// here:
    ///
    ///     class C extends S with M1, M2, M3 {}
    ///     class Named = S with M1, M2, M3;
    ///
    /// For `C` we unroll 3 classes: _C&S&M1, _C&S&M1&M2, _C&S&M1&M2&M3.
    /// For `Named` we unroll 2 classes: _Named&S&M1, _Named&S&M1&M2.
    ///
    /// The classes themselves will be generated as:
    ///
    ///     class C extends _C&S&M1&M2&M3 {}
    ///     class Named = _Named&S&M1&M2 with M3;
    ///
    var unrollLength = e.mixins.length;
    if (e.isMixinApplication) unrollLength--;
    if (unrollLength <= 0) return supertype;

    /// The mixin application's synthetic name.
    ///
    /// The full name of the mixin application is obtained by prepending the
    /// name of the subclass (`C` or `Named` in the above examples) to the
    /// running name. For the example `C`, that leads to these names:
    ///
    /// 1. `_C&S&M1`
    /// 2. `_C&S&M1&M2`
    /// 3. `_C&S&M1&M2&M3`.
    var runningName = '_${e.name}&${e.supertype.name}';

    /// The type variables used in the current supertype and mixin, or null
    /// if this class doesn't have any type parameters.
    var usedTypeVars = e.typeParameters.isNotEmpty
        ? freeTypeParameters(supertype.asInterfaceType)
        : null;

    for (int i = 0; i < unrollLength; i++) {
      var mixin = e.mixins[i];
      runningName += "&${mixin.name}";

      var mixedInType = _typeToSupertype(mixin);
      List<TypeParameter> typeParameters;
      if (usedTypeVars != null) {
        // Any type params used by superclasses will continue to be used, plus
        // anything additional that this mixin uses.
        usedTypeVars.addAll(freeTypeParameters(mixedInType.asInterfaceType));
        if (usedTypeVars.isNotEmpty) {
          // Make fresh type parameters for this class, and then substitute them
          // into supertype and mixin type arguments (if any).
          var fresh = getFreshTypeParameters(usedTypeVars.toList());
          typeParameters = fresh.freshTypeParameters;
          supertype = fresh.substituteSuper(supertype);
          mixedInType = fresh.substituteSuper(mixedInType);
        }
      }

      var c = Class(
          name: runningName,
          isAbstract: true,
          mixedInType: mixedInType,
          supertype: supertype,
          typeParameters: typeParameters,
          fileUri: e.source.uri);

      library.addClass(c);

      // Compute the superclass to use for the next iteration of this loop.
      //
      // Any type arguments are in terms of the original class type parameters.
      // This allows us to perform consistent substitutions and have the correct
      // type arguments for the final supertype (that we return).
      supertype = Supertype(
          c,
          typeParameters != null
              ? List.of(usedTypeVars.map((t) => TypeParameterType(t)))
              : []);
    }

    return supertype;
  }

  Constructor visitConstructorElement(a.ConstructorElement e) {
    assert(!e.isFactory);
    var ref = _reference(e);
    if (ref.node != null) return ref.asConstructor;
    // By convention, instance constructors return `void` in Kernel.
    var function = _createFunction(e)..returnType = const VoidType();
    var result = Constructor(function,
        name: _getName(e),
        isConst: e.isConst,
        isExternal: e.isExternal,
        isSynthetic: e.isSynthetic,
        fileUri: e.source.uri,
        reference: ref);
    if (!result.isSynthetic) {
      // TODO(jmesserly): CFE does not respect the synthetic bit on constructors
      // so we set a bogus offset. This causes CFE to treat it as not synthetic.
      //
      // (The bug is in DillMemberBuilder.isSynthetic. Synthetic constructors
      // have different semantics/optimizations in some cases, so it is
      // important that the constructor is correctly marked.)
      result.fileOffset = 1;
    }
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  Procedure _visitFactory(a.ConstructorElement e) {
    var ref = _reference(e);
    if (ref.node != null) return ref.asProcedure;

    var result = Procedure.byReference(_getName(e), ProcedureKind.Factory, null,
        isExternal: e.isExternal,
        isConst: e.isConst,
        isStatic: true,
        fileUri: e.source.uri,
        reference: ref);

    _visitAnnotations(e.metadata, result.addAnnotation);

    // Since the factory is static, we need to create fresh type parameters that
    // match the ones in the enclosing class.
    FreshTypeParameters fresh;
    DartType Function(a.DartType) visitType;

    if (e.enclosingElement.typeParameters.isNotEmpty) {
      fresh = getFreshTypeParameters(
          visitClassElement(e.enclosingElement).typeParameters);
      visitType = (t) => fresh.substitute(_visitDartType(t, ensureNode: true));
    } else {
      visitType = _visitDartType;
    }

    result.function = _createFunction(e, fresh?.freshTypeParameters, visitType);
    result.function.parent = result;

    var redirect = e.redirectedConstructor;
    if (redirect == null) return result;

    // Get the raw constructor element before the type is applied.
    var rawRedirect =
        redirect is a.ConstructorMember ? redirect.baseElement : redirect;

    // TODO(jmesserly): conceptually we only need a reference here, but
    // RedirectingFactoryBody requires the complete node.
    var ctor = rawRedirect.isFactory
        ? _visitFactory(rawRedirect)
        : visitConstructorElement(rawRedirect);

    var redirectedType = redirect.type.returnType as a.InterfaceType;
    var typeArgs = redirectedType.typeArguments.map(visitType).toList();
    result.function.body = RedirectingFactoryBody(ctor, typeArgs);
    return result;
  }

  Field _createRedirectingFactoryField(
      List<Procedure> factories, a.ClassElement c) {
    return Field(_getName(c, "_redirecting#"),
        isStatic: true,
        initializer: ListLiteral(List.of(factories.map((f) => StaticGet(f)))),
        fileUri: c.source.uri);
  }

  LibraryDependency visitExportElement(a.ExportElement e) =>
      LibraryDependency.byReference(
          LibraryDependency.ExportFlag,
          const [],
          _reference(e.exportedLibrary),
          null,
          e.combinators.map(_visitCombinator).toList());

  Field visitFieldElement(a.FieldElement e) {
    var result = Field(_getName(e),
        type: _visitDartType(e.type),
        initializer: null,
        isFinal: e.isFinal,
        isConst: e.isConst,
        isStatic: e.isStatic,
        fileUri: e.source.uri,
        reference: _reference(e));
    if (!e.isFinal && !e.isConst) {
      var class_ = e.enclosingElement;
      if (class_.typeParameters.isNotEmpty) {
        result.isGenericCovariantImpl = _isGenericCovariant(class_, e.type);
      }
    }
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  Procedure visitFunctionElement(a.FunctionElement e) {
    var result = Procedure.byReference(
        _getName(e), ProcedureKind.Method, _createFunction(e),
        isExternal: e.isExternal,
        fileUri: e.source.uri,
        isStatic: true,
        reference: _reference(e));
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  Typedef visitFunctionTypeAliasElement(a.FunctionTypeAliasElement e,
      [Library library]) {
    var ref = _reference(e);
    if (ref.node != null) return ref.asTypedef;

    var t = Typedef(e.name, null, reference: ref, fileUri: e.source.uri);
    library ??= visitLibraryElement(e.library);
    library.addTypedef(t);

    a.FunctionType type;
    var typeParams = e.typeParameters;
    if (e is a.GenericTypeAliasElement) {
      type = e.function.type;
    } else {
      type = e.type;
      if (typeParams.isNotEmpty) {
        // Skip past the type formals, we'll add them back below, so these
        // type parameter names will end up in scope in the generated JS.
        type = type.instantiate(typeParams.map((f) => f.type).toList());
      }
    }
    t.typeParameters.addAll(typeParams.map(visitTypeParameterElement));
    setParents(t.typeParameters, t);
    t.type = _visitDartType(type, originTypedef: t.thisType);
    _visitAnnotations(e.metadata, t.addAnnotation);
    return t;
  }

  LibraryDependency visitImportElement(a.ImportElement e) =>
      LibraryDependency.byReference(0, const [], _reference(e.importedLibrary),
          null, e.combinators.map(_visitCombinator).toList());

  Library visitLibraryElement(a.LibraryElement e) {
    var ref = _reference(e);
    if (ref.node != null) return ref.asLibrary;

    var library = Library(e.source.uri,
        name: e.name,
        fileUri: e.definingCompilationUnit.source.uri,
        reference: ref);
    library.fileOffset = 0;

    _visitAnnotations(e.metadata, library.addAnnotation);
    e.imports.map(visitImportElement).forEach(library.addDependency);
    e.exports.map(visitExportElement).forEach(library.addDependency);
    e.parts.map((p) => LibraryPart(const [], p.uri)).forEach(library.addPart);

    _visitUnit(a.CompilationUnitElement u) {
      for (var t in u.types) {
        visitClassElement(t, library);
      }
      for (var t in u.mixins) {
        visitClassElement(t, library);
      }
      for (var t in u.functionTypeAliases) {
        visitFunctionTypeAliasElement(t, library);
      }
      u.functions.map(visitFunctionElement).forEach(library.addMember);
      u.accessors
          .where((a) => !a.isSynthetic)
          .map(visitPropertyAccessorElement)
          .forEach(library.addMember);
      u.topLevelVariables
          .map(visitTopLevelVariableElement)
          .forEach(library.addMember);
    }

    _visitUnit(e.definingCompilationUnit);
    e.parts.forEach(_visitUnit);

    var libraryImpl = e as a.LibraryElementImpl;
    libraryImpl.publicNamespace ??=
        _namespaceBuilder.createPublicNamespaceForLibrary(e);
    libraryImpl.exportNamespace ??=
        _namespaceBuilder.createExportNamespaceForLibrary(e);
    var publicNames = libraryImpl.publicNamespace.definedNames;
    var exportNames = libraryImpl.exportNamespace.definedNames;
    exportNames.forEach((name, value) {
      if (!publicNames.containsKey(name)) {
        value = value is a.PropertyAccessorElement && value.isSynthetic
            ? value.variable
            : value;
        library.additionalExports.add(_reference(value));
      }
    });
    return library;
  }

  Procedure visitMethodElement(a.MethodElement e) {
    var result = Procedure.byReference(
        _getName(e),
        e.isOperator ? ProcedureKind.Operator : ProcedureKind.Method,
        _createFunction(e),
        isAbstract: e.isAbstract,
        isStatic: e.isStatic,
        isExternal: e.isExternal,
        fileUri: e.source.uri,
        reference: _reference(e));
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  Procedure visitPropertyAccessorElement(a.PropertyAccessorElement e) {
    var result = Procedure.byReference(
        _getName(e, e.variable.name),
        e.isGetter ? ProcedureKind.Getter : ProcedureKind.Setter,
        _createFunction(e),
        isAbstract: e.isAbstract,
        isStatic: e.isStatic,
        isExternal: e.isExternal,
        fileUri: e.source.uri,
        reference: _reference(e));
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  Field visitTopLevelVariableElement(a.TopLevelVariableElement e) {
    var result = Field(_getName(e),
        type: _visitDartType(e.type),
        initializer: null,
        isFinal: e.isFinal,
        isConst: e.isConst,
        isStatic: e.isStatic,
        fileUri: e.source.uri,
        reference: _reference(e));
    _visitAnnotations(e.metadata, result.addAnnotation);
    return result;
  }

  TypeParameter visitTypeParameterElement(a.TypeParameterElement e) {
    var t = _typeParams[e];
    if (t != null) return t;
    _typeParams[e] = t = TypeParameter(e.name);

    var hasBound = e.bound != null;
    t.bound =
        hasBound ? _visitDartType(e.bound) : _visitDartType(types.objectType);
    t.defaultType = hasBound ? t.bound : const DynamicType();

    var enclosingElement = e.enclosingElement;
    if (hasBound && enclosingElement is a.ClassMemberElement) {
      var class_ = enclosingElement.enclosingElement;
      if (class_ != null && class_.typeParameters.isNotEmpty) {
        t.isGenericCovariantImpl = _isGenericCovariant(class_, e.bound);
      }
    }
    return t;
  }

  Name _getName(a.Element e, [String name]) {
    name ??= e.name;
    return Name.byReference(
        name, name.startsWith('_') ? _reference(e.library) : null);
  }

  /// Converts an Analyzer [type] to a Kernel type.
  ///
  /// If [ensureNode] is set, the reference to the [Class] or [Typedef] will
  /// populated with the node (creating it if needed). Many members on
  /// [InterfaceType] and [TypedefType] rely on having a node present, so this
  /// enables the use of those members if they're needed by the converter.
  DartType _visitDartType(a.DartType type,
      {bool ensureNode = false, TypedefType originTypedef}) {
    if (type.isVoid) {
      return const VoidType();
    } else if (type.isDynamic) {
      return const DynamicType();
    } else if (type.isBottom) {
      return const BottomType();
    } else if (type is a.TypeParameterType) {
      return TypeParameterType(visitTypeParameterElement(type.element));
    }

    visit(a.DartType t) => _visitDartType(t, ensureNode: ensureNode);

    if (type is a.InterfaceType) {
      var ref = ensureNode
          ? visitClassElement(type.element).reference
          : _reference(type.element);
      var typeArgs = type.typeArguments;
      var newTypeArgs = typeArgs.isNotEmpty
          ? typeArgs.map(visit).toList()
          : const <DartType>[];
      return InterfaceType.byReference(ref, newTypeArgs);
    }

    var f = type as a.FunctionType;
    if (f.name != null && f.name != '') {
      var ref = ensureNode
          ? visitFunctionTypeAliasElement(
                  f.element as a.FunctionTypeAliasElement)
              .reference
          : _reference(f.element);
      return TypedefType.byReference(ref, f.typeArguments.map(visit).toList());
    }
    var params = f.parameters;
    var positional = f.normalParameterTypes.map(visit).toList();
    positional.addAll(f.optionalParameterTypes.map(visit));

    var named = <NamedType>[];
    f.namedParameterTypes.forEach((name, type) {
      named.add(NamedType(name, visit(type)));
    });

    return FunctionType(positional, visit(f.returnType),
        typeParameters: f.typeFormals.map(visitTypeParameterElement).toList(),
        namedParameters: named,
        requiredParameterCount: params.where((p) => !p.isOptional).length,
        typedefType: originTypedef);
  }

  Supertype _typeToSupertype(a.InterfaceType t) {
    if (t == null) return null;
    return Supertype(
        visitClassElement(t.element),
        t.typeArguments
            .map((a) => _visitDartType(a, ensureNode: true))
            .toList());
  }

  Combinator _visitCombinator(a.NamespaceCombinator combinator) {
    bool isShow;
    List<String> names;
    if (combinator is a.ShowElementCombinator) {
      isShow = true;
      names = combinator.shownNames;
    } else {
      isShow = false;
      names = (combinator as a.HideElementCombinator).hiddenNames;
    }
    return Combinator(isShow, names);
  }

  /// Creates a function node for the executable element [e], optionally using
  /// the supplied [typeParameters] and calling [visitType] so it can perform
  /// any necessary substitutions.
  FunctionNode _createFunction(a.ExecutableElement e,
      [List<TypeParameter> typeParameters,
      DartType Function(a.DartType) visitType]) {
    visitType ??= _visitDartType;

    var enclosingElement = e.enclosingElement;
    var class_ = enclosingElement is a.ClassElement ? enclosingElement : null;

    visitParameter(a.ParameterElement e) {
      var result = VariableDeclaration(e.name,
          type: visitType(e.type),
          isFinal: e.isFinal,
          isFieldFormal: e.isInitializingFormal,
          isCovariant: e.isCovariant,
          initializer:
              e.isOptional ? _visitConstant(e.computeConstantValue()) : null);
      if (class_ != null && class_.typeParameters.isNotEmpty) {
        result.isGenericCovariantImpl = _isGenericCovariant(class_, e.type);
      }
      return result;
    }

    var params = e.parameters;
    var asyncMarker = _getAsyncMarker(e);
    return FunctionNode(null,
        typeParameters: typeParameters ??
            e.typeParameters.map(visitTypeParameterElement).toList(),
        positionalParameters:
            params.where((p) => !p.isNamed).map(visitParameter).toList(),
        namedParameters:
            params.where((p) => p.isNamed).map(visitParameter).toList(),
        requiredParameterCount: params.where((p) => !p.isOptional).length,
        returnType: visitType(e.returnType),
        asyncMarker: asyncMarker,
        dartAsyncMarker: asyncMarker);
  }

  Reference _reference(a.Element e) {
    if (e == null) throw ArgumentError('null element');
    return _references.putIfAbsent(e, () => Reference());
  }

  bool _isGenericCovariant(a.ClassElement c, a.DartType type) {
    var classUpperBound = rules.instantiateToBounds(c.type) as a.InterfaceType;
    var typeUpperBound = type.substitute2(classUpperBound.typeArguments,
        a.TypeParameterTypeImpl.getTypes(classUpperBound.typeParameters));
    // Is it safe to assign the upper bound of the field/parameter to it?
    // If not then we'll need a runtime check.
    return !rules.isSubtypeOf(typeUpperBound, type);
  }

  /// Transforms a metadata annotation from Analyzer to Kernel format.
  ///
  /// If needed this uses Analyzer's constant evaluation to evaluate the AST,
  /// and then converts the resulting constant value into a Kernel tree.
  /// By first computing the expression's constant value, we avoid having to
  /// convert a bunch of Analyzer ASTs nodes. Instead we can convert the more
  /// limited set of constant values allowed in Dart (see [_visitConstant]).
  void _visitAnnotations(List<a.ElementAnnotation> metadata,
      void Function(Expression) addAnnotation) {
    if (metadata.isEmpty) return;

    for (a.ElementAnnotation annotation in metadata) {
      var ast = (annotation as a.ElementAnnotationImpl).annotationAst;
      var arguments = ast.arguments;
      if (arguments == null) {
        var e = ast.element;
        e = e is a.PropertyAccessorElement && e.isSynthetic ? e.variable : e;
        addAnnotation(StaticGet.byReference(_reference(e)));
      } else {
        // Use Analyzer's constant evaluation to produce the constant, then
        // emit the resulting value. We do this to avoid handling all of the
        // AST nodes that might be needed for constant evaluation. Instead we
        // just serialize the resulting value to a Kernel expression that will
        // reproduce it.
        addAnnotation(_visitConstant(annotation.computeConstantValue()));
      }
    }
  }

  /// Converts an Analyzer constant value in [obj] to a Kernel expression
  /// (usually a Literal or ConstructorInvocation) that will recreate that
  /// constant value.
  Expression _visitConstant(a.DartObject obj) {
    if (obj == null || obj.isNull || !obj.hasKnownValue) return NullLiteral();

    var type = obj.type;
    if (identical(type, types.boolType)) {
      var value = obj.toBoolValue();
      return value != null ? BoolLiteral(value) : NullLiteral();
    }
    if (identical(type, types.intType)) {
      return IntLiteral(obj.toIntValue());
    }
    if (identical(type, types.doubleType)) {
      return DoubleLiteral(obj.toDoubleValue());
    }
    if (identical(type, types.stringType)) {
      return StringLiteral(obj.toStringValue());
    }
    if (identical(type, types.symbolType)) {
      return SymbolLiteral(obj.toSymbolValue());
    }
    if (identical(type, types.typeType)) {
      return TypeLiteral(_visitDartType(obj.toTypeValue()));
    }
    if (type is a.InterfaceType) {
      if (type.element == types.listType.element) {
        return ListLiteral(obj.toListValue().map(_visitConstant).toList(),
            typeArgument: _visitDartType(type.typeArguments[0]), isConst: true);
      }
      if (type.element == types.mapType.element) {
        var entries = obj
            .toMapValue()
            .entries
            .map(
                (e) => MapEntry(_visitConstant(e.key), _visitConstant(e.value)))
            .toList();
        return MapLiteral(entries,
            keyType: _visitDartType(type.typeArguments[0]),
            valueType: _visitDartType(type.typeArguments[1]),
            isConst: true);
      }
      if (obj is a.DartObjectImpl && obj.isUserDefinedObject) {
        var classElem = type.element;
        if (classElem.isEnum) {
          // TODO(jmesserly): we should be able to use `getField('index')` but
          // in some cases Analyzer uses the name of the static field that
          // contains the enum, rather than the `index` field, due to a bug.
          //
          // So we just grab the one instance field, regardless of its name.
          var index = obj.fields.values.single.toIntValue();
          var field =
              classElem.fields.where((f) => f.type == type).elementAt(index);
          return StaticGet.byReference(_reference(field));
        }
        var invocation = obj.getInvocation();
        var constructor = invocation.constructor;
        // For a redirecting const factory, the constant constructor will be
        // from the original one, but the `type` will match the redirected type.
        //
        // This leads to mismatch in how we call this constructor. So we need to
        // find the redirected one.
        for (a.ConstructorElement rc;
            (rc = constructor.redirectedConstructor) != null;) {
          constructor = rc;
        }
        constructor = constructor is a.ConstructorMember
            ? constructor.baseElement
            : constructor;
        return ConstructorInvocation.byReference(
            _reference(constructor),
            Arguments(
                invocation.positionalArguments.map(_visitConstant).toList(),
                named: invocation.namedArguments.entries
                    .map((e) => NamedExpression(e.key, _visitConstant(e.value)))
                    .toList(),
                types: type.typeArguments.map(_visitDartType).toList()),
            isConst: true);
      }
    }
    if (obj is a.DartObjectImpl && type is a.FunctionType) {
      var e = obj.toFunctionValue();
      e = e is a.PropertyAccessorElement && e.isSynthetic
          ? e.variable as a.ExecutableElement
          : e;
      // TODO(jmesserly): support generic tear-off implicit instantiation.
      return StaticGet.byReference(_reference(e));
    }
    throw UnsupportedError('unknown constant type `$type`: $obj');
  }
}

AsyncMarker _getAsyncMarker(a.ExecutableElement e) {
  return e.isGenerator
      ? (e.isAsynchronous ? AsyncMarker.AsyncStar : AsyncMarker.SyncStar)
      : (e.isAsynchronous ? AsyncMarker.Async : AsyncMarker.Sync);
}

a.StoreBasedSummaryResynthesizer _createSummaryResynthesizer(
    a.SummaryDataStore summaryData, String dartSdkPath) {
  var context = _createContextForSummaries(summaryData, dartSdkPath);
  var resynthesizer = a.StoreBasedSummaryResynthesizer(
      context, null, context.sourceFactory, /*strongMode*/ true, summaryData);
  resynthesizer.finishCoreAsyncLibraries();
  context.typeProvider = resynthesizer.typeProvider;
  return resynthesizer;
}

/// Creates a dummy Analyzer context so we can use summary resynthesizer.
///
/// This is similar to Analyzer's `LibraryContext._createResynthesizingContext`.
a.AnalysisContextImpl _createContextForSummaries(
    a.SummaryDataStore summaryData, String dartSdkPath) {
  var sdk = a.SummaryBasedDartSdk(dartSdkPath, true,
      resourceProvider: a.PhysicalResourceProvider.INSTANCE);
  var sdkSummaryBundle = sdk.getLinkedBundle();
  if (sdkSummaryBundle != null) {
    summaryData.addBundle(null, sdkSummaryBundle);
  }

  // TODO(jmesserly): use RestrictedAnalysisContext.
  var context = a.AnalysisEngine.instance.createAnalysisContext()
      as a.AnalysisContextImpl;
  context.sourceFactory = a.SourceFactory(
      [a.DartUriResolver(sdk), a.InSummaryUriResolver(null, summaryData)]);
  context.useSdkCachePartition = false;
  // TODO(jmesserly): do we need to set analysisOptions or declaredVariables?
  return context;
}
