// Copyright (c) 2018, the Dart project authors.  Please see the AUTHO@override S 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/analyzer.dart' as a;
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/fasta/kernel/redirecting_factory_body.dart';
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.StrongTypeSystemImpl rules;

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

  AnalyzerToKernel._(a.AnalysisContext context, this._summaryData)
      : _resynth = a.StoreBasedSummaryResynthesizer(
            context, context.sourceFactory, /*strongMode*/ true, _summaryData),
        types = context.typeProvider,
        rules = context.typeSystem as a.StrongTypeSystemImpl;

  /// 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 context = _createContextForSummaries(summaryData, analyzerSdkSummary);
    return AnalyzerToKernel._(context, 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, []);
    }

    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_.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: e.isAbstract,
          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 subsititions 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.isSythetic. Sythetic 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);
    _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.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}) {
    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).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);
  }

  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.ElementAnnotationImpl annotation in metadata) {
      var ast = annotation.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 (var 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 : 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);
}

/// Creates a dummy Analyzer context so we can use summary resynthesizer.
///
/// This is similar to Analyzer's `LibraryContext._createResynthesizingContext`.
a.AnalysisContext _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): can we avoid creating an analysis context entirely?
  // It doesn't look like StoreBasedSummaryResynthesizer uses much of it.
  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?
  context.resultProvider = a.InputPackagesResultProvider(context, summaryData);
  return context;
}
