// Copyright (c) 2015, 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 summary_resynthesizer;

import 'dart:collection';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/expr_builder.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/summary_sdk.dart';

/**
 * Expando for marking types with implicit type arguments, which are the same as
 * type parameter bounds (in strong mode), or `dynamic` (in spec mode).
 *
 * If a type is associated with a non-null value in this expando, then it has
 * implicit type arguments.
 */
final _typesWithImplicitTypeArguments = new Expando();

/// An instance of [LibraryResynthesizer] is responsible for resynthesizing the
/// elements in a single library from that library's summary.
abstract class LibraryResynthesizer {
  /// Builds the export namespace for the library by aggregating together its
  /// public namespace and export names.
  Namespace buildExportNamespace();

  /// Builds the public namespace for the library.
  Namespace buildPublicNamespace();
}

/// [LibraryResynthesizerContextMixin] contains methods useful for implementing
/// the [LibraryResynthesizerContext] interface.
abstract class LibraryResynthesizerContextMixin
    implements LibraryResynthesizerContext {
  /// Gets the associated [LibraryResynthesizer].
  LibraryResynthesizer get resynthesizer;

  @override
  Namespace buildExportNamespace() => resynthesizer.buildExportNamespace();

  @override
  Namespace buildPublicNamespace() => resynthesizer.buildPublicNamespace();
}

/// [LibraryResynthesizerMixin] contains methods useful for implementing the
/// [LibraryResynthesizer] interface.
abstract class LibraryResynthesizerMixin implements LibraryResynthesizer {
  /// Gets the library element being resynthesized.
  LibraryElement get library;

  /// Gets the list of export names created during summary linking.
  List<LinkedExportName> get linkedExportNames;

  /// Builds or retrieves an [Element] for the entity referred to by the given
  /// [exportName].
  Element buildExportName(LinkedExportName exportName);

  @override
  Namespace buildExportNamespace() {
    Namespace publicNamespace = library.publicNamespace;
    List<LinkedExportName> exportNames = linkedExportNames;
    Map<String, Element> definedNames = new HashMap<String, Element>();
    // Start by populating all the public names from [publicNamespace].
    publicNamespace.definedNames.forEach((String name, Element element) {
      definedNames[name] = element;
    });
    // Add all the names from [exportNames].
    for (LinkedExportName exportName in exportNames) {
      String name = exportName.name;
      if (!definedNames.containsKey(name)) {
        definedNames[name] = buildExportName(exportName);
      }
    }
    return new Namespace(definedNames);
  }

  @override
  Namespace buildPublicNamespace() =>
      new NamespaceBuilder().createPublicNamespaceForLibrary(library);
}

class RecursiveInstantiateToBounds {}

/// Data structure used during resynthesis to record all the information that is
/// known about how to resynthesize a single entry in [LinkedUnit.references]
/// (and its associated entry in [UnlinkedUnit.references], if it exists).
abstract class ReferenceInfo {
  /// The element referred to by this reference, or `null` if there is no
  /// associated element (e.g. because it is a reference to an undefined
  /// entity).
  Element get element;

  /// The enclosing [_ReferenceInfo], or `null` for top-level elements.
  ReferenceInfo get enclosing;

  /// Indicates whether the thing being referenced has at least one type
  /// parameter.
  bool get hasTypeParameters;

  /// The name of the entity referred to by this reference.
  String get name;

  /// If this reference refers to a non-generic type, the type it refers to.
  /// Otherwise `null`.
  DartType get type;
}

/**
 * Implementation of [ElementResynthesizer] used when resynthesizing an element
 * model from summaries.
 */
abstract class SummaryResynthesizer extends ElementResynthesizer {
  /**
   * Source factory used to convert URIs to [Source] objects.
   */
  final SourceFactory sourceFactory;

  /**
   * Cache of [Source] objects that have already been converted from URIs.
   */
  final Map<String, Source> _sources = <String, Source>{};

  /**
   * The `dart:core` library for the context.
   */
  LibraryElementImpl _coreLibrary;

  /**
   * The `dart:async` library for the context.
   */
  LibraryElementImpl _asyncLibrary;

  /**
   * The [TypeProvider] used to obtain SDK types during resynthesis.
   */
  TypeProvider _typeProvider;

  /**
   * Map of compilation units resynthesized from summaries.  The two map keys
   * are the first two elements of the element's location (the library URI and
   * the compilation unit URI).
   */
  final Map<String, Map<String, CompilationUnitElementImpl>>
      _resynthesizedUnits = <String, Map<String, CompilationUnitElementImpl>>{};

  /**
   * Map of top level elements resynthesized from summaries.  The three map
   * keys are the first three elements of the element's location (the library
   * URI, the compilation unit URI, and the name of the top level declaration).
   */
  final Map<String, Map<String, Map<String, Element>>> _resynthesizedElements =
      <String, Map<String, Map<String, Element>>>{};

  /**
   * Map of libraries which have been resynthesized from summaries.  The map
   * key is the library URI.
   */
  final Map<String, LibraryElement> _resynthesizedLibraries =
      <String, LibraryElement>{};

  SummaryResynthesizer(AnalysisContext context, this.sourceFactory, bool _)
      : super(context) {
    _buildTypeProvider();
  }

  /**
   * Number of libraries that have been resynthesized so far.
   */
  int get resynthesisCount => _resynthesizedLibraries.length;

  /**
   * Indicates whether the summary should be resynthesized assuming strong mode
   * semantics.
   */
  @deprecated
  bool get strongMode => true;

  /**
   * The [TypeProvider] used to obtain SDK types during resynthesis.
   */
  TypeProvider get typeProvider => _typeProvider;

  /**
   * The [TypeSystem] used perform type operations.
   */
  TypeSystem get typeSystem => context.typeSystem;

  /**
   * The client installed this resynthesizer into the context, and set its
   * type provider, so it is not safe to access type provider to create
   * additional types.
   */
  void finishCoreAsyncLibraries() {
    _coreLibrary.createLoadLibraryFunction(_typeProvider);
    _asyncLibrary.createLoadLibraryFunction(_typeProvider);
  }

