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

import 'dart:collection';

import 'package:analyzer/dart/analysis/session.dart';
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, AnalysisSession session,
      this.sourceFactory, bool _)
      : super(context, session) {
    _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];
          if (libraryMap == null) {
            throw new StateError(
                'Unable to find library `$libraryUri` in a summary file.');
          }
        }
        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, session, '', -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({});
        _resynthesizedUnits[uri] = {uri: unitElement};
        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
  bool isSimplyBounded(int notSimplyBoundedSlot) {
    return !unitResynthesizer.linkedUnit.notSimplyBounded
        .contains(notSimplyBoundedSlot);
  }

  @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.
mixin 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;

  @override
  AnalysisSession get session => enclosingElement.session;
}

/// 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,
        summaryResynthesizer.session,
        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 GenericTypeAliasElementImpl.typeAfterSubstitution(
          actualElement, 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 element.instantiate(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) {
      ArgumentList arguments = constExpr.getProperty(ExprBuilder.ARGUMENT_LIST);
      elementAnnotation.element = constExpr.staticElement;
      elementAnnotation.annotationAst =
          AstTestFactory.annotation2(constExpr, null, arguments);
    } else if (constExpr is InstanceCreationExpression) {
      var element = constExpr.staticElement;
      elementAnnotation.element = element;
      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);
      elementAnnotation.element = propertyElement;
      elementAnnotation.annotationAst =
          AstTestFactory.annotation2(target, propertyName, arguments)
            ..element = propertyElement;
    } 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;
  }
}