  @override
  Element getElement(ElementLocation location) {
    List<String> components = location.components;
    String libraryUri = components[0];
    // Resynthesize locally.
    if (components.length == 1) {
      return getLibraryElement(libraryUri);
    } else if (components.length == 2) {
      LibraryElement libraryElement = getLibraryElement(libraryUri);
      // Try to find the unit element.
      {
        Map<String, CompilationUnitElement> libraryMap =
            _resynthesizedUnits[libraryUri];
        assert(libraryMap != null);
        String unitUri = components[1];
        CompilationUnitElement unitElement = libraryMap[unitUri];
        if (unitElement != null) {
          return unitElement;
        }
      }
      // Try to find the prefix element.
      {
        String name = components[1];
        for (PrefixElement prefix in libraryElement.prefixes) {
          if (prefix.name == name) {
            return prefix;
          }
        }
      }
      // Fail.
      throw new Exception('The element not found in summary: $location');
    } else if (components.length == 3 || components.length == 4) {
      String unitUri = components[1];
      // Prepare elements-in-units in the library.
      Map<String, Map<String, Element>> unitsInLibrary =
          _resynthesizedElements[libraryUri];
      if (unitsInLibrary == null) {
        unitsInLibrary = new HashMap<String, Map<String, Element>>();
        _resynthesizedElements[libraryUri] = unitsInLibrary;
      }
      // Prepare elements in the unit.
      Map<String, Element> elementsInUnit = unitsInLibrary[unitUri];
      if (elementsInUnit == null) {
        // Prepare the CompilationUnitElementImpl.
        Map<String, CompilationUnitElementImpl> libraryMap =
            _resynthesizedUnits[libraryUri];
        if (libraryMap == null) {
          getLibraryElement(libraryUri);
          libraryMap = _resynthesizedUnits[libraryUri];
          assert(libraryMap != null);
        }
        CompilationUnitElementImpl unitElement = libraryMap[unitUri];
        // Fill elements in the unit map.
        if (unitElement != null) {
          elementsInUnit = new HashMap<String, Element>();
          void putElement(Element e) {
            String id =
                e is PropertyAccessorElementImpl ? e.identifier : e.name;
            elementsInUnit[id] = e;
          }

          unitElement.accessors.forEach(putElement);
          unitElement.enums.forEach(putElement);
          unitElement.functions.forEach(putElement);
          unitElement.functionTypeAliases.forEach(putElement);
          unitElement.mixins.forEach(putElement);
          unitElement.topLevelVariables.forEach(putElement);
          unitElement.types.forEach(putElement);
          unitsInLibrary[unitUri] = elementsInUnit;
        }
      }
      // Get the element.
      Element element = elementsInUnit[components[2]];
      if (element != null && components.length == 4) {
        String name = components[3];
        Element parentElement = element;
        if (parentElement is ClassElement) {
          if (name.endsWith('?')) {
            element =
                parentElement.getGetter(name.substring(0, name.length - 1));
          } else if (name.endsWith('=')) {
            element =
                parentElement.getSetter(name.substring(0, name.length - 1));
          } else if (name.isEmpty) {
            element = parentElement.unnamedConstructor;
          } else {
            element = parentElement.getField(name) ??
                parentElement.getMethod(name) ??
                parentElement.getNamedConstructor(name);
          }
        } else {
          // The only elements that are currently retrieved using 4-component
          // locations are class members.
          throw new StateError(
              '4-element locations not supported for ${element.runtimeType}');
        }
      }
      if (element == null) {
        throw new Exception('Element not found in summary: $location');
      }
      return element;
    } else {
      throw new UnimplementedError(location.toString());
    }
  }

  /**
   * Get the [LibraryElement] for the given [uri], resynthesizing it if it
   * hasn't been resynthesized already.
   */
  LibraryElement getLibraryElement(String uri) {
    return _resynthesizedLibraries.putIfAbsent(uri, () {
      LinkedLibrary serializedLibrary = getLinkedSummary(uri);
      Source librarySource = _getSource(uri);
      if (serializedLibrary == null) {
        LibraryElementImpl libraryElement =
            new LibraryElementImpl(context, '', -1, 0);
        libraryElement.isSynthetic = true;
        CompilationUnitElementImpl unitElement =
            new CompilationUnitElementImpl();
        libraryElement.definingCompilationUnit = unitElement;
        unitElement.source = librarySource;
        unitElement.librarySource = librarySource;
        libraryElement.createLoadLibraryFunction(typeProvider);
        libraryElement.publicNamespace = new Namespace({});
        libraryElement.exportNamespace = new Namespace({});
        return libraryElement;
      }
      UnlinkedUnit unlinkedSummary = getUnlinkedSummary(uri);
      if (unlinkedSummary == null) {
        throw new StateError('Unable to find unlinked summary: $uri');
      }
      List<UnlinkedUnit> serializedUnits = <UnlinkedUnit>[unlinkedSummary];
      for (String part in serializedUnits[0].publicNamespace.parts) {
        Source partSource = sourceFactory.resolveUri(librarySource, part);
        UnlinkedUnit partUnlinkedUnit;
        if (partSource != null) {
          String partAbsUri = partSource.uri.toString();
          partUnlinkedUnit = getUnlinkedSummary(partAbsUri);
        }
        serializedUnits.add(partUnlinkedUnit ??
            new UnlinkedUnitBuilder(codeRange: new CodeRangeBuilder()));
      }
      _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
          this, serializedLibrary, serializedUnits, librarySource);
      LibraryElement library = libraryResynthesizer.buildLibrary();
      _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
      return library;
    });
  }

  /**
   * Return the [LinkedLibrary] for the given [uri] or `null` if it could not
   * be found.  Caller has already checked that `parent.hasLibrarySummary(uri)`
   * returns `false`.
   */
  LinkedLibrary getLinkedSummary(String uri);

  /**
   * Return the [UnlinkedUnit] for the given [uri] or `null` if it could not
   * be found.  Caller has already checked that `parent.hasLibrarySummary(uri)`
   * returns `false`.
   */
  UnlinkedUnit getUnlinkedSummary(String uri);

  /**
   * Return `true` if this resynthesizer can provide summaries of the libraries
   * with the given [uri].  Caller has already checked that
   * `parent.hasLibrarySummary(uri)` returns `false`.
   */
  bool hasLibrarySummary(String uri);

  void _buildTypeProvider() {
    _coreLibrary = getLibraryElement('dart:core') as LibraryElementImpl;
    _asyncLibrary = getLibraryElement('dart:async') as LibraryElementImpl;
    SummaryTypeProvider summaryTypeProvider = new SummaryTypeProvider();
    summaryTypeProvider.initializeCore(_coreLibrary);
    summaryTypeProvider.initializeAsync(_asyncLibrary);
    _typeProvider = summaryTypeProvider;
  }

  /**
   * Get the [Source] object for the given [uri].
   */
  Source _getSource(String uri) {
    return _sources.putIfAbsent(uri, () => sourceFactory.forUri(uri));
  }
}

class SummaryResynthesizerContext implements ResynthesizerContext {
  final _UnitResynthesizer unitResynthesizer;

  SummaryResynthesizerContext(this.unitResynthesizer);

  @deprecated
  @override
  bool get isStrongMode => true;

  @override
  ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
    return unitResynthesizer.buildAnnotation(context, uc);
  }

  @override
  Expression buildExpression(ElementImpl context, UnlinkedExpr uc) {
    return unitResynthesizer._buildConstExpression(context, uc);
  }

  @override
  UnitExplicitTopLevelAccessors buildTopLevelAccessors() {
    return unitResynthesizer.buildUnitExplicitTopLevelAccessors();
  }

  @override
  UnitExplicitTopLevelVariables buildTopLevelVariables() {
    return unitResynthesizer.buildUnitExplicitTopLevelVariables();
  }

  @override
  TopLevelInferenceError getTypeInferenceError(int slot) {
    return unitResynthesizer.getTypeInferenceError(slot);
  }

  @override
  bool inheritsCovariant(int slot) {
    return unitResynthesizer.parametersInheritingCovariant.contains(slot);
  }

  @override
  bool isInConstCycle(int slot) {
    return unitResynthesizer.constCycles.contains(slot);
  }

  @override
  ConstructorElement resolveConstructorRef(
      ElementImpl context, EntityRef entry) {
    return unitResynthesizer._getConstructorForEntry(context, entry);
  }

  @override
  DartType resolveLinkedType(ElementImpl context, int slot) {
    return unitResynthesizer.buildLinkedType(context, slot);
  }

  @override
  DartType resolveTypeRef(ElementImpl context, EntityRef type,
      {bool defaultVoid: false,
      bool instantiateToBoundsAllowed: true,
      bool declaredType: false}) {
    return unitResynthesizer.buildType(context, type,
        defaultVoid: defaultVoid,
        instantiateToBoundsAllowed: instantiateToBoundsAllowed,
        declaredType: declaredType);
  }
}

/// An instance of [_UnitResynthesizer] is responsible for resynthesizing the
/// elements in a single unit from that unit's summary.
abstract class UnitResynthesizer {
  /// Gets the [LibraryElement] being resynthesized.
  LibraryElement get library;

  /// Gets the [TypeProvider], which may be used to create core types.
  TypeProvider get typeProvider;

  /// Gets the [TypeSystem], which may be used to create core types.
  TypeSystem get typeSystem;

  /// Builds a [DartType] object based on a [EntityRef].  This [DartType]
  /// may refer to elements in other libraries than the library being
  /// deserialized, so handles may be used to avoid having to deserialize other
  /// libraries in the process.
  DartType buildType(ElementImpl context, EntityRef type);

  /// Builds a [DartType] object based on [ReferenceInfo], which should refer to
  /// a class, by filling in the type arguments as appropriate, and performing
  /// instantiate to bounds if necessary.
  DartType buildTypeForClassInfo(ReferenceInfo info, int numTypeArguments,
      DartType getTypeArgument(int i));

  /// Returns the defining type for a [ConstructorElement] by applying
  /// [typeArgumentRefs] to the given linked [info].  Returns [DynamicTypeImpl]
  /// if the [info] is unresolved.
  DartType createConstructorDefiningType(ElementImpl context,
      ReferenceInfo info, List<EntityRef> typeArgumentRefs);

  /// Determines if the given [type] has implicit type arguments.
  bool doesTypeHaveImplicitArguments(ParameterizedType type);

  /// Returns the [ConstructorElement] corresponding to the given linked [info],
  /// using the [classType] which has already been computed (e.g. by
  /// [createConstructorDefiningType]).  Both cases when [info] is a
  /// [ClassElement] and [ConstructorElement] are supported.
  ConstructorElement getConstructorForInfo(
      InterfaceType classType, ReferenceInfo info);

  /// Returns the [ReferenceInfo] with the given [index].
  ReferenceInfo getReferenceInfo(int index);
}

/// [UnitResynthesizerMixin] contains methods useful for implementing the
/// [UnitResynthesizer] interface.
abstract class UnitResynthesizerMixin implements UnitResynthesizer {
  @override
  DartType createConstructorDefiningType(ElementImpl context,
      ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
    bool isClass = info.element is ClassElement;
    ReferenceInfo classInfo = isClass ? info : info.enclosing;
    if (classInfo == null) {
      return DynamicTypeImpl.instance;
    }
    List<DartType> typeArguments =
        typeArgumentRefs.map((t) => buildType(context, t)).toList();
    return buildTypeForClassInfo(classInfo, typeArguments.length, (i) {
      if (i < typeArguments.length) {
        return typeArguments[i];
      } else {
        return DynamicTypeImpl.instance;
      }
    });
  }

  @override
  ConstructorElement getConstructorForInfo(
      InterfaceType classType, ReferenceInfo info) {
    ConstructorElement element;
    Element infoElement = info.element;
    if (infoElement is ConstructorElement) {
      element = infoElement;
    } else if (infoElement is ClassElement) {
      element = infoElement.unnamedConstructor;
    }
    if (element != null && info.hasTypeParameters) {
      return new ConstructorMember(element, classType);
    }
    return element;
  }
}

/**
 * Local function element representing the initializer for a variable that has
 * been resynthesized from a summary.  The actual element won't be constructed
 * until it is requested.  But properties [context] and [enclosingElement] can
 * be used without creating the actual element.
 */
class _DeferredInitializerElement extends FunctionElementHandle {
  /**
   * The variable element containing this element.
   */
  @override
  final VariableElement enclosingElement;

  _DeferredInitializerElement(this.enclosingElement) : super(null, null);

  @override
  FunctionElement get actualElement => enclosingElement.initializer;

  @override
  AnalysisContext get context => enclosingElement.context;

  @override
  ElementLocation get location => actualElement.location;
}

/// Specialization of [LibraryResynthesizer] for resynthesis from linked
/// summaries.
class _LibraryResynthesizer extends LibraryResynthesizerMixin {
  /**
   * The [SummaryResynthesizer] which is being used to obtain summaries.
   */
  final SummaryResynthesizer summaryResynthesizer;

  /**
   * Linked summary of the library to be resynthesized.
   */
  final LinkedLibrary linkedLibrary;

  /**
   * Unlinked compilation units constituting the library to be resynthesized.
   */
  final List<UnlinkedUnit> unlinkedUnits;

  /**
   * [Source] object for the library to be resynthesized.
   */
  final Source librarySource;

  /**
   * The URI of [librarySource].
   */
  Uri libraryUri;

  /**
   * The URI of [librarySource].
   */
  String libraryUriStr;

  /**
   * Indicates whether [librarySource] is the `dart:core` library.
   */
  bool isCoreLibrary;

  /**
   * The resynthesized library.
   */
  LibraryElementImpl library;

  /**
   * Map of compilation unit elements that have been resynthesized so far.  The
   * key is the URI of the compilation unit.
   */
  final Map<String, CompilationUnitElementImpl> resynthesizedUnits =
      <String, CompilationUnitElementImpl>{};

  _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
      this.unlinkedUnits, this.librarySource) {
    libraryUri = librarySource.uri;
    libraryUriStr = libraryUri.toString();
    isCoreLibrary = libraryUriStr == 'dart:core';
  }

  @override
  List<LinkedExportName> get linkedExportNames => linkedLibrary.exportNames;

  /**
   * Resynthesize a [NamespaceCombinator].
   */
  NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
    if (serializedCombinator.shows.isNotEmpty) {
      return new ShowElementCombinatorImpl.forSerialized(serializedCombinator);
    } else {
      return new HideElementCombinatorImpl.forSerialized(serializedCombinator);
    }
  }

  @override
  ElementHandle buildExportName(LinkedExportName exportName) {
    String name = exportName.name;
    if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
        !name.endsWith('=')) {
      name += '?';
    }
    ElementLocationImpl location = new ElementLocationImpl.con3(
        getReferencedLocationComponents(
            exportName.dependency, exportName.unit, name));
    switch (exportName.kind) {
      case ReferenceKind.classOrEnum:
        return new ClassElementHandle(summaryResynthesizer, location);
      case ReferenceKind.typedef:
        return new FunctionTypeAliasElementHandle(
            summaryResynthesizer, location);
      case ReferenceKind.genericFunctionTypedef:
        return new GenericTypeAliasElementHandle(
            summaryResynthesizer, location);
      case ReferenceKind.topLevelFunction:
        return new FunctionElementHandle(summaryResynthesizer, location);
      case ReferenceKind.topLevelPropertyAccessor:
        return new PropertyAccessorElementHandle(
            summaryResynthesizer, location);
      case ReferenceKind.constructor:
      case ReferenceKind.function:
      case ReferenceKind.propertyAccessor:
      case ReferenceKind.method:
      case ReferenceKind.prefix:
      case ReferenceKind.unresolved:
      case ReferenceKind.variable:
        // Should never happen.  Exported names never refer to import prefixes,
        // and they always refer to defined top-level entities.
        throw new StateError('Unexpected export name kind: ${exportName.kind}');
    }
    return null;
  }

  /**
   * Main entry point.  Resynthesize the [LibraryElement] and return it.
   */
  LibraryElement buildLibrary() {
    // Create LibraryElementImpl.
    bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
    library = new LibraryElementImpl.forSerialized(
        summaryResynthesizer.context,
        unlinkedUnits[0].libraryName,
        hasName ? unlinkedUnits[0].libraryNameOffset : -1,
        unlinkedUnits[0].libraryNameLength,
        new _LibraryResynthesizerContext(this),
        unlinkedUnits[0]);
    // Create the defining unit.
    _UnitResynthesizer definingUnitResynthesizer =
        createUnitResynthesizer(0, librarySource, null);
    CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit;
    library.definingCompilationUnit = definingUnit;
    definingUnit.source = librarySource;
    definingUnit.librarySource = librarySource;
    // Create parts.
    List<_UnitResynthesizer> partResynthesizers = <_UnitResynthesizer>[];
    UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
    assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
        linkedLibrary.units.length);
    for (int i = 1; i < linkedLibrary.units.length; i++) {
      _UnitResynthesizer partResynthesizer = buildPart(
          definingUnitResynthesizer,
          unlinkedDefiningUnit.publicNamespace.parts[i - 1],
          unlinkedDefiningUnit.parts[i - 1],
          i);
      if (partResynthesizer != null) {
        partResynthesizers.add(partResynthesizer);
      }
    }
    library.parts = partResynthesizers.map((r) => r.unit).toList();
    // Populate units.
    rememberUriToUnit(definingUnitResynthesizer);
    for (_UnitResynthesizer partResynthesizer in partResynthesizers) {
      rememberUriToUnit(partResynthesizer);
    }
    // Create the synthetic element for `loadLibrary`.
    // Until the client received dart:core and dart:async, we cannot do this,
    // because the TypeProvider is not fully initialized. So, it is up to the
    // Dart SDK client to initialize TypeProvider and finish the dart:core and
    // dart:async libraries creation.
    if (library.name != 'dart.core' && library.name != 'dart.async') {
      library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
    }
    // Done.
    return library;
  }

  /**
   * Create a [_UnitResynthesizer] that will resynthesize the part with the
   * given [uri]. Return `null` if the [uri] is invalid.
   */
  _UnitResynthesizer buildPart(_UnitResynthesizer definingUnitResynthesizer,
      String uri, UnlinkedPart partDecl, int unitNum) {
    Source unitSource =
        summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
    _UnitResynthesizer partResynthesizer =
        createUnitResynthesizer(unitNum, unitSource, partDecl);
    CompilationUnitElementImpl partUnit = partResynthesizer.unit;
    partUnit.uriOffset = partDecl.uriOffset;
    partUnit.uriEnd = partDecl.uriEnd;
    partUnit.source = unitSource;
    partUnit.librarySource = librarySource;
    partUnit.uri = uri;
    return partResynthesizer;
  }

  /**
   * Set up data structures for deserializing a compilation unit.
   */
  _UnitResynthesizer createUnitResynthesizer(
      int unitNum, Source unitSource, UnlinkedPart unlinkedPart) {
    LinkedUnit linkedUnit = linkedLibrary.units[unitNum];
    UnlinkedUnit unlinkedUnit = unlinkedUnits[unitNum];
    return new _UnitResynthesizer(
        this, unlinkedUnit, linkedUnit, unitSource, unlinkedPart);
  }

  /**
   * Build the components of an [ElementLocationImpl] for the entity in the
   * given [unit] of the dependency located at [dependencyIndex], and having
   * the given [name].
   */
  List<String> getReferencedLocationComponents(
      int dependencyIndex, int unit, String name) {
    if (dependencyIndex == 0) {
      String partUri;
      if (unit != 0) {
        String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
        partUri = _resolveRelativeUri(uri);
      } else {
        partUri = libraryUriStr;
      }
      return <String>[libraryUriStr, partUri, name];
    }

    LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
    String referencedLibraryUri = _resolveRelativeUri(dependency.uri);

    String partUri;
    if (unit != 0) {
      String uri = dependency.parts[unit - 1];
      partUri = _resolveRelativeUri(uri);
    } else {
      partUri = referencedLibraryUri;
    }
    return <String>[referencedLibraryUri, partUri, name];
  }

  /**
   * Remember the absolute URI to the corresponding unit mapping.
   */
  void rememberUriToUnit(_UnitResynthesizer unitResynthesizer) {
    CompilationUnitElementImpl unit = unitResynthesizer.unit;
    Source source = unit.source;
    if (source != null) {
      String absoluteUri = source.uri.toString();
      resynthesizedUnits[absoluteUri] = unit;
    }
  }

  /**
   * Resolve the [relativeUriStr] against [libraryUri] using Dart rules.
   */
  String _resolveRelativeUri(String relativeUriStr) {
    Uri relativeUri = Uri.parse(relativeUriStr);
    Uri resolvedUri = resolveRelativeUri(libraryUri, relativeUri);
    return resolvedUri.toString();
  }
}

/**
 * Implementation of [LibraryResynthesizerContext] for [_LibraryResynthesizer].
 */
class _LibraryResynthesizerContext extends LibraryResynthesizerContextMixin
    implements LibraryResynthesizerContext {
  final _LibraryResynthesizer resynthesizer;

  _LibraryResynthesizerContext(this.resynthesizer);

  @override
  LinkedLibrary get linkedLibrary => resynthesizer.linkedLibrary;

  @override
  LibraryElement buildExportedLibrary(String relativeUri) {
    return _getLibraryByRelativeUri(relativeUri);
  }

  @override
  LibraryElement buildImportedLibrary(int dependency) {
    String depUri = resynthesizer.linkedLibrary.dependencies[dependency].uri;
    return _getLibraryByRelativeUri(depUri);
  }

  @override
  FunctionElement findEntryPoint() {
    LibraryElementImpl library = resynthesizer.library;
    Element entryPoint =
        library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
    if (entryPoint is FunctionElement) {
      return entryPoint;
    }
    return null;
  }

  @override
  void patchTopLevelAccessors() {
    LibraryElementImpl library = resynthesizer.library;
    BuildLibraryElementUtils.patchTopLevelAccessors(library);
  }

  LibraryElementHandle _getLibraryByRelativeUri(String depUri) {
    Source source = resynthesizer.summaryResynthesizer.sourceFactory
        .resolveUri(resynthesizer.librarySource, depUri);
    if (source == null) {
      return null;
    }
    String absoluteUri = source.uri.toString();
    return new LibraryElementHandle(resynthesizer.summaryResynthesizer,
        new ElementLocationImpl.con3(<String>[absoluteUri]));
  }
}

/// Specialization of [ReferenceInfo] for resynthesis from linked summaries.
class _ReferenceInfo extends ReferenceInfo {
  /**
   * The [_LibraryResynthesizer] which is being used to obtain summaries.
   */
  final _LibraryResynthesizer libraryResynthesizer;

  @override
  final _ReferenceInfo enclosing;

  @override
  final String name;

  /**
   * Is `true` if the [element] can be used as a declared type.
   */
  final bool isDeclarableType;

  @override
  final Element element;

  /**
   * If this reference refers to a non-generic type, the type it refers to.
   * Otherwise `null`.
   */
  DartType _type;

  /**
   * The number of type parameters accepted by the entity referred to by this
   * reference, or zero if it doesn't accept any type parameters.
   */
  final int numTypeParameters;

  bool _isBeingInstantiatedToBounds = false;
  bool _isRecursiveWhileInstantiateToBounds = false;

  /**
   * Create a new [_ReferenceInfo] object referring to an element called [name]
   * via the element handle [element], and having [numTypeParameters] type
   * parameters.
   *
   * For the special types `dynamic` and `void`, [specialType] should point to
   * the type itself.  Otherwise, pass `null` and the type will be computed
   * when appropriate.
   */
  _ReferenceInfo(
      this.libraryResynthesizer,
      this.enclosing,
      this.name,
      this.isDeclarableType,
      this.element,
      DartType specialType,
      this.numTypeParameters) {
    if (specialType != null) {
      _type = specialType;
    }
  }

  @override
  bool get hasTypeParameters => numTypeParameters != 0;

  @override
  DartType get type {
    if (_type == null) {
      _type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
    }
    return _type;
  }

  List<DartType> get _dynamicTypeArguments =>
      new List<DartType>.filled(numTypeParameters, DynamicTypeImpl.instance);

  /**
   * Build a [DartType] corresponding to the result of applying some type
   * arguments to the entity referred to by this [_ReferenceInfo].  The type
   * arguments are retrieved by calling [getTypeArgument].
   *
   * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
   * created which refers to a function type implicitly defined by one of the
   * element's parameters.  [implicitFunctionTypeIndices] is interpreted as in
   * [EntityRef.implicitFunctionTypeIndices].
   *
   * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
   * is returned.
   */
  DartType buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
      DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
    DartType result =
        (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
            ? type
            : _buildType(instantiateToBoundsAllowed, numTypeArguments,
                getTypeArgument, implicitFunctionTypeIndices);
    if (result == null) {
      return DynamicTypeImpl.instance;
    }
    return result;
  }

  /**
   * If this reference refers to a type, build a [DartType].  Otherwise return
   * `null`.  If [numTypeArguments] is the same as the [numTypeParameters],
   * the type is instantiated with type arguments returned by [getTypeArgument],
   * otherwise it is instantiated with type parameter bounds (if strong mode),
   * or with `dynamic` type arguments.
   *
   * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
   * created which refers to a function type implicitly defined by one of the
   * element's parameters.  [implicitFunctionTypeIndices] is interpreted as in
   * [EntityRef.implicitFunctionTypeIndices].
   */
  DartType _buildType(bool instantiateToBoundsAllowed, int numTypeArguments,
      DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
    ElementHandle element = this.element; // To allow type promotion
    if (element is ClassElementHandle) {
      List<DartType> typeArguments = null;
      // If type arguments are specified, use them.
      // Otherwise, delay until they are requested.
      if (numTypeParameters == 0) {
        return element.type;
      } else if (numTypeArguments == numTypeParameters) {
        typeArguments = _buildTypeArguments(numTypeArguments, getTypeArgument);
      }
      InterfaceTypeImpl type =
          new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
        if (typeArguments == null) {
          if (!_isBeingInstantiatedToBounds) {
            _isBeingInstantiatedToBounds = true;
            _isRecursiveWhileInstantiateToBounds = false;
            try {
              InterfaceType instantiatedToBounds = libraryResynthesizer
                  .summaryResynthesizer.context.typeSystem
                  .instantiateToBounds(element.type) as InterfaceType;
              if (_isRecursiveWhileInstantiateToBounds) {
                throw new RecursiveInstantiateToBounds();
              }
              return instantiatedToBounds.typeArguments;
            } finally {
              _isBeingInstantiatedToBounds = false;
            }
          } else {
            _isRecursiveWhileInstantiateToBounds = true;
            typeArguments = _dynamicTypeArguments;
          }
        }
        return typeArguments;
      });
      // Mark the type as having implicit type arguments, so that we don't
      // attempt to request them during constant expression resynthesizing.
      if (typeArguments == null) {
        _typesWithImplicitTypeArguments[type] = true;
      }
      // Done.
      return type;
    } else if (element is GenericTypeAliasElementHandle) {
      GenericTypeAliasElementImpl actualElement = element.actualElement;
      List<DartType> typeArguments;
      if (numTypeArguments == numTypeParameters) {
        typeArguments = _buildTypeArguments(numTypeArguments, getTypeArgument);
      } else if (instantiateToBoundsAllowed) {
        if (!_isBeingInstantiatedToBounds) {
          _isBeingInstantiatedToBounds = true;
          _isRecursiveWhileInstantiateToBounds = false;
          try {
            typeArguments = libraryResynthesizer
                .summaryResynthesizer.context.typeSystem
                .instantiateTypeFormalsToBounds(element.typeParameters);
            if (_isRecursiveWhileInstantiateToBounds) {
              typeArguments = _dynamicTypeArguments;
            }
          } finally {
            _isBeingInstantiatedToBounds = false;
          }
        } else {
          _isRecursiveWhileInstantiateToBounds = true;
          typeArguments = _dynamicTypeArguments;
        }
      } else {
        typeArguments = _dynamicTypeArguments;
      }
      return actualElement.typeAfterSubstitution(typeArguments);
    } else if (element is FunctionTypedElement) {
      if (element is FunctionTypeAliasElementHandle) {
        List<DartType> typeArguments;
        if (numTypeArguments == numTypeParameters) {
          typeArguments =
              _buildTypeArguments(numTypeArguments, getTypeArgument);
        } else if (instantiateToBoundsAllowed) {
          if (!_isBeingInstantiatedToBounds) {
            _isBeingInstantiatedToBounds = true;
            _isRecursiveWhileInstantiateToBounds = false;
            try {
              FunctionType instantiatedToBounds = libraryResynthesizer
                  .summaryResynthesizer.context.typeSystem
                  .instantiateToBounds(element.type) as FunctionType;
              if (!_isRecursiveWhileInstantiateToBounds) {
                typeArguments = instantiatedToBounds.typeArguments;
              } else {
                typeArguments = _dynamicTypeArguments;
              }
            } finally {
              _isBeingInstantiatedToBounds = false;
            }
          } else {
            _isRecursiveWhileInstantiateToBounds = true;
            typeArguments = _dynamicTypeArguments;
          }
        } else {
          typeArguments = _dynamicTypeArguments;
        }
        return new FunctionTypeImpl.forTypedef(element,
            typeArguments: typeArguments);
      } else {
        FunctionTypedElementComputer computer;
        if (implicitFunctionTypeIndices.isNotEmpty) {
          numTypeArguments = numTypeParameters;
          computer = () {
            FunctionTypedElement element = this.element;
            for (int index in implicitFunctionTypeIndices) {
              element = element.parameters[index].type.element;
            }
            return element;
          };
        } else {
          // For a type that refers to a generic executable, the type arguments are
          // not supposed to include the arguments to the executable itself.
          if (element is MethodElementHandle && !element.isStatic) {
            numTypeArguments = enclosing?.numTypeParameters ?? 0;
          } else {
            numTypeArguments = 0;
          }
          computer = () => this.element as FunctionTypedElement;
        }
        // TODO(paulberry): Is it a bug that we have to pass `false` for
        // isInstantiated?
        return new DeferredFunctionTypeImpl(computer, null,
            _buildTypeArguments(numTypeArguments, getTypeArgument), false);
      }
    } else {
      return null;
    }
  }

  /**
   * Build a list of type arguments having length [numTypeArguments] where each
   * type argument is obtained by calling [getTypeArgument].
   */
  List<DartType> _buildTypeArguments(
      int numTypeArguments, DartType getTypeArgument(int i)) {
    List<DartType> typeArguments = const <DartType>[];
    if (numTypeArguments != 0) {
      typeArguments = new List<DartType>(numTypeArguments);
      for (int i = 0; i < numTypeArguments; i++) {
        typeArguments[i] = getTypeArgument(i);
      }
    }
    return typeArguments;
  }
}

/// Specialization of [UnitResynthesizer] for resynthesis from linked summaries.
class _UnitResynthesizer extends UnitResynthesizer with UnitResynthesizerMixin {
  /**
   * The [_LibraryResynthesizer] which is being used to obtain summaries.
   */
  final _LibraryResynthesizer libraryResynthesizer;

  /**
   * The [UnlinkedUnit] from which elements are currently being resynthesized.
   */
  final UnlinkedUnit unlinkedUnit;

  /**
   * The [LinkedUnit] from which elements are currently being resynthesized.
   */
  final LinkedUnit linkedUnit;

  /**
   * The [CompilationUnitElementImpl] for the compilation unit currently being
   * resynthesized.
   */
  CompilationUnitElementImpl unit;

  /**
   * Map from slot id to the corresponding [EntityRef] object for linked types
   * (i.e. propagated and inferred types).
   */
  final Map<int, EntityRef> linkedTypeMap = <int, EntityRef>{};

  /**
   * Set of slot ids corresponding to const constructors that are part of
   * cycles.
   */
  Set<int> constCycles;

  /**
   * Set of slot ids corresponding to parameters that inherit `@covariant`
   * behavior.
   */
  Set<int> parametersInheritingCovariant;

  int numLinkedReferences;
  int numUnlinkedReferences;

  /**
   * List of [_ReferenceInfo] objects describing the references in the current
   * compilation unit.  This list is works as a lazily filled cache, use
   * [getReferenceInfo] to get the [_ReferenceInfo] for an index.
   */
  List<_ReferenceInfo> referenceInfos;

  /**
   * The [ResynthesizerContext] for this resynthesize session.
   */
  ResynthesizerContext _resynthesizerContext;

  _UnitResynthesizer(this.libraryResynthesizer, this.unlinkedUnit,
      this.linkedUnit, Source unitSource, UnlinkedPart unlinkedPart) {
    _resynthesizerContext = new SummaryResynthesizerContext(this);
    unit = new CompilationUnitElementImpl.forSerialized(
        libraryResynthesizer.library,
        _resynthesizerContext,
        unlinkedUnit,
        unlinkedPart);

    {
      List<int> lineStarts = unlinkedUnit.lineStarts;
      if (lineStarts.isEmpty) {
        lineStarts = const <int>[0];
      }
      unit.lineInfo = new LineInfo(lineStarts);
    }

    for (EntityRef t in linkedUnit.types) {
      linkedTypeMap[t.slot] = t;
    }
    constCycles = linkedUnit.constCycles.toSet();
    parametersInheritingCovariant =
        linkedUnit.parametersInheritingCovariant.toSet();
    numLinkedReferences = linkedUnit.references.length;
    numUnlinkedReferences = unlinkedUnit.references.length;
    referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
  }

  @override
  LibraryElement get library => libraryResynthesizer.library;

  SummaryResynthesizer get summaryResynthesizer =>
      libraryResynthesizer.summaryResynthesizer;

  @override
  TypeProvider get typeProvider => summaryResynthesizer.typeProvider;

  @override
  TypeSystem get typeSystem => summaryResynthesizer.typeSystem;

  /**
   * Build [ElementAnnotationImpl] for the given [UnlinkedExpr].
   */
  ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
    ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
    Expression constExpr = _buildConstExpression(context, uc);
    if (constExpr == null) {
      // Invalid constant expression.
    } else if (constExpr is Identifier) {
      var element = constExpr.staticElement;
      ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST);
      if (element is PropertyAccessorElement && arguments == null) {
        elementAnnotation.element = element;
        elementAnnotation.annotationAst = AstTestFactory.annotation(constExpr);
      } else if (element is ConstructorElement && arguments != null) {
        elementAnnotation.element = element;
        elementAnnotation.annotationAst =
            AstTestFactory.annotation2(constExpr, null, arguments);
      } else {
        elementAnnotation.annotationAst = AstTestFactory.annotation(
            AstTestFactory.identifier3(r'#invalidConst'));
      }
    } else if (constExpr is InstanceCreationExpression) {
      elementAnnotation.element = constExpr.staticElement;
      Identifier typeName = constExpr.constructorName.type.name;
      SimpleIdentifier constructorName = constExpr.constructorName.name;
      if (typeName is SimpleIdentifier && constructorName != null) {
        // E.g. `@cls.ctor()`.  Since `cls.ctor` would have been parsed as
        // a PrefixedIdentifier, we need to resynthesize it as one.
        typeName = AstTestFactory.identifier(typeName, constructorName);
        constructorName = null;
      }
      elementAnnotation.annotationAst = AstTestFactory.annotation2(
          typeName, constructorName, constExpr.argumentList)
        ..element = constExpr.staticElement;
    } else if (constExpr is PropertyAccess) {
      var target = constExpr.target as Identifier;
      var propertyName = constExpr.propertyName;
      var propertyElement = propertyName.staticElement;
      ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST);
      if (propertyElement is PropertyAccessorElement && arguments == null) {
        elementAnnotation.element = propertyElement;
        elementAnnotation.annotationAst =
            AstTestFactory.annotation2(target, propertyName, null)
              ..element = propertyElement;
      } else if (propertyElement is ConstructorElement && arguments != null) {
        elementAnnotation.element = propertyElement;
        elementAnnotation.annotationAst =
            AstTestFactory.annotation2(target, propertyName, arguments)
              ..element = propertyElement;
      } else {
        elementAnnotation.annotationAst = AstTestFactory.annotation(
            AstTestFactory.identifier3(r'#invalidConst'));
      }
    } else {
      throw new StateError(
          'Unexpected annotation type: ${constExpr.runtimeType}');
    }
    return elementAnnotation;
  }

  /**
   * Build an implicit getter for the given [property] and bind it to the
   * [property] and to its enclosing element.
   */
  PropertyAccessorElementImpl buildImplicitGetter(
      PropertyInducingElementImpl property) {
    PropertyAccessorElementImpl_ImplicitGetter getter =
        new PropertyAccessorElementImpl_ImplicitGetter(property);
    getter.enclosingElement = property.enclosingElement;
    return getter;
  }

  /**
   * Build an implicit setter for the given [property] and bind it to the
   * [property] and to its enclosing element.
   */
  PropertyAccessorElementImpl buildImplicitSetter(
      PropertyInducingElementImpl property) {
    PropertyAccessorElementImpl_ImplicitSetter setter =
        new PropertyAccessorElementImpl_ImplicitSetter(property);
    setter.enclosingElement = property.enclosingElement;
    return setter;
  }

  /**
   * Build the appropriate [DartType] object corresponding to a slot id in the
   * [LinkedUnit.types] table.
   */
  DartType buildLinkedType(ElementImpl context, int slot) {
    if (slot == 0) {
      // A slot id of 0 means there is no [DartType] object to build.
      return null;
    }
    EntityRef type = linkedTypeMap[slot];
    if (type == null) {
      // A missing entry in [LinkedUnit.types] means there is no [DartType]
      // stored in this slot.
      return null;
    }
    return buildType(context, type);
  }

  @override
  DartType buildType(ElementImpl context, EntityRef type,
      {bool defaultVoid: false,
      bool instantiateToBoundsAllowed: true,
      bool declaredType: false}) {
    if (type == null) {
      if (defaultVoid) {
        return VoidTypeImpl.instance;
      } else {
        return DynamicTypeImpl.instance;
      }
    }
    if (type.refinedSlot != 0) {
      var refinedType = linkedTypeMap[type.refinedSlot];
      if (refinedType != null) {
        type = refinedType;
      }
    }
    if (type.paramReference != 0) {
      return context.typeParameterContext
          .getTypeParameterType(type.paramReference);
    } else if (type.entityKind == EntityRefKind.genericFunctionType) {
      GenericFunctionTypeElement element =
          new GenericFunctionTypeElementImpl.forSerialized(context, type);
      return element.type;
    } else if (type.syntheticReturnType != null) {
      FunctionElementImpl element =
          new FunctionElementImpl_forLUB(context, type);
      return element.type;
    } else {
      DartType getTypeArgument(int i) {
        if (i < type.typeArguments.length) {
          return buildType(context, type.typeArguments[i],
              declaredType: declaredType);
        } else {
          return DynamicTypeImpl.instance;
        }
      }

      _ReferenceInfo referenceInfo = getReferenceInfo(type.reference);
      if (declaredType && !referenceInfo.isDeclarableType) {
        return DynamicTypeImpl.instance;
      }

      return referenceInfo.buildType(
          instantiateToBoundsAllowed,
          type.typeArguments.length,
          getTypeArgument,
          type.implicitFunctionTypeIndices);
    }
  }

  @override
  DartType buildTypeForClassInfo(covariant _ReferenceInfo info,
          int numTypeArguments, DartType getTypeArgument(int i)) =>
      info.buildType(true, numTypeArguments, getTypeArgument, const <int>[]);

  UnitExplicitTopLevelAccessors buildUnitExplicitTopLevelAccessors() {
    Map<String, TopLevelVariableElementImpl> implicitVariables =
        new HashMap<String, TopLevelVariableElementImpl>();
    UnitExplicitTopLevelAccessors accessorsData =
        new UnitExplicitTopLevelAccessors();
    for (UnlinkedExecutable unlinkedExecutable in unlinkedUnit.executables) {
      UnlinkedExecutableKind kind = unlinkedExecutable.kind;
      if (kind == UnlinkedExecutableKind.getter ||
          kind == UnlinkedExecutableKind.setter) {
        // name
        String name = unlinkedExecutable.name;
        if (kind == UnlinkedExecutableKind.setter) {
          assert(name.endsWith('='));
          name = name.substring(0, name.length - 1);
        }
        // create
        PropertyAccessorElementImpl accessor =
            new PropertyAccessorElementImpl.forSerialized(
                unlinkedExecutable, unit);
        accessorsData.accessors.add(accessor);
        // implicit variable
        TopLevelVariableElementImpl variable = implicitVariables[name];
        if (variable == null) {
          variable = new TopLevelVariableElementImpl(name, -1);
          variable.enclosingElement = unit;
          implicitVariables[name] = variable;
          accessorsData.implicitVariables.add(variable);
          variable.isSynthetic = true;
          variable.isFinal = kind == UnlinkedExecutableKind.getter;
        } else {
          variable.isFinal = false;
        }
        accessor.variable = variable;
        // link
        if (kind == UnlinkedExecutableKind.getter) {
          variable.getter = accessor;
        } else {
          variable.setter = accessor;
        }
      }
    }
    return accessorsData;
  }

  UnitExplicitTopLevelVariables buildUnitExplicitTopLevelVariables() {
    List<UnlinkedVariable> unlinkedVariables = unlinkedUnit.variables;
    int numberOfVariables = unlinkedVariables.length;
    UnitExplicitTopLevelVariables variablesData =
        new UnitExplicitTopLevelVariables(numberOfVariables);
    for (int i = 0; i < numberOfVariables; i++) {
      UnlinkedVariable unlinkedVariable = unlinkedVariables[i];
      TopLevelVariableElementImpl element;
      if (unlinkedVariable.initializer?.bodyExpr != null &&
          unlinkedVariable.isConst) {
        element = new ConstTopLevelVariableElementImpl.forSerialized(
            unlinkedVariable, unit);
      } else {
        element = new TopLevelVariableElementImpl.forSerialized(
            unlinkedVariable, unit);
      }
      variablesData.variables[i] = element;
      // implicit accessors
      variablesData.implicitAccessors.add(buildImplicitGetter(element));
      if (!(element.isConst || element.isFinal)) {
        variablesData.implicitAccessors.add(buildImplicitSetter(element));
      }
    }
    return variablesData;
  }

  @override
  bool doesTypeHaveImplicitArguments(ParameterizedType type) =>
      _typesWithImplicitTypeArguments[type] != null;

  @override
  _ReferenceInfo getReferenceInfo(int index) {
    _ReferenceInfo result = referenceInfos[index];
    if (result == null) {
      LinkedReference linkedReference = linkedUnit.references[index];
      String name;
      int containingReference;
      if (index < numUnlinkedReferences) {
        name = unlinkedUnit.references[index].name;
        containingReference = unlinkedUnit.references[index].prefixReference;
      } else {
        name = linkedUnit.references[index].name;
        containingReference = linkedUnit.references[index].containingReference;
      }
      _ReferenceInfo enclosingInfo = containingReference != 0
          ? getReferenceInfo(containingReference)
          : null;
      Element element;
      DartType type;
      bool isDeclarableType = false;
      int numTypeParameters = linkedReference.numTypeParameters;
      if (linkedReference.kind == ReferenceKind.unresolved) {
        type = UndefinedTypeImpl.instance;
        element = null;
        isDeclarableType = true;
      } else if (name == 'dynamic') {
        type = DynamicTypeImpl.instance;
        element = type.element;
        isDeclarableType = true;
      } else if (name == 'void') {
        type = VoidTypeImpl.instance;
        element = type.element;
        isDeclarableType = true;
      } else if (name == '*bottom*') {
        type = BottomTypeImpl.instance;
        element = null;
        isDeclarableType = true;
      } else {
        List<String> locationComponents;
        if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
          String identifier = _getElementIdentifier(name, linkedReference.kind);
          locationComponents =
              enclosingInfo.element.location.components.toList();
          locationComponents.add(identifier);
        } else {
          String identifier = _getElementIdentifier(name, linkedReference.kind);
          locationComponents =
              libraryResynthesizer.getReferencedLocationComponents(
                  linkedReference.dependency, linkedReference.unit, identifier);
          if (linkedReference.kind == ReferenceKind.prefix) {
            locationComponents = <String>[
              locationComponents[0],
              locationComponents[2]
            ];
          }
        }
        ElementLocation location =
            new ElementLocationImpl.con3(locationComponents);
        if (enclosingInfo != null) {
          numTypeParameters += enclosingInfo.numTypeParameters;
        }
        switch (linkedReference.kind) {
          case ReferenceKind.classOrEnum:
            element = new ClassElementHandle(summaryResynthesizer, location);
            isDeclarableType = true;
            break;
          case ReferenceKind.constructor:
            assert(location.components.length == 4);
            element =
                new ConstructorElementHandle(summaryResynthesizer, location);
            break;
          case ReferenceKind.method:
            assert(location.components.length == 4);
            element = new MethodElementHandle(summaryResynthesizer, location);
            break;
          case ReferenceKind.propertyAccessor:
            assert(location.components.length == 4);
            element = new PropertyAccessorElementHandle(
                summaryResynthesizer, location);
            break;
          case ReferenceKind.topLevelFunction:
            assert(location.components.length == 3);
            element = new FunctionElementHandle(summaryResynthesizer, location);
            break;
          case ReferenceKind.topLevelPropertyAccessor:
            element = new PropertyAccessorElementHandle(
                summaryResynthesizer, location);
            break;
          case ReferenceKind.typedef:
          case ReferenceKind.genericFunctionTypedef:
            element = new GenericTypeAliasElementHandle(
                summaryResynthesizer, location);
            isDeclarableType = true;
            break;
          case ReferenceKind.function:
            Element enclosingElement = enclosingInfo.element;
            if (enclosingElement is VariableElement) {
              element = new _DeferredInitializerElement(enclosingElement);
            } else {
              throw new StateError('Unexpected element enclosing function:'
                  ' ${enclosingElement.runtimeType}');
            }
            break;
          case ReferenceKind.prefix:
            element = new PrefixElementHandle(summaryResynthesizer, location);
            break;
          case ReferenceKind.variable:
          case ReferenceKind.unresolved:
            break;
        }
      }
      result = new _ReferenceInfo(libraryResynthesizer, enclosingInfo, name,
          isDeclarableType, element, type, numTypeParameters);
      referenceInfos[index] = result;
    }
    return result;
  }

  /**
   * Return the error reported during type inference for the given [slot],
   * or `null` if there were no error.
   */
  TopLevelInferenceError getTypeInferenceError(int slot) {
    if (slot == 0) {
      return null;
    }
    for (TopLevelInferenceError error in linkedUnit.topLevelInferenceErrors) {
      if (error.slot == slot) {
        return error;
      }
    }
    return null;
  }

  Expression _buildConstExpression(ElementImpl context, UnlinkedExpr uc) {
    return new ExprBuilder(this, context, uc).build();
  }

  /**
   * Return the [ConstructorElement] corresponding to the given [entry].
   */
  ConstructorElement _getConstructorForEntry(
      ElementImpl context, EntityRef entry) {
    _ReferenceInfo info = getReferenceInfo(entry.reference);
    DartType type =
        createConstructorDefiningType(context, info, entry.typeArguments);
    if (type is InterfaceType) {
      return getConstructorForInfo(type, info);
    }
    return null;
  }

  /**
   * If the given [kind] is a top-level or class member property accessor, and
   * the given [name] does not end with `=`, i.e. does not denote a setter,
   * return the getter identifier by appending `?`.
   */
  static String _getElementIdentifier(String name, ReferenceKind kind) {
    if (kind == ReferenceKind.topLevelPropertyAccessor ||
        kind == ReferenceKind.propertyAccessor) {
      if (!name.endsWith('=')) {
        return name + '?';
      }
    }
    return name;
  }
}
