// 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/ast/token.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/constant.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_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';

/**
 * Implementation of [ElementResynthesizer] used when resynthesizing an element
 * model from summaries.
 */
abstract class SummaryResynthesizer extends ElementResynthesizer {
  /**
   * The parent [SummaryResynthesizer] which is asked to resynthesize elements
   * and get summaries before this resynthesizer attempts to do this.
   * Can be `null`.
   */
  final SummaryResynthesizer parent;

  /**
   * 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 [TypeProvider] used to obtain core types (such as Object, int, List,
   * and dynamic) during resynthesis.
   */
  final TypeProvider typeProvider;

  /**
   * Indicates whether the summary should be resynthesized assuming strong mode
   * semantics.
   */
  final bool strongMode;

  /**
   * 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, CompilationUnitElement>> _resynthesizedUnits =
      <String, Map<String, CompilationUnitElement>>{};

  /**
   * 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(this.parent, AnalysisContext context, this.typeProvider,
      this.sourceFactory, this.strongMode)
      : super(context);

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

  /**
   * Perform delayed finalization of the `dart:core` and `dart:async` libraries.
   */
  void finalizeCoreAsyncLibraries() {
    (_resynthesizedLibraries['dart:core'] as LibraryElementImpl)
        .createLoadLibraryFunction(typeProvider);
    (_resynthesizedLibraries['dart:async'] as LibraryElementImpl)
        .createLoadLibraryFunction(typeProvider);
  }

  @override
  Element getElement(ElementLocation location) {
    List<String> components = location.components;
    String libraryUri = components[0];
    // Ask the parent resynthesizer.
    if (parent != null && parent._hasLibrarySummary(libraryUri)) {
      return parent.getElement(location);
    }
    // Resynthesize locally.
    if (components.length == 1) {
      return getLibraryElement(libraryUri);
    } else if (components.length == 2) {
      Map<String, CompilationUnitElement> libraryMap =
          _resynthesizedUnits[libraryUri];
      if (libraryMap == null) {
        getLibraryElement(libraryUri);
        libraryMap = _resynthesizedUnits[libraryUri];
        assert(libraryMap != null);
      }
      String unitUri = components[1];
      CompilationUnitElement element = libraryMap[unitUri];
      if (element == null) {
        throw new Exception('Unit element not found in summary: $location');
      }
      return element;
    } else if (components.length == 3 || components.length == 4) {
      Map<String, Map<String, Element>> libraryMap =
          _resynthesizedElements[libraryUri];
      if (libraryMap == null) {
        getLibraryElement(libraryUri);
        libraryMap = _resynthesizedElements[libraryUri];
        assert(libraryMap != null);
      }
      Map<String, Element> compilationUnitElements = libraryMap[components[1]];
      Element element;
      if (compilationUnitElements != null) {
        element = compilationUnitElements[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) {
    if (parent != null && parent._hasLibrarySummary(uri)) {
      return parent.getLibraryElement(uri);
    }
    return _resynthesizedLibraries.putIfAbsent(uri, () {
      LinkedLibrary serializedLibrary = _getLinkedSummaryOrThrow(uri);
      List<UnlinkedUnit> serializedUnits = <UnlinkedUnit>[
        _getUnlinkedSummaryOrThrow(uri)
      ];
      Source librarySource = _getSource(uri);
      for (String part in serializedUnits[0].publicNamespace.parts) {
        Source partSource = sourceFactory.resolveUri(librarySource, part);
        String partAbsUri = partSource.uri.toString();
        serializedUnits.add(_getUnlinkedSummaryOrThrow(partAbsUri));
      }
      _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
          this, serializedLibrary, serializedUnits, librarySource);
      LibraryElement library = libraryResynthesizer.buildLibrary();
      _resynthesizedUnits[uri] = libraryResynthesizer.resynthesizedUnits;
      _resynthesizedElements[uri] = libraryResynthesizer.resynthesizedElements;
      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);

  /**
   * Return the [LinkedLibrary] for the given [uri] or throw [StateError] if it
   * could not be found.
   */
  LinkedLibrary _getLinkedSummaryOrThrow(String uri) {
    if (parent != null && parent._hasLibrarySummary(uri)) {
      return parent._getLinkedSummaryOrThrow(uri);
    }
    LinkedLibrary summary = getLinkedSummary(uri);
    if (summary != null) {
      return summary;
    }
    throw new StateError('Unable to find linked summary: $uri');
  }

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

  /**
   * Return the [UnlinkedUnit] for the given [uri] or throw [StateError] if it
   * could not be found.
   */
  UnlinkedUnit _getUnlinkedSummaryOrThrow(String uri) {
    if (parent != null && parent._hasLibrarySummary(uri)) {
      return parent._getUnlinkedSummaryOrThrow(uri);
    }
    UnlinkedUnit summary = getUnlinkedSummary(uri);
    if (summary != null) {
      return summary;
    }
    throw new StateError('Unable to find unlinked summary: $uri');
  }

  /**
   * Return `true` if this resynthesizer can provide summaries of the libraries
   * with the given [uri].
   */
  bool _hasLibrarySummary(String uri) {
    if (parent != null && parent._hasLibrarySummary(uri)) {
      return true;
    }
    return hasLibrarySummary(uri);
  }
}

/**
 * Builder of [Expression]s from [UnlinkedConst]s.
 */
class _ConstExprBuilder {
  final _UnitResynthesizer resynthesizer;
  final UnlinkedConst uc;

  int intPtr = 0;
  int doublePtr = 0;
  int stringPtr = 0;
  int refPtr = 0;
  final List<Expression> stack = <Expression>[];

  _ConstExprBuilder(this.resynthesizer, this.uc);

  Expression build() {
    if (!uc.isValidConst) {
      return AstFactory.identifier3(r'$$invalidConstExpr$$');
    }
    for (UnlinkedConstOperation operation in uc.operations) {
      switch (operation) {
        case UnlinkedConstOperation.pushNull:
          _push(AstFactory.nullLiteral());
          break;
        // bool
        case UnlinkedConstOperation.pushFalse:
          _push(AstFactory.booleanLiteral(false));
          break;
        case UnlinkedConstOperation.pushTrue:
          _push(AstFactory.booleanLiteral(true));
          break;
        // literals
        case UnlinkedConstOperation.pushInt:
          int value = uc.ints[intPtr++];
          _push(AstFactory.integer(value));
          break;
        case UnlinkedConstOperation.pushLongInt:
          int value = 0;
          int count = uc.ints[intPtr++];
          for (int i = 0; i < count; i++) {
            int next = uc.ints[intPtr++];
            value = value << 32 | next;
          }
          _push(AstFactory.integer(value));
          break;
        case UnlinkedConstOperation.pushDouble:
          double value = uc.doubles[doublePtr++];
          _push(AstFactory.doubleLiteral(value));
          break;
        case UnlinkedConstOperation.makeSymbol:
          String component = uc.strings[stringPtr++];
          _push(AstFactory.symbolLiteral([component]));
          break;
        // String
        case UnlinkedConstOperation.pushString:
          String value = uc.strings[stringPtr++];
          _push(AstFactory.string2(value));
          break;
        case UnlinkedConstOperation.concatenate:
          int count = uc.ints[intPtr++];
          List<InterpolationElement> elements = <InterpolationElement>[];
          for (int i = 0; i < count; i++) {
            Expression expr = _pop();
            InterpolationElement element = _newInterpolationElement(expr);
            elements.insert(0, element);
          }
          _push(AstFactory.string(elements));
          break;
        // binary
        case UnlinkedConstOperation.equal:
          _pushBinary(TokenType.EQ_EQ);
          break;
        case UnlinkedConstOperation.notEqual:
          _pushBinary(TokenType.BANG_EQ);
          break;
        case UnlinkedConstOperation.and:
          _pushBinary(TokenType.AMPERSAND_AMPERSAND);
          break;
        case UnlinkedConstOperation.or:
          _pushBinary(TokenType.BAR_BAR);
          break;
        case UnlinkedConstOperation.bitXor:
          _pushBinary(TokenType.CARET);
          break;
        case UnlinkedConstOperation.bitAnd:
          _pushBinary(TokenType.AMPERSAND);
          break;
        case UnlinkedConstOperation.bitOr:
          _pushBinary(TokenType.BAR);
          break;
        case UnlinkedConstOperation.bitShiftLeft:
          _pushBinary(TokenType.LT_LT);
          break;
        case UnlinkedConstOperation.bitShiftRight:
          _pushBinary(TokenType.GT_GT);
          break;
        case UnlinkedConstOperation.add:
          _pushBinary(TokenType.PLUS);
          break;
        case UnlinkedConstOperation.subtract:
          _pushBinary(TokenType.MINUS);
          break;
        case UnlinkedConstOperation.multiply:
          _pushBinary(TokenType.STAR);
          break;
        case UnlinkedConstOperation.divide:
          _pushBinary(TokenType.SLASH);
          break;
        case UnlinkedConstOperation.floorDivide:
          _pushBinary(TokenType.TILDE_SLASH);
          break;
        case UnlinkedConstOperation.modulo:
          _pushBinary(TokenType.PERCENT);
          break;
        case UnlinkedConstOperation.greater:
          _pushBinary(TokenType.GT);
          break;
        case UnlinkedConstOperation.greaterEqual:
          _pushBinary(TokenType.GT_EQ);
          break;
        case UnlinkedConstOperation.less:
          _pushBinary(TokenType.LT);
          break;
        case UnlinkedConstOperation.lessEqual:
          _pushBinary(TokenType.LT_EQ);
          break;
        // prefix
        case UnlinkedConstOperation.complement:
          _pushPrefix(TokenType.TILDE);
          break;
        case UnlinkedConstOperation.negate:
          _pushPrefix(TokenType.MINUS);
          break;
        case UnlinkedConstOperation.not:
          _pushPrefix(TokenType.BANG);
          break;
        // conditional
        case UnlinkedConstOperation.conditional:
          Expression elseExpr = _pop();
          Expression thenExpr = _pop();
          Expression condition = _pop();
          _push(
              AstFactory.conditionalExpression(condition, thenExpr, elseExpr));
          break;
        // invokeMethodRef
        case UnlinkedConstOperation.invokeMethodRef:
          _pushInvokeMethodRef();
          break;
        // containers
        case UnlinkedConstOperation.makeUntypedList:
          _pushList(null);
          break;
        case UnlinkedConstOperation.makeTypedList:
          TypeName itemType = _newTypeName();
          _pushList(AstFactory.typeArgumentList(<TypeName>[itemType]));
          break;
        case UnlinkedConstOperation.makeUntypedMap:
          _pushMap(null);
          break;
        case UnlinkedConstOperation.makeTypedMap:
          TypeName keyType = _newTypeName();
          TypeName valueType = _newTypeName();
          _pushMap(AstFactory.typeArgumentList(<TypeName>[keyType, valueType]));
          break;
        case UnlinkedConstOperation.pushReference:
          _pushReference();
          break;
        case UnlinkedConstOperation.extractProperty:
          _pushExtractProperty();
          break;
        case UnlinkedConstOperation.invokeConstructor:
          _pushInstanceCreation();
          break;
        case UnlinkedConstOperation.pushConstructorParameter:
          String name = uc.strings[stringPtr++];
          SimpleIdentifier identifier = AstFactory.identifier3(name);
          identifier.staticElement = resynthesizer.currentConstructor.parameters
              .firstWhere((parameter) => parameter.name == name,
                  orElse: () => throw new StateError(
                      'Unable to resolve constructor parameter: $name'));
          _push(identifier);
          break;
        case UnlinkedConstOperation.assignToRef:
        case UnlinkedConstOperation.assignToProperty:
        case UnlinkedConstOperation.assignToIndex:
        case UnlinkedConstOperation.extractIndex:
        case UnlinkedConstOperation.invokeMethod:
        case UnlinkedConstOperation.cascadeSectionBegin:
        case UnlinkedConstOperation.cascadeSectionEnd:
        case UnlinkedConstOperation.typeCast:
        case UnlinkedConstOperation.typeCheck:
        case UnlinkedConstOperation.throwException:
        case UnlinkedConstOperation.pushLocalFunctionReference:
          throw new UnimplementedError(
              'Unexpected $operation in a constant expression.');
      }
    }
    return stack.single;
  }

  List<Expression> _buildArguments() {
    List<Expression> arguments;
    {
      int numNamedArgs = uc.ints[intPtr++];
      int numPositionalArgs = uc.ints[intPtr++];
      int numArgs = numNamedArgs + numPositionalArgs;
      arguments = _removeTopItems(numArgs);
      // add names to the named arguments
      for (int i = 0; i < numNamedArgs; i++) {
        String name = uc.strings[stringPtr++];
        int index = numPositionalArgs + i;
        arguments[index] = AstFactory.namedExpression2(name, arguments[index]);
      }
    }
    return arguments;
  }

  /**
   * Build the identifier sequence (a single or prefixed identifier, or a
   * property access) corresponding to the given reference [info].
   */
  Expression _buildIdentifierSequence(_ReferenceInfo info) {
    Expression enclosing;
    if (info.enclosing != null) {
      enclosing = _buildIdentifierSequence(info.enclosing);
    }
    Element element = info.element;
    if (element == null && info.name == 'length') {
      element = _getStringLengthElement();
    }
    if (enclosing == null) {
      return AstFactory.identifier3(info.name)..staticElement = element;
    }
    if (enclosing is SimpleIdentifier) {
      SimpleIdentifier identifier = AstFactory.identifier3(info.name)
        ..staticElement = element;
      return AstFactory.identifier(enclosing, identifier);
    }
    SimpleIdentifier property = AstFactory.identifier3(info.name)
      ..staticElement = element;
    return AstFactory.propertyAccess(enclosing, property);
  }

  TypeName _buildTypeAst(DartType type) {
    List<TypeName> argumentNodes;
    if (type is ParameterizedType) {
      if (!resynthesizer.libraryResynthesizer.typesWithImplicitTypeArguments
          .contains(type)) {
        List<DartType> typeArguments = type.typeArguments;
        argumentNodes = typeArguments.every((a) => a.isDynamic)
            ? null
            : typeArguments.map(_buildTypeAst).toList();
      }
    }
    TypeName node = AstFactory.typeName4(type.name, argumentNodes);
    node.type = type;
    (node.name as SimpleIdentifier).staticElement = type.element;
    return node;
  }

  PropertyAccessorElement _getStringLengthElement() =>
      resynthesizer.typeProvider.stringType.getGetter('length');

  InterpolationElement _newInterpolationElement(Expression expr) {
    if (expr is SimpleStringLiteral) {
      return new InterpolationString(expr.literal, expr.value);
    } else {
      return new InterpolationExpression(
          TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION),
          expr,
          TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
    }
  }

  /**
   * Convert the next reference to the [DartType] and return the AST
   * corresponding to this type.
   */
  TypeName _newTypeName() {
    EntityRef typeRef = uc.references[refPtr++];
    DartType type = resynthesizer.buildType(
        typeRef, resynthesizer._currentTypeParameterizedElement);
    return _buildTypeAst(type);
  }

  Expression _pop() => stack.removeLast();

  void _push(Expression expr) {
    stack.add(expr);
  }

  void _pushBinary(TokenType operator) {
    Expression right = _pop();
    Expression left = _pop();
    _push(AstFactory.binaryExpression(left, operator, right));
  }

  void _pushExtractProperty() {
    Expression target = _pop();
    String name = uc.strings[stringPtr++];
    SimpleIdentifier propertyNode = AstFactory.identifier3(name);
    // Only String.length property access can be potentially resolved.
    if (name == 'length') {
      propertyNode.staticElement = _getStringLengthElement();
    }
    _push(AstFactory.propertyAccess(target, propertyNode));
  }

  void _pushInstanceCreation() {
    EntityRef ref = uc.references[refPtr++];
    _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    // prepare ConstructorElement
    TypeName typeNode;
    String constructorName;
    ConstructorElement constructorElement;
    if (info.element != null) {
      if (info.element is ConstructorElement) {
        constructorName = info.name;
      } else if (info.element is ClassElement) {
        constructorName = null;
      } else {
        throw new StateError('Unsupported element for invokeConstructor '
            '${info.element?.runtimeType}');
      }
      InterfaceType definingType =
          resynthesizer._createConstructorDefiningType(info, ref.typeArguments);
      constructorElement =
          resynthesizer._createConstructorElement(definingType, info);
      typeNode = _buildTypeAst(definingType);
    } else {
      if (info.enclosing != null) {
        if (info.enclosing.enclosing != null) {
          PrefixedIdentifier typeName = AstFactory.identifier5(
              info.enclosing.enclosing.name, info.enclosing.name);
          typeName.prefix.staticElement = info.enclosing.enclosing.element;
          typeName.identifier.staticElement = info.enclosing.element;
          typeName.identifier.staticType = info.enclosing.type;
          typeNode = AstFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else if (info.enclosing.element != null) {
          SimpleIdentifier typeName =
              AstFactory.identifier3(info.enclosing.name);
          typeName.staticElement = info.enclosing.element;
          typeName.staticType = info.enclosing.type;
          typeNode = AstFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else {
          typeNode = AstFactory.typeName3(
              AstFactory.identifier5(info.enclosing.name, info.name));
          constructorName = null;
        }
      } else {
        typeNode = AstFactory.typeName4(info.name);
      }
    }
    // prepare arguments
    List<Expression> arguments = _buildArguments();
    // create ConstructorName
    ConstructorName constructorNode;
    if (constructorName != null) {
      constructorNode = AstFactory.constructorName(typeNode, constructorName);
      constructorNode.name.staticElement = constructorElement;
    } else {
      constructorNode = AstFactory.constructorName(typeNode, null);
    }
    constructorNode.staticElement = constructorElement;
    // create InstanceCreationExpression
    InstanceCreationExpression instanceCreation = AstFactory
        .instanceCreationExpression(Keyword.CONST, constructorNode, arguments);
    instanceCreation.staticElement = constructorElement;
    _push(instanceCreation);
  }

  void _pushInvokeMethodRef() {
    List<Expression> arguments = _buildArguments();
    EntityRef ref = uc.references[refPtr++];
    _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    Expression node = _buildIdentifierSequence(info);
    if (node is SimpleIdentifier) {
      _push(new MethodInvocation(
          null,
          TokenFactory.tokenFromType(TokenType.PERIOD),
          node,
          null,
          AstFactory.argumentList(arguments)));
    } else {
      throw new UnimplementedError('For ${node?.runtimeType}: $node');
    }
  }

  void _pushList(TypeArgumentList typeArguments) {
    int count = uc.ints[intPtr++];
    List<Expression> elements = <Expression>[];
    for (int i = 0; i < count; i++) {
      elements.insert(0, _pop());
    }
    _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements));
  }

  void _pushMap(TypeArgumentList typeArguments) {
    int count = uc.ints[intPtr++];
    List<MapLiteralEntry> entries = <MapLiteralEntry>[];
    for (int i = 0; i < count; i++) {
      Expression value = _pop();
      Expression key = _pop();
      entries.insert(0, AstFactory.mapLiteralEntry2(key, value));
    }
    _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries));
  }

  void _pushPrefix(TokenType operator) {
    Expression operand = _pop();
    _push(AstFactory.prefixExpression(operator, operand));
  }

  void _pushReference() {
    EntityRef ref = uc.references[refPtr++];
    _ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    Expression node = _buildIdentifierSequence(info);
    _push(node);
  }

  List<Expression> _removeTopItems(int count) {
    int start = stack.length - count;
    int end = stack.length;
    List<Expression> items = stack.getRange(start, end).toList();
    stack.removeRange(start, end);
    return items;
  }
}

/**
 * Temporary [TypeParameterizedElementMixin] implementation.
 *
 * TODO(scheglov) remove after moving resynthesize logic to Impl.
 */
class _CurrentTypeParameterizedElement
    implements TypeParameterizedElementMixin {
  final _UnitResynthesizer unitResynthesizer;

  _CurrentTypeParameterizedElement(this.unitResynthesizer);

  @override
  TypeParameterType getTypeParameterType(int index) {
    return unitResynthesizer.getTypeParameterFromScope(index);
  }

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/**
 * A class element that has been resynthesized from a summary.  The actual
 * element won't be constructed until it is requested.  But properties
 * [context],  [displayName], [enclosingElement] and [name] can be used without
 * creating the actual element.  This allows to put these elements into
 * namespaces without creating actual elements until they are really needed.
 */
class _DeferredClassElement extends ClassElementHandle {
  final _UnitResynthesizer unitResynthesizer;
  final CompilationUnitElement unitElement;
  final UnlinkedClass serializedClass;

  ClassElementImpl _actualElement;

  /**
   * We don't resynthesize executables of classes until they are requested.
   * TODO(scheglov) Check whether we need separate flags for separate kinds.
   */
  bool _executablesResynthesized = false;

  @override
  final String name;

  factory _DeferredClassElement(_UnitResynthesizer unitResynthesizer,
      CompilationUnitElement unitElement, UnlinkedClass serializedClass) {
    String name = serializedClass.name;
    List<String> components =
        unitResynthesizer.unit.location.components.toList();
    components.add(name);
    ElementLocationImpl location = new ElementLocationImpl.con3(components);
    return new _DeferredClassElement._(
        unitResynthesizer, unitElement, serializedClass, name, location);
  }

  _DeferredClassElement._(this.unitResynthesizer, this.unitElement,
      this.serializedClass, this.name, ElementLocation location)
      : super(null, location);

  @override
  List<PropertyAccessorElement> get accessors {
    _ensureExecutables();
    return actualElement.accessors;
  }

  @override
  ClassElementImpl get actualElement {
    if (_actualElement == null) {
      _actualElement = unitResynthesizer.buildClassImpl(serializedClass, this);
      _actualElement.enclosingElement = unitElement;
    }
    return _actualElement;
  }

  @override
  List<ConstructorElement> get constructors {
    _ensureExecutables();
    return actualElement.constructors;
  }

  @override
  AnalysisContext get context => unitElement.context;

  @override
  String get displayName => name;

  @override
  CompilationUnitElement get enclosingElement {
    return unitElement;
  }

  @override
  List<FieldElement> get fields {
    _ensureExecutables();
    return actualElement.fields;
  }

  @override
  List<MethodElement> get methods {
    _ensureExecutables();
    return actualElement.methods;
  }

  @override
  void ensureAccessorsReady() {
    _ensureExecutables();
  }

  @override
  void ensureActualElementComplete() {
    _ensureExecutables();
  }

  @override
  void ensureConstructorsReady() {
    _ensureExecutables();
  }

  @override
  void ensureMethodsReady() {
    _ensureExecutables();
  }

  /**
   * Ensure that we have [actualElement], and it has all executables.
   */
  void _ensureExecutables() {
    if (!_executablesResynthesized) {
      _executablesResynthesized = true;
      unitResynthesizer.buildClassExecutables(actualElement, serializedClass);
    }
  }
}

/**
 * The constructor element that has been resynthesized from a summary.  The
 * actual element won't be constructed until it is requested.  But properties
 * [displayName], [enclosingElement] and [name] can be used without creating
 * the actual element.
 */
class _DeferredConstructorElement extends ConstructorElementHandle {
  /**
   * The type defining this constructor element.  If [_isMember] is `false`,
   * then the type parameters of [_definingType] are not guaranteed to be
   * valid.
   */
  final InterfaceType _definingType;

  /**
   * The constructor name.
   */
  final String name;

  factory _DeferredConstructorElement(InterfaceType definingType, String name) {
    List<String> components = definingType.element.location.components.toList();
    components.add(name);
    ElementLocationImpl location = new ElementLocationImpl.con3(components);
    return new _DeferredConstructorElement._(definingType, name, location);
  }

  _DeferredConstructorElement._(
      this._definingType, this.name, ElementLocation location)
      : super(null, location);

  @override
  ConstructorElement get actualElement =>
      enclosingElement.getNamedConstructor(name);

  @override
  AnalysisContext get context => _definingType.element.context;

  @override
  String get displayName => name;

  @override
  ClassElement get enclosingElement {
    return _definingType.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;
}

/**
 * Local function element 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 _DeferredLocalFunctionElement extends FunctionElementHandle {
  /**
   * The executable element containing this element.
   */
  @override
  final ExecutableElement enclosingElement;

  /**
   * The index of this function within [ExecutableElement.functions].
   */
  final int _localIndex;

  _DeferredLocalFunctionElement(this.enclosingElement, this._localIndex)
      : super(null, null);

  @override
  FunctionElement get actualElement {
    ExecutableElement enclosingElement = this.enclosingElement;
    if (enclosingElement is PropertyAccessorElement &&
        enclosingElement.isSynthetic) {
      return enclosingElement.variable.initializer;
    } else {
      return enclosingElement.functions[_localIndex];
    }
  }

  @override
  AnalysisContext get context => enclosingElement.context;

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

/**
 * Local variable element 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 _DeferredLocalVariableElement extends LocalVariableElementHandle {
  /**
   * The executable element containing this element.
   */
  @override
  final ExecutableElement enclosingElement;

  /**
   * The index of this variable within [ExecutableElement.localVariables].
   */
  final int _localIndex;

  _DeferredLocalVariableElement(this.enclosingElement, this._localIndex)
      : super(null, null);

  @override
  LocalVariableElement get actualElement =>
      enclosingElement.localVariables[_localIndex];

  @override
  AnalysisContext get context => enclosingElement.context;

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

/**
 * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the
 * elements in a single library from that library's summary.
 */
class _LibraryResynthesizer {
  /**
   * 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].
   */
  String libraryUri;

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

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

  /**
   * Classes which should have their supertype set to "object" once
   * resynthesis is complete.  Only used if [isCoreLibrary] is `true`.
   */
  List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[];

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

  /**
   * Map of top level elements that have been resynthesized so far.  The first
   * key is the URI of the compilation unit; the second is the name of the top
   * level element.
   */
  final Map<String, Map<String, Element>> resynthesizedElements =
      <String, Map<String, Element>>{};

  /**
   * Types with implicit type arguments, which are the same as type parameter
   * bounds (in strong mode), or `dynamic` (in spec mode).
   */
  final Set<DartType> typesWithImplicitTypeArguments =
      new Set<DartType>.identity();

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

  /**
   * Resynthesize a [NamespaceCombinator].
   */
  NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
    if (serializedCombinator.shows.isNotEmpty) {
      ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl();
      // Note: we call toList() so that we don't retain a reference to the
      // deserialized data structure.
      combinator.shownNames = serializedCombinator.shows.toList();
      combinator.offset = serializedCombinator.offset;
      combinator.end = serializedCombinator.end;
      return combinator;
    } else {
      HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
      // Note: we call toList() so that we don't retain a reference to the
      // deserialized data structure.
      combinator.hiddenNames = serializedCombinator.hides.toList();
      return combinator;
    }
  }

  /**
   * Resynthesize an [ExportElement],
   */
  ExportElement buildExport(
      _UnitResynthesizer definingUnitResynthesizer,
      UnlinkedExportPublic serializedExportPublic,
      UnlinkedExportNonPublic serializedExportNonPublic) {
    ExportElementImpl exportElement =
        new ExportElementImpl(serializedExportNonPublic.offset);
    String exportedLibraryUri = summaryResynthesizer.sourceFactory
        .resolveUri(librarySource, serializedExportPublic.uri)
        .uri
        .toString();
    exportElement.exportedLibrary = new LibraryElementHandle(
        summaryResynthesizer,
        new ElementLocationImpl.con3(<String>[exportedLibraryUri]));
    exportElement.uri = serializedExportPublic.uri;
    exportElement.combinators =
        serializedExportPublic.combinators.map(buildCombinator).toList();
    exportElement.uriOffset = serializedExportNonPublic.uriOffset;
    exportElement.uriEnd = serializedExportNonPublic.uriEnd;
    definingUnitResynthesizer.buildAnnotations(
        exportElement, serializedExportNonPublic.annotations);
    return exportElement;
  }

  /**
   * Build an [ElementHandle] referring to the entity referred to by the given
   * [exportName].
   */
  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.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}');
    }
  }

  /**
   * Build the export namespace for the library by aggregating together its
   * [publicNamespace] and [exportNames].
   */
  Namespace buildExportNamespace(
      Namespace publicNamespace, List<LinkedExportName> exportNames) {
    HashMap<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) {
      definedNames.putIfAbsent(
          exportName.name, () => buildExportName(exportName));
    }
    return new Namespace(definedNames);
  }

  /**
   * Resynthesize an [ImportElement].
   */
  ImportElement buildImport(
      _UnitResynthesizer definingUnitResynthesizer,
      UnlinkedImport serializedImport,
      int dependency,
      LibraryElement libraryBeingResynthesized) {
    bool isSynthetic = serializedImport.isImplicit;
    ImportElementImpl importElement =
        new ImportElementImpl(isSynthetic ? -1 : serializedImport.offset);
    if (dependency == 0) {
      importElement.importedLibrary = libraryBeingResynthesized;
    } else {
      String absoluteUri = summaryResynthesizer.sourceFactory
          .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
          .uri
          .toString();
      importElement.importedLibrary = new LibraryElementHandle(
          summaryResynthesizer,
          new ElementLocationImpl.con3(<String>[absoluteUri]));
    }
    if (isSynthetic) {
      importElement.synthetic = true;
    } else {
      importElement.uri = serializedImport.uri;
      importElement.uriOffset = serializedImport.uriOffset;
      importElement.uriEnd = serializedImport.uriEnd;
      importElement.deferred = serializedImport.isDeferred;
      definingUnitResynthesizer.buildAnnotations(
          importElement, serializedImport.annotations);
    }
    importElement.prefixOffset = serializedImport.prefixOffset;
    if (serializedImport.prefixReference != 0) {
      UnlinkedReference serializedPrefix =
          unlinkedUnits[0].references[serializedImport.prefixReference];
      importElement.prefix = new PrefixElementImpl(
          serializedPrefix.name, serializedImport.prefixOffset);
    }
    importElement.combinators =
        serializedImport.combinators.map(buildCombinator).toList();
    return importElement;
  }

  /**
   * Main entry point.  Resynthesize the [LibraryElement] and return it.
   */
  LibraryElement buildLibrary() {
    // Create LibraryElementImpl.
    bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
    library = new LibraryElementImpl(
        summaryResynthesizer.context,
        unlinkedUnits[0].libraryName,
        hasName ? unlinkedUnits[0].libraryNameOffset : -1,
        unlinkedUnits[0].libraryNameLength);
    // Create the defining unit.
    _UnitResynthesizer definingUnitResynthesizer =
        createUnitResynthesizer(0, librarySource, null);
    CompilationUnitElementImpl definingUnit = definingUnitResynthesizer.unit;
    definingUnitResynthesizer.buildDocumentation(
        library, unlinkedUnits[0].libraryDocumentationComment);
    definingUnitResynthesizer.buildAnnotations(
        library, unlinkedUnits[0].libraryAnnotations);
    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);
      partResynthesizers.add(partResynthesizer);
    }
    library.parts = partResynthesizers.map((r) => r.unit).toList();
    // Create imports.
    List<ImportElement> imports = <ImportElement>[];
    for (int i = 0; i < unlinkedDefiningUnit.imports.length; i++) {
      imports.add(buildImport(
          definingUnitResynthesizer,
          unlinkedDefiningUnit.imports[i],
          linkedLibrary.importDependencies[i],
          library));
    }
    library.imports = imports;
    // Create exports.
    List<ExportElement> exports = <ExportElement>[];
    assert(unlinkedDefiningUnit.exports.length ==
        unlinkedDefiningUnit.publicNamespace.exports.length);
    for (int i = 0; i < unlinkedDefiningUnit.exports.length; i++) {
      exports.add(buildExport(
          definingUnitResynthesizer,
          unlinkedDefiningUnit.publicNamespace.exports[i],
          unlinkedDefiningUnit.exports[i]));
    }
    library.exports = exports;
    // Populate units.
    populateUnit(definingUnitResynthesizer);
    for (_UnitResynthesizer partResynthesizer in partResynthesizers) {
      populateUnit(partResynthesizer);
    }
    BuildLibraryElementUtils.patchTopLevelAccessors(library);
    // Update delayed Object class references.
    if (isCoreLibrary) {
      ClassElement objectElement = library.getType('Object');
      assert(objectElement != null);
      for (ClassElementImpl classElement in delayedObjectSubclasses) {
        classElement.supertype = objectElement.type;
      }
    }
    // Compute namespaces.
    library.publicNamespace =
        new NamespaceBuilder().createPublicNamespaceForLibrary(library);
    library.exportNamespace = buildExportNamespace(
        library.publicNamespace, linkedLibrary.exportNames);
    // Find the entry point.  Note: we can't use element.isEntryPoint because
    // that will trigger resynthesis of exported libraries.
    Element entryPoint =
        library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
    if (entryPoint is FunctionElement) {
      library.entryPoint = entryPoint;
    }
    // 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, but do not populate, the [CompilationUnitElement] for a part other
   * than the defining compilation unit.
   */
  _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 referencedLibraryUri = libraryUri;
      String partUri;
      if (unit != 0) {
        String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
        Source partSource =
            summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
        partUri = partSource.uri.toString();
      } else {
        partUri = referencedLibraryUri;
      }
      return <String>[referencedLibraryUri, partUri, name];
    }
    LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
    Source referencedLibrarySource = summaryResynthesizer.sourceFactory
        .resolveUri(librarySource, dependency.uri);
    String referencedLibraryUri = referencedLibrarySource.uri.toString();
    String partUri;
    if (unit != 0) {
      String uri = dependency.parts[unit - 1];
      Source partSource =
          summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
      partUri = partSource.uri.toString();
    } else {
      partUri = referencedLibraryUri;
    }
    return <String>[referencedLibraryUri, partUri, name];
  }

  /**
   * Populate a [CompilationUnitElement] by deserializing all the elements
   * contained in it.
   */
  void populateUnit(_UnitResynthesizer unitResynthesized) {
    // TODO(scheglov)
    unitResynthesized.populateUnit();
    String absoluteUri = unitResynthesized.unit.source.uri.toString();
    resynthesizedUnits[absoluteUri] = unitResynthesized.unit;
    resynthesizedElements[absoluteUri] = unitResynthesized.elementMap;
  }
}

/**
 * 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).
 */
class _ReferenceInfo {
  /**
   * The [_LibraryResynthesizer] which is being used to obtain summaries.
   */
  final _LibraryResynthesizer libraryResynthesizer;

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

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

  /**
   * 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).
   */
  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;

  /**
   * 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.element, DartType specialType, this.numTypeParameters) {
    if (specialType != null) {
      type = specialType;
    } else {
      type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
    }
  }

  /**
   * 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) {
      // TODO(paulberry): figure out how to handle this case (which should
      // only occur in the event of erroneous code).
      throw new UnimplementedError();
    }
    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 in 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) {
        typeArguments = const <DartType>[];
      } else if (numTypeArguments == numTypeParameters) {
        typeArguments = new List<DartType>(numTypeParameters);
        for (int i = 0; i < numTypeParameters; i++) {
          typeArguments[i] = getTypeArgument(i);
        }
      }
      InterfaceTypeImpl type =
          new InterfaceTypeImpl.elementWithNameAndArgs(element, name, () {
        if (typeArguments == null) {
          typeArguments = element.typeParameters.map((typeParameter) {
            DartType bound = typeParameter.bound;
            return libraryResynthesizer.summaryResynthesizer.strongMode &&
                instantiateToBoundsAllowed &&
                bound != null ? bound : DynamicTypeImpl.instance;
          }).toList();
        }
        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) {
        libraryResynthesizer.typesWithImplicitTypeArguments.add(type);
      }
      // Done.
      return type;
    } else if (element is FunctionTypedElement) {
      int numTypeArguments;
      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 if (element is FunctionTypeAliasElementHandle) {
        return new FunctionTypeImpl.elementWithNameAndArgs(
            element,
            name,
            _buildTypeArguments(numTypeParameters, getTypeArgument),
            numTypeParameters != 0);
      } else {
        // For a type that refers to a generic executable, the type arguments are
        // not supposed to include the arguments to the executable itself.
        numTypeArguments = enclosing == null ? 0 : enclosing.numTypeParameters;
        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 = <DartType>[];
      for (int i = 0; i < numTypeArguments; i++) {
        typeArguments.add(getTypeArgument(i));
      }
    }
    return typeArguments;
  }
}

class _ResynthesizerContext implements ResynthesizerContext {
  final _UnitResynthesizer _unitResynthesizer;

  _ResynthesizerContext(this._unitResynthesizer);

  @override
  ElementAnnotationImpl buildAnnotation(UnlinkedConst uc) {
    return _unitResynthesizer.buildAnnotation(uc);
  }

  @override
  Expression buildExpression(UnlinkedConst uc) {
    return _unitResynthesizer._buildConstExpression(uc);
  }

  @override
  DartType resolveTypeRef(
      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
      {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
    return _unitResynthesizer.buildType(type, typeParameterContext,
        defaultVoid: defaultVoid,
        instantiateToBoundsAllowed: instantiateToBoundsAllowed);
  }
}

/**
 * An instance of [_UnitResynthesizer] is responsible for resynthesizing the
 * elements in a single unit from that unit's summary.
 */
class _UnitResynthesizer {
  /**
   * 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;

  /**
   * [ElementHolder] into which resynthesized elements should be placed.  This
   * object is recreated afresh for each unit in the library, and is used to
   * populate the [CompilationUnitElement].
   */
  final ElementHolder unitHolder = new ElementHolder();

  /**
   * Map of top-level elements that have been resynthesized so far.  The key is
   * the name of the top level element.
   */
  Map<String, Element> elementMap = <String, Element>{};

  /**
   * 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;

  /**
   * The [ConstructorElementImpl] for the constructor currently being
   * resynthesized.
   */
  ConstructorElementImpl currentConstructor;

  /**
   * Type parameters for the generic class, typedef, or executable currently
   * being resynthesized, if any.  This is a list of lists; if multiple
   * entities with type parameters are nested (e.g. a generic executable inside
   * a generic class), then the zeroth element of [currentTypeParameters]
   * contains the type parameters for the outermost nested entity, and further
   * elements contain the type parameters for entities that are more deeply
   * nested.  If we are not currently resynthesizing a class, typedef, or
   * executable, then this is an empty list.
   */
  final List<List<TypeParameterElement>> currentTypeParameters =
      <List<TypeParameterElement>>[];

  /**
   * If a class is currently being resynthesized, map from field name to the
   * corresponding field element.  This is used when resynthesizing
   * initializing formal parameters.
   */
  Map<String, FieldElementImpl> fields;

  /**
   * If a class is currently being resynthesized, map from constructor name to
   * the corresponding constructor element.  This is used when resynthesizing
   * constructor initializers.
   */
  Map<String, ConstructorElementImpl> constructors;

  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;

  /**
   * TODO(scheglov) clean up after moving resynthesize logic to Impl.
   */
  TypeParameterizedElementMixin _currentTypeParameterizedElement;

  _UnitResynthesizer(this.libraryResynthesizer, this.unlinkedUnit,
      this.linkedUnit, Source unitSource, UnlinkedPart unlinkedPart) {
    _resynthesizerContext = new _ResynthesizerContext(this);
    unit = new CompilationUnitElementImpl.forSerialized(
        libraryResynthesizer.library,
        _resynthesizerContext,
        unlinkedUnit,
        unlinkedPart,
        unitSource.shortName);
    for (EntityRef t in linkedUnit.types) {
      linkedTypeMap[t.slot] = t;
    }
    constCycles = linkedUnit.constCycles.toSet();
    numLinkedReferences = linkedUnit.references.length;
    numUnlinkedReferences = unlinkedUnit.references.length;
    referenceInfos = new List<_ReferenceInfo>(numLinkedReferences);
    _currentTypeParameterizedElement =
        new _CurrentTypeParameterizedElement(this);
  }

  SummaryResynthesizer get summaryResynthesizer =>
      libraryResynthesizer.summaryResynthesizer;

  TypeProvider get typeProvider => summaryResynthesizer.typeProvider;

  /**
   * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
   */
  ElementAnnotationImpl buildAnnotation(UnlinkedConst uc) {
    ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
    Expression constExpr = _buildConstExpression(uc);
    if (constExpr is Identifier) {
      elementAnnotation.element = constExpr.staticElement;
      elementAnnotation.annotationAst = AstFactory.annotation(constExpr);
    } 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 = AstFactory.identifier(typeName, constructorName);
        constructorName = null;
      }
      elementAnnotation.annotationAst = AstFactory.annotation2(
          typeName, constructorName, constExpr.argumentList);
    } else {
      throw new StateError(
          'Unexpected annotation type: ${constExpr.runtimeType}');
    }
    return elementAnnotation;
  }

  /**
   * Build the annotations for the given [element].
   */
  void buildAnnotations(
      ElementImpl element, List<UnlinkedConst> serializedAnnotations) {
    if (serializedAnnotations.isNotEmpty) {
      element.metadata = serializedAnnotations.map(buildAnnotation).toList();
    }
  }

  /**
   * Resynthesize a [ClassElement] and place it in [unitHolder].
   */
  void buildClass(UnlinkedClass serializedClass) {
    ClassElement classElement;
    if (libraryResynthesizer.isCoreLibrary &&
        serializedClass.supertype == null) {
      classElement = buildClassImpl(serializedClass, null);
      if (!serializedClass.hasNoSupertype) {
        libraryResynthesizer.delayedObjectSubclasses.add(classElement);
      }
    } else {
      classElement = new _DeferredClassElement(this, unit, serializedClass);
    }
    unitHolder.addType(classElement);
  }

  /**
   * Fill the given [ClassElementImpl] with executable elements and fields.
   */
  void buildClassExecutables(
      ClassElementImpl classElement, UnlinkedClass serializedClass) {
    currentTypeParameters.add(classElement.typeParameters);
    ElementHolder memberHolder = new ElementHolder();
    fields = <String, FieldElementImpl>{};
    for (UnlinkedVariable serializedVariable in serializedClass.fields) {
      buildVariable(serializedVariable, memberHolder);
    }
    bool constructorFound = false;
    constructors = <String, ConstructorElementImpl>{};
    for (UnlinkedExecutable serializedExecutable
        in serializedClass.executables) {
      switch (serializedExecutable.kind) {
        case UnlinkedExecutableKind.constructor:
          constructorFound = true;
          buildConstructor(serializedExecutable, classElement, memberHolder);
          break;
        case UnlinkedExecutableKind.functionOrMethod:
        case UnlinkedExecutableKind.getter:
        case UnlinkedExecutableKind.setter:
          if (serializedExecutable.isStatic) {
            currentTypeParameters.removeLast();
          }
          buildExecutable(serializedExecutable, classElement, memberHolder);
          if (serializedExecutable.isStatic) {
            currentTypeParameters.add(classElement.typeParameters);
          }
          break;
      }
    }
    if (!serializedClass.isMixinApplication) {
      if (!constructorFound) {
        // Synthesize implicit constructors.
        ConstructorElementImpl constructor = new ConstructorElementImpl('', -1);
        constructor.synthetic = true;
        constructor.returnType = classElement.type;
        constructor.type = new FunctionTypeImpl.elementWithNameAndArgs(
            constructor, null, getCurrentTypeArguments(), false);
        memberHolder.addConstructor(constructor);
      }
      classElement.constructors = memberHolder.constructors;
    }
    classElement.accessors = memberHolder.accessors;
    classElement.fields = memberHolder.fields;
    classElement.methods = memberHolder.methods;
    resolveConstructorInitializers(classElement);
    currentTypeParameters.removeLast();
    assert(currentTypeParameters.isEmpty);
  }

  /**
   * Resynthesize a [ClassElementImpl].  If [handle] is not `null`, then
   * executables are not resynthesized, and [InterfaceTypeImpl] is created
   * around the [handle], so that executables are resynthesized lazily.
   */
  ClassElementImpl buildClassImpl(
      UnlinkedClass serializedClass, ClassElementHandle handle) {
    ClassElementImpl classElement =
        new ClassElementImpl.forSerialized(serializedClass, unit);
    classElement.hasBeenInferred = summaryResynthesizer.strongMode;
    InterfaceTypeImpl correspondingType =
        new InterfaceTypeImpl(handle ?? classElement);
    if (serializedClass.supertype != null) {
      classElement.supertype =
          buildType(serializedClass.supertype, classElement);
    } else if (!libraryResynthesizer.isCoreLibrary) {
      classElement.supertype = typeProvider.objectType;
    }
    classElement.interfaces = serializedClass.interfaces
        .map((EntityRef t) => buildType(t, classElement))
        .toList();
    classElement.mixins = serializedClass.mixins
        .map((EntityRef t) => buildType(t, classElement))
        .toList();
    // TODO(scheglov) move to ClassElementImpl
    correspondingType.typeArguments = classElement.typeParameterTypes;
    classElement.type = correspondingType;
    assert(currentTypeParameters.isEmpty);
    // TODO(scheglov) Somehow Observatory shows too much time spent here
    // during DDC run on the large codebase. I would expect only Object here.
    if (handle == null) {
      buildClassExecutables(classElement, serializedClass);
    }
    fields = null;
    constructors = null;
    return classElement;
  }

  void buildCodeRange(ElementImpl element, CodeRange codeRange) {
    if (codeRange != null) {
      element.setCodeRange(codeRange.offset, codeRange.length);
    }
  }

  /**
   * Resynthesize a [NamespaceCombinator].
   */
  NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
    if (serializedCombinator.shows.isNotEmpty) {
      ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl();
      // Note: we call toList() so that we don't retain a reference to the
      // deserialized data structure.
      combinator.shownNames = serializedCombinator.shows.toList();
      combinator.offset = serializedCombinator.offset;
      combinator.end = serializedCombinator.end;
      return combinator;
    } else {
      HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
      // Note: we call toList() so that we don't retain a reference to the
      // deserialized data structure.
      combinator.hiddenNames = serializedCombinator.hides.toList();
      return combinator;
    }
  }

  /**
   * Resynthesize a [ConstructorElement] and place it in the given [holder].
   * [classType] is the type of the class for which this element is a
   * constructor.
   */
  void buildConstructor(UnlinkedExecutable serializedExecutable,
      ClassElementImpl classElement, ElementHolder holder) {
    assert(serializedExecutable.kind == UnlinkedExecutableKind.constructor);
    currentConstructor = new ConstructorElementImpl.forSerialized(
        serializedExecutable, classElement);
    currentConstructor.isCycleFree = serializedExecutable.isConst &&
        !constCycles.contains(serializedExecutable.constCycleSlot);
    if (serializedExecutable.name.isEmpty) {
      currentConstructor.nameEnd =
          serializedExecutable.nameOffset + classElement.name.length;
    } else {
      currentConstructor.nameEnd = serializedExecutable.nameEnd;
      currentConstructor.periodOffset = serializedExecutable.periodOffset;
    }
    constructors[serializedExecutable.name] = currentConstructor;
    currentConstructor.returnType = classElement.type;
    buildExecutableCommonParts(currentConstructor, serializedExecutable);
    currentConstructor.constantInitializers = serializedExecutable
        .constantInitializers
        .map(buildConstructorInitializer)
        .toList();
    if (serializedExecutable.isRedirectedConstructor) {
      if (serializedExecutable.isFactory) {
        EntityRef redirectedConstructor =
            serializedExecutable.redirectedConstructor;
        _ReferenceInfo info = getReferenceInfo(redirectedConstructor.reference);
        List<EntityRef> typeArguments = redirectedConstructor.typeArguments;
        currentConstructor.redirectedConstructor = _createConstructorElement(
            _createConstructorDefiningType(info, typeArguments), info);
      } else {
        List<String> locationComponents = unit.location.components.toList();
        locationComponents.add(classElement.name);
        locationComponents.add(serializedExecutable.redirectedConstructorName);
        currentConstructor.redirectedConstructor =
            new _DeferredConstructorElement._(
                classElement.type,
                serializedExecutable.redirectedConstructorName,
                new ElementLocationImpl.con3(locationComponents));
      }
    }
    holder.addConstructor(currentConstructor);
    currentConstructor = null;
  }

  /**
   * Resynthesize the [ConstructorInitializer] in context of
   * [currentConstructor], which is used to resolve constructor parameter names.
   */
  ConstructorInitializer buildConstructorInitializer(
      UnlinkedConstructorInitializer serialized) {
    UnlinkedConstructorInitializerKind kind = serialized.kind;
    String name = serialized.name;
    List<Expression> arguments = <Expression>[];
    {
      int numArguments = serialized.arguments.length;
      int numNames = serialized.argumentNames.length;
      for (int i = 0; i < numArguments; i++) {
        Expression expression = _buildConstExpression(serialized.arguments[i]);
        int nameIndex = numNames + i - numArguments;
        if (nameIndex >= 0) {
          expression = AstFactory.namedExpression2(
              serialized.argumentNames[nameIndex], expression);
        }
        arguments.add(expression);
      }
    }
    switch (kind) {
      case UnlinkedConstructorInitializerKind.field:
        return AstFactory.constructorFieldInitializer(
            false, name, _buildConstExpression(serialized.expression));
      case UnlinkedConstructorInitializerKind.superInvocation:
        return AstFactory.superConstructorInvocation2(
            name.isNotEmpty ? name : null, arguments);
      case UnlinkedConstructorInitializerKind.thisInvocation:
        return AstFactory.redirectingConstructorInvocation2(
            name.isNotEmpty ? name : null, arguments);
    }
  }

  /**
   * Build the documentation for the given [element].  Does nothing if
   * [serializedDocumentationComment] is `null`.
   */
  void buildDocumentation(ElementImpl element,
      UnlinkedDocumentationComment serializedDocumentationComment) {
    if (serializedDocumentationComment != null) {
      element.documentationComment = serializedDocumentationComment.text;
      element.setDocRange(serializedDocumentationComment.offset,
          serializedDocumentationComment.length);
    }
  }

  /**
   * Resynthesize the [ClassElement] corresponding to an enum, along with the
   * associated fields and implicit accessors.
   */
  void buildEnum(UnlinkedEnum serializedEnum) {
    assert(!libraryResynthesizer.isCoreLibrary);
    ClassElementImpl classElement =
        new ClassElementImpl(serializedEnum.name, serializedEnum.nameOffset);
    classElement.enum2 = true;
    InterfaceType enumType = new InterfaceTypeImpl(classElement);
    classElement.type = enumType;
    classElement.supertype = typeProvider.objectType;
    buildDocumentation(classElement, serializedEnum.documentationComment);
    buildAnnotations(classElement, serializedEnum.annotations);
    buildCodeRange(classElement, serializedEnum.codeRange);
    ElementHolder memberHolder = new ElementHolder();
    // Build the 'index' field.
    FieldElementImpl indexField = new FieldElementImpl('index', -1);
    indexField.final2 = true;
    indexField.synthetic = true;
    indexField.type = typeProvider.intType;
    memberHolder.addField(indexField);
    buildImplicitAccessors(indexField, memberHolder);
    // Build the 'values' field.
    FieldElementImpl valuesField = new ConstFieldElementImpl('values', -1);
    valuesField.synthetic = true;
    valuesField.const3 = true;
    valuesField.static = true;
    valuesField.type = typeProvider.listType.instantiate(<DartType>[enumType]);
    memberHolder.addField(valuesField);
    buildImplicitAccessors(valuesField, memberHolder);
    // Build fields for all enum constants.
    List<DartObjectImpl> constantValues = <DartObjectImpl>[];
    for (int i = 0; i < serializedEnum.values.length; i++) {
      UnlinkedEnumValue serializedEnumValue = serializedEnum.values[i];
      String fieldName = serializedEnumValue.name;
      ConstFieldElementImpl field =
          new ConstFieldElementImpl(fieldName, serializedEnumValue.nameOffset);
      buildDocumentation(field, serializedEnumValue.documentationComment);
      field.const3 = true;
      field.static = true;
      field.type = enumType;
      // Create a value for the constant.
      Map<String, DartObjectImpl> fieldMap = <String, DartObjectImpl>{
        fieldName: new DartObjectImpl(typeProvider.intType, new IntState(i))
      };
      DartObjectImpl value =
          new DartObjectImpl(enumType, new GenericState(fieldMap));
      constantValues.add(value);
      field.evaluationResult = new EvaluationResultImpl(value);
      // Add the field.
      memberHolder.addField(field);
      buildImplicitAccessors(field, memberHolder);
    }
    // Build the value of the 'values' field.
    valuesField.evaluationResult = new EvaluationResultImpl(
        new DartObjectImpl(valuesField.type, new ListState(constantValues)));
    // done
    classElement.fields = memberHolder.fields;
    classElement.accessors = memberHolder.accessors;
    classElement.constructors = <ConstructorElement>[];
    unitHolder.addEnum(classElement);
  }

  /**
   * Resynthesize an [ExecutableElement] and place it in the given [holder].
   */
  void buildExecutable(
      UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement,
      [ElementHolder holder]) {
    bool isTopLevel = holder == null;
    if (holder == null) {
      holder = unitHolder;
    }
    UnlinkedExecutableKind kind = serializedExecutable.kind;
    String name = serializedExecutable.name;
    if (kind == UnlinkedExecutableKind.setter) {
      assert(name.endsWith('='));
      name = name.substring(0, name.length - 1);
    }
    switch (kind) {
      case UnlinkedExecutableKind.functionOrMethod:
        if (isTopLevel) {
          FunctionElementImpl executableElement =
              new FunctionElementImpl.forSerialized(
                  serializedExecutable, enclosingElement);
          buildExecutableCommonParts(executableElement, serializedExecutable);
          holder.addFunction(executableElement);
        } else {
          MethodElementImpl executableElement =
              new MethodElementImpl.forSerialized(
                  serializedExecutable, enclosingElement);
          buildExecutableCommonParts(executableElement, serializedExecutable);
          holder.addMethod(executableElement);
        }
        break;
      case UnlinkedExecutableKind.getter:
      case UnlinkedExecutableKind.setter:
        PropertyAccessorElementImpl executableElement =
            new PropertyAccessorElementImpl.forSerialized(
                serializedExecutable, enclosingElement);
        buildExecutableCommonParts(executableElement, serializedExecutable);
        DartType type;
        if (kind == UnlinkedExecutableKind.getter) {
          type = executableElement.returnType;
        } else {
          type = executableElement.parameters[0].type;
        }
        holder.addAccessor(executableElement);
        PropertyInducingElementImpl implicitVariable;
        if (isTopLevel) {
          implicitVariable = buildImplicitTopLevelVariable(name, kind, holder);
        } else {
          FieldElementImpl field = buildImplicitField(name, type, kind, holder);
          field.static = serializedExecutable.isStatic;
          implicitVariable = field;
        }
        executableElement.variable = implicitVariable;
        if (kind == UnlinkedExecutableKind.getter) {
          implicitVariable.getter = executableElement;
        } else {
          implicitVariable.setter = executableElement;
        }
        break;
      default:
        // The only other executable type is a constructor, and that is handled
        // separately (in [buildConstructor].  So this code should be
        // unreachable.
        assert(false);
    }
  }

  /**
   * Handle the parts of an executable element that are common to constructors,
   * functions, methods, getters, and setters.
   */
  void buildExecutableCommonParts(ExecutableElementImpl executableElement,
      UnlinkedExecutable serializedExecutable) {
    executableElement.typeParameters =
        buildTypeParameters(serializedExecutable.typeParameters);
    executableElement.parameters = serializedExecutable.parameters
        .map((p) => buildParameter(p, executableElement))
        .toList();
    if (serializedExecutable.kind == UnlinkedExecutableKind.constructor) {
      // Caller handles setting the return type.
      assert(serializedExecutable.returnType == null);
    } else {
      bool isSetter =
          serializedExecutable.kind == UnlinkedExecutableKind.setter;
      executableElement.returnType = buildLinkedType(
              serializedExecutable.inferredReturnTypeSlot,
              _currentTypeParameterizedElement) ??
          buildType(
              serializedExecutable.returnType, _currentTypeParameterizedElement,
              defaultVoid: isSetter && summaryResynthesizer.strongMode);
    }
    executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
        executableElement, null, getCurrentTypeArguments(skipLevels: 1), false);
    executableElement.functions = serializedExecutable.localFunctions
        .map((f) => buildLocalFunction(f, executableElement))
        .toList();
    executableElement.labels =
        serializedExecutable.localLabels.map(buildLocalLabel).toList();
    executableElement.localVariables = serializedExecutable.localVariables
        .map((v) => buildLocalVariable(v, executableElement))
        .toList();
    currentTypeParameters.removeLast();
  }

  /**
   * Build the implicit getter and setter associated with [element], and place
   * them in [holder].
   */
  void buildImplicitAccessors(
      PropertyInducingElementImpl element, ElementHolder holder) {
    String name = element.name;
    DartType type = element.type;
    PropertyAccessorElementImpl getter =
        new PropertyAccessorElementImpl(name, element.nameOffset);
    getter.getter = true;
    getter.static = element.isStatic;
    getter.synthetic = true;
    getter.returnType = type;
    getter.type = new FunctionTypeImpl(getter);
    getter.variable = element;
    getter.hasImplicitReturnType = element.hasImplicitType;
    holder.addAccessor(getter);
    element.getter = getter;
    if (!(element.isConst || element.isFinal)) {
      PropertyAccessorElementImpl setter =
          new PropertyAccessorElementImpl(name, element.nameOffset);
      setter.setter = true;
      setter.static = element.isStatic;
      setter.synthetic = true;
      setter.parameters = <ParameterElement>[
        new ParameterElementImpl('_$name', element.nameOffset)
          ..synthetic = true
          ..type = type
          ..parameterKind = ParameterKind.REQUIRED
      ];
      setter.returnType = VoidTypeImpl.instance;
      setter.type = new FunctionTypeImpl(setter);
      setter.variable = element;
      holder.addAccessor(setter);
      element.setter = setter;
    }
  }

  /**
   * Build the implicit field associated with a getter or setter, and place it
   * in [holder].
   */
  FieldElementImpl buildImplicitField(String name, DartType type,
      UnlinkedExecutableKind kind, ElementHolder holder) {
    FieldElementImpl field = holder.getField(name);
    if (field == null) {
      field = new FieldElementImpl(name, -1);
      field.synthetic = true;
      field.final2 = kind == UnlinkedExecutableKind.getter;
      field.type = type;
      holder.addField(field);
      return field;
    } else {
      // TODO(paulberry): what if the getter and setter have a type mismatch?
      field.final2 = false;
      return field;
    }
  }

  /**
   * Build the implicit top level variable associated with a getter or setter,
   * and place it in [holder].
   */
  PropertyInducingElementImpl buildImplicitTopLevelVariable(
      String name, UnlinkedExecutableKind kind, ElementHolder holder) {
    TopLevelVariableElementImpl variable = holder.getTopLevelVariable(name);
    if (variable == null) {
      variable = new TopLevelVariableElementImpl(name, -1);
      variable.synthetic = true;
      variable.final2 = kind == UnlinkedExecutableKind.getter;
      holder.addTopLevelVariable(variable);
      return variable;
    } else {
      // TODO(paulberry): what if the getter and setter have a type mismatch?
      variable.final2 = false;
      return variable;
    }
  }

  /**
   * Build the appropriate [DartType] object corresponding to a slot id in the
   * [LinkedUnit.types] table.
   */
  DartType buildLinkedType(
      int slot, TypeParameterizedElementMixin typeParameterContext) {
    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(type, typeParameterContext);
  }

  /**
   * Resynthesize a local [FunctionElement].
   */
  FunctionElementImpl buildLocalFunction(
      UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement) {
    FunctionElementImpl element = new FunctionElementImpl.forSerialized(
        serializedExecutable, enclosingElement);
    if (serializedExecutable.visibleOffset != 0) {
      element.setVisibleRange(serializedExecutable.visibleOffset,
          serializedExecutable.visibleLength);
    }
    buildExecutableCommonParts(element, serializedExecutable);
    return element;
  }

  /**
   * Resynthesize a [LabelElement].
   */
  LabelElement buildLocalLabel(UnlinkedLabel serializedLabel) {
    return new LabelElementImpl(
        serializedLabel.name,
        serializedLabel.nameOffset,
        serializedLabel.isOnSwitchStatement,
        serializedLabel.isOnSwitchMember);
  }

  /**
   * Resynthesize a [LocalVariableElement].
   */
  LocalVariableElement buildLocalVariable(UnlinkedVariable serializedVariable,
      ExecutableElementImpl enclosingExecutable) {
    LocalVariableElementImpl element;
    if (serializedVariable.constExpr != null && serializedVariable.isConst) {
      ConstLocalVariableElementImpl constElement =
          new ConstLocalVariableElementImpl.forSerialized(
              serializedVariable, enclosingExecutable);
      element = constElement;
      constElement.constantInitializer =
          _buildConstExpression(serializedVariable.constExpr);
    } else {
      element = new LocalVariableElementImpl.forSerialized(
          serializedVariable, enclosingExecutable);
    }
    if (serializedVariable.visibleOffset != 0) {
      element.setVisibleRange(
          serializedVariable.visibleOffset, serializedVariable.visibleLength);
    }
    buildVariableCommonParts(element, serializedVariable,
        isLazilyResynthesized: true);
    return element;
  }

  /**
   * Resynthesize a [ParameterElement].
   */
  ParameterElement buildParameter(
      UnlinkedParam serializedParameter, ElementImpl enclosingElement,
      {bool synthetic: false}) {
    ParameterElementImpl parameterElement;
    bool isLazilyResynthesized = false;
    int nameOffset = synthetic ? -1 : serializedParameter.nameOffset;
    if (serializedParameter.isInitializingFormal) {
      FieldFormalParameterElementImpl initializingParameter;
      if (serializedParameter.kind == UnlinkedParamKind.required) {
        initializingParameter = new FieldFormalParameterElementImpl(
            serializedParameter.name, nameOffset);
      } else {
        DefaultFieldFormalParameterElementImpl defaultParameter =
            new DefaultFieldFormalParameterElementImpl(
                serializedParameter.name, nameOffset);
        initializingParameter = defaultParameter;
        if (serializedParameter.defaultValue != null) {
          defaultParameter.constantInitializer =
              _buildConstExpression(serializedParameter.defaultValue);
          defaultParameter.defaultValueCode =
              serializedParameter.defaultValueCode;
        }
      }
      parameterElement = initializingParameter;
      initializingParameter.field = fields[serializedParameter.name];
    } else {
      if (serializedParameter.kind == UnlinkedParamKind.required) {
        parameterElement = new ParameterElementImpl.forSerialized(
            serializedParameter, enclosingElement);
        isLazilyResynthesized = true;
      } else {
        DefaultParameterElementImpl defaultParameter =
            new DefaultParameterElementImpl.forSerialized(
                serializedParameter, enclosingElement);
        isLazilyResynthesized = true;
        parameterElement = defaultParameter;
      }
    }
    parameterElement.synthetic = synthetic;
    if (!isLazilyResynthesized) {
      buildAnnotations(parameterElement, serializedParameter.annotations);
      buildCodeRange(parameterElement, serializedParameter.codeRange);
    }
    if (serializedParameter.isFunctionTyped) {
      FunctionElementImpl parameterTypeElement =
          new FunctionElementImpl('', -1);
      parameterTypeElement.synthetic = true;
      List<ParameterElement> subParameters = serializedParameter.parameters
          .map((UnlinkedParam p) =>
              buildParameter(p, parameterTypeElement, synthetic: synthetic))
          .toList();
      if (synthetic) {
        parameterTypeElement.parameters = subParameters;
      } else {
        parameterElement.parameters = subParameters;
        parameterTypeElement.shareParameters(subParameters);
        parameterTypeElement.enclosingElement = parameterElement;
      }
      parameterTypeElement.returnType =
          buildType(serializedParameter.type, _currentTypeParameterizedElement);
      parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
          parameterTypeElement, null, getCurrentTypeArguments(), false);
      parameterTypeElement.type = parameterElement.type;
    } else {
      if (serializedParameter.isInitializingFormal &&
          serializedParameter.type == null) {
        // The type is inherited from the matching field.
        parameterElement.type =
            fields[serializedParameter.name]?.type ?? DynamicTypeImpl.instance;
      } else {
        parameterElement.type = buildLinkedType(
                serializedParameter.inferredTypeSlot,
                _currentTypeParameterizedElement) ??
            buildType(
                serializedParameter.type, _currentTypeParameterizedElement);
      }
      if (!isLazilyResynthesized) {
        parameterElement.hasImplicitType = serializedParameter.type == null;
      }
    }
    buildVariableInitializer(parameterElement, serializedParameter.initializer);
    switch (serializedParameter.kind) {
      case UnlinkedParamKind.named:
        parameterElement.parameterKind = ParameterKind.NAMED;
        break;
      case UnlinkedParamKind.positional:
        parameterElement.parameterKind = ParameterKind.POSITIONAL;
        break;
      case UnlinkedParamKind.required:
        parameterElement.parameterKind = ParameterKind.REQUIRED;
        break;
    }
    if (!isLazilyResynthesized) {
      if (serializedParameter.visibleOffset != 0) {
        parameterElement.setVisibleRange(serializedParameter.visibleOffset,
            serializedParameter.visibleLength);
      }
    }
    return parameterElement;
  }

  /**
   * Handle the parts that are common to top level variables and fields.
   */
  void buildPropertyIntroducingElementCommonParts(
      PropertyInducingElementImpl element,
      UnlinkedVariable serializedVariable) {
    buildVariableCommonParts(element, serializedVariable);
    element.propagatedType = buildLinkedType(
        serializedVariable.propagatedTypeSlot,
        _currentTypeParameterizedElement);
  }

  /**
   * Build a [DartType] object based on a [EntityRef].  This [DartType]
   * may refer to elements in other libraries than the library being
   * deserialized, so handles are used to avoid having to deserialize other
   * libraries in the process.
   */
  DartType buildType(
      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
      {bool defaultVoid: false, bool instantiateToBoundsAllowed: true}) {
    if (type == null) {
      if (defaultVoid) {
        return VoidTypeImpl.instance;
      } else {
        return DynamicTypeImpl.instance;
      }
    }
    if (type.paramReference != 0) {
      return typeParameterContext.getTypeParameterType(type.paramReference);
    } else if (type.syntheticReturnType != null) {
      FunctionElementImpl element = new FunctionElementImpl('', -1);
      element.synthetic = true;
      element.parameters = type.syntheticParams
          .map((UnlinkedParam param) =>
              buildParameter(param, element, synthetic: true))
          .toList();
      element.returnType =
          buildType(type.syntheticReturnType, typeParameterContext);
      FunctionTypeImpl result = new FunctionTypeImpl.elementWithNameAndArgs(
          element, null, null, false);
      element.type = result;
      return result;
    } else {
      DartType getTypeArgument(int i) {
        if (i < type.typeArguments.length) {
          return buildType(type.typeArguments[i], typeParameterContext);
        } else {
          return DynamicTypeImpl.instance;
        }
      }
      _ReferenceInfo referenceInfo = getReferenceInfo(type.reference);
      return referenceInfo.buildType(
          instantiateToBoundsAllowed,
          type.typeArguments.length,
          getTypeArgument,
          type.implicitFunctionTypeIndices);
    }
  }

  /**
   * Resynthesize a [FunctionTypeAliasElement] and place it in the
   * [unitHolder].
   */
  void buildTypedef(UnlinkedTypedef serializedTypedef) {
    FunctionTypeAliasElementImpl functionTypeAliasElement =
        new FunctionTypeAliasElementImpl.forSerialized(serializedTypedef, unit);
    // TODO(scheglov) remove this after delaying parameters and their types
    currentTypeParameters.add(functionTypeAliasElement.typeParameters);
    functionTypeAliasElement.parameters = serializedTypedef.parameters
        .map((p) => buildParameter(p, functionTypeAliasElement))
        .toList();
    functionTypeAliasElement.returnType =
        buildType(serializedTypedef.returnType, functionTypeAliasElement);
    functionTypeAliasElement.type =
        new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
    unitHolder.addTypeAlias(functionTypeAliasElement);
    // TODO(scheglov) remove this after delaying parameters and their types
    currentTypeParameters.removeLast();
    assert(currentTypeParameters.isEmpty);
  }

  /**
   * Resynthesize a [TypeParameterElement], handling all parts of its except
   * its bound.
   *
   * The bound is deferred until later since it may refer to other type
   * parameters that have not been resynthesized yet.  To handle the bound,
   * call [finishTypeParameter].
   */
  TypeParameterElement buildTypeParameter(
      UnlinkedTypeParam serializedTypeParameter) {
    TypeParameterElementImpl typeParameterElement =
        new TypeParameterElementImpl(
            serializedTypeParameter.name, serializedTypeParameter.nameOffset);
    typeParameterElement.type = new TypeParameterTypeImpl(typeParameterElement);
    buildAnnotations(typeParameterElement, serializedTypeParameter.annotations);
    buildCodeRange(typeParameterElement, serializedTypeParameter.codeRange);
    return typeParameterElement;
  }

  /**
   * Build [TypeParameterElement]s corresponding to the type parameters in
   * [serializedTypeParameters] and store them in [currentTypeParameters].
   * Also return them.
   */
  List<TypeParameterElement> buildTypeParameters(
      List<UnlinkedTypeParam> serializedTypeParameters) {
    List<TypeParameterElement> typeParameters =
        serializedTypeParameters.map(buildTypeParameter).toList();
    currentTypeParameters.add(typeParameters);
    for (int i = 0; i < serializedTypeParameters.length; i++) {
      finishTypeParameter(serializedTypeParameters[i], typeParameters[i]);
    }
    return typeParameters;
  }

  /**
   * Resynthesize a [TopLevelVariableElement] or [FieldElement].
   */
  void buildVariable(UnlinkedVariable serializedVariable,
      [ElementHolder holder]) {
    if (holder == null) {
      TopLevelVariableElementImpl element;
      if (serializedVariable.constExpr != null && serializedVariable.isConst) {
        ConstTopLevelVariableElementImpl constElement =
            new ConstTopLevelVariableElementImpl(
                serializedVariable.name, serializedVariable.nameOffset);
        element = constElement;
        constElement.constantInitializer =
            _buildConstExpression(serializedVariable.constExpr);
      } else {
        element = new TopLevelVariableElementImpl(
            serializedVariable.name, serializedVariable.nameOffset);
      }
      buildPropertyIntroducingElementCommonParts(element, serializedVariable);
      unitHolder.addTopLevelVariable(element);
      buildImplicitAccessors(element, unitHolder);
    } else {
      FieldElementImpl element;
      if (serializedVariable.constExpr != null &&
          (serializedVariable.isConst ||
              serializedVariable.isFinal && !serializedVariable.isStatic)) {
        ConstFieldElementImpl constElement = new ConstFieldElementImpl(
            serializedVariable.name, serializedVariable.nameOffset);
        element = constElement;
        constElement.constantInitializer =
            _buildConstExpression(serializedVariable.constExpr);
      } else {
        element = new FieldElementImpl(
            serializedVariable.name, serializedVariable.nameOffset);
      }
      buildPropertyIntroducingElementCommonParts(element, serializedVariable);
      element.static = serializedVariable.isStatic;
      holder.addField(element);
      buildImplicitAccessors(element, holder);
      fields[element.name] = element;
    }
  }

  /**
   * Handle the parts that are common to variables.
   */
  void buildVariableCommonParts(
      VariableElementImpl element, UnlinkedVariable serializedVariable,
      {bool isLazilyResynthesized: false}) {
    element.type = buildLinkedType(serializedVariable.inferredTypeSlot,
            _currentTypeParameterizedElement) ??
        buildType(serializedVariable.type, _currentTypeParameterizedElement);
    if (!isLazilyResynthesized) {
      element.const3 = serializedVariable.isConst;
      element.final2 = serializedVariable.isFinal;
      element.hasImplicitType = serializedVariable.type == null;
      buildDocumentation(element, serializedVariable.documentationComment);
      buildAnnotations(element, serializedVariable.annotations);
      buildCodeRange(element, serializedVariable.codeRange);
    }
    buildVariableInitializer(element, serializedVariable.initializer);
  }

  /**
   * If the given [serializedInitializer] is not `null`, create the
   * corresponding [FunctionElementImpl] and set it for the [variable].
   */
  void buildVariableInitializer(
      VariableElementImpl variable, UnlinkedExecutable serializedInitializer) {
    if (serializedInitializer == null) {
      return null;
    }
    FunctionElementImpl initializerElement =
        buildLocalFunction(serializedInitializer, variable);
    initializerElement.synthetic = true;
    variable.initializer = initializerElement;
  }

  /**
   * Finish creating a [TypeParameterElement] by deserializing its bound.
   */
  void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter,
      TypeParameterElementImpl typeParameterElement) {
    if (serializedTypeParameter.bound != null) {
      typeParameterElement.bound = buildType(
          serializedTypeParameter.bound, _currentTypeParameterizedElement,
          instantiateToBoundsAllowed: false);
    }
  }

  /**
   * Return a list of type arguments corresponding to [currentTypeParameters],
   * skipping the innermost [skipLevels] nesting levels.
   *
   * Type parameters are listed in nesting order from innermost to outermost,
   * and then in declaration order.  So for instance if we are resynthesizing a
   * method declared as `class C<T, U> { void m<V, W>() { ... } }`, then the
   * type parameters will be returned in the order `[V, W, T, U]`.
   */
  List<DartType> getCurrentTypeArguments({int skipLevels: 0}) {
    assert(currentTypeParameters.length >= skipLevels);
    List<DartType> result = <DartType>[];
    for (int i = currentTypeParameters.length - 1 - skipLevels; i >= 0; i--) {
      result.addAll(currentTypeParameters[i]
          .map((TypeParameterElement param) => param.type));
    }
    return result;
  }

  /**
   * Return [_ReferenceInfo] with the given [index], lazily resolving it.
   */
  _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;
      int numTypeParameters = linkedReference.numTypeParameters;
      if (linkedReference.kind == ReferenceKind.unresolved) {
        type = UndefinedTypeImpl.instance;
        element = null;
      } else if (name == 'dynamic') {
        type = DynamicTypeImpl.instance;
        element = type.element;
      } else if (name == 'void') {
        type = VoidTypeImpl.instance;
        element = type.element;
      } else if (name == '*bottom*') {
        type = BottomTypeImpl.instance;
        element = null;
      } 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);
        }
        ElementLocation location =
            new ElementLocationImpl.con3(locationComponents);
        if (enclosingInfo != null) {
          numTypeParameters += enclosingInfo.numTypeParameters;
        }
        switch (linkedReference.kind) {
          case ReferenceKind.classOrEnum:
            element = new ClassElementHandle(summaryResynthesizer, location);
            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:
            element = new FunctionTypeAliasElementHandle(
                summaryResynthesizer, location);
            break;
          case ReferenceKind.variable:
            Element enclosingElement = enclosingInfo.element;
            if (enclosingElement is ExecutableElement) {
              element = new _DeferredLocalVariableElement(
                  enclosingElement, linkedReference.localIndex);
            } else {
              throw new StateError('Unexpected element enclosing variable:'
                  ' ${enclosingElement.runtimeType}');
            }
            break;
          case ReferenceKind.function:
            Element enclosingElement = enclosingInfo.element;
            if (enclosingElement is VariableElement) {
              element = new _DeferredInitializerElement(enclosingElement);
            } else if (enclosingElement is ExecutableElement) {
              element = new _DeferredLocalFunctionElement(
                  enclosingElement, linkedReference.localIndex);
            } else {
              throw new StateError('Unexpected element enclosing function:'
                  ' ${enclosingElement.runtimeType}');
            }
            break;
          case ReferenceKind.prefix:
          case ReferenceKind.unresolved:
            break;
        }
      }
      result = new _ReferenceInfo(libraryResynthesizer, enclosingInfo, name,
          element, type, numTypeParameters);
      referenceInfos[index] = result;
    }
    return result;
  }

  /**
   * Get the type parameter from the surrounding scope whose De Bruijn index is
   * [index].
   */
  DartType getTypeParameterFromScope(int index) {
    for (int i = currentTypeParameters.length - 1; i >= 0; i--) {
      List<TypeParameterElement> paramsAtThisNestingLevel =
          currentTypeParameters[i];
      int numParamsAtThisNestingLevel = paramsAtThisNestingLevel.length;
      if (index <= numParamsAtThisNestingLevel) {
        return paramsAtThisNestingLevel[numParamsAtThisNestingLevel - index]
            .type;
      }
      index -= numParamsAtThisNestingLevel;
    }
    throw new StateError('Type parameter not found');
  }

  /**
   * Populate a [CompilationUnitElement] by deserializing all the elements
   * contained in it.
   */
  void populateUnit() {
    unlinkedUnit.classes.forEach(buildClass);
    unlinkedUnit.enums.forEach(buildEnum);
    unlinkedUnit.executables.forEach((e) => buildExecutable(e, unit));
    unlinkedUnit.typedefs.forEach(buildTypedef);
    unlinkedUnit.variables.forEach(buildVariable);
    unit.accessors = unitHolder.accessors;
    unit.enums = unitHolder.enums;
    unit.functions = unitHolder.functions;
    List<FunctionTypeAliasElement> typeAliases = unitHolder.typeAliases;
    for (FunctionTypeAliasElementImpl typeAlias in typeAliases) {
      if (typeAlias.isSynthetic) {
        typeAlias.enclosingElement = unit;
      }
    }
    unit.typeAliases = typeAliases.where((e) => !e.isSynthetic).toList();
    unit.types = unitHolder.types;
    unit.topLevelVariables = unitHolder.topLevelVariables;
    for (ClassElement cls in unit.types) {
      elementMap[cls.name] = cls;
    }
    for (ClassElement cls in unit.enums) {
      elementMap[cls.name] = cls;
    }
    for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) {
      elementMap[typeAlias.name] = typeAlias;
    }
    for (FunctionElement function in unit.functions) {
      elementMap[function.name] = function;
    }
    for (PropertyAccessorElementImpl accessor in unit.accessors) {
      elementMap[accessor.identifier] = accessor;
    }
    assert(currentTypeParameters.isEmpty);
  }

  /**
   * Constructor initializers can reference fields and other constructors of
   * the same class, including forward references. So, we need to delay
   * resolution until after class elements are built.
   */
  void resolveConstructorInitializers(ClassElementImpl classElement) {
    for (ConstructorElementImpl constructor in constructors.values) {
      for (ConstructorInitializer initializer
          in constructor.constantInitializers) {
        if (initializer is ConstructorFieldInitializer) {
          SimpleIdentifier nameNode = initializer.fieldName;
          nameNode.staticElement = fields[nameNode.name];
        } else if (initializer is SuperConstructorInvocation) {
          SimpleIdentifier nameNode = initializer.constructorName;
          ConstructorElement element = new _DeferredConstructorElement(
              classElement.supertype, nameNode?.name ?? '');
          initializer.staticElement = element;
          nameNode?.staticElement = element;
        } else if (initializer is RedirectingConstructorInvocation) {
          SimpleIdentifier nameNode = initializer.constructorName;
          ConstructorElement element = constructors[nameNode?.name ?? ''];
          initializer.staticElement = element;
          nameNode?.staticElement = element;
        }
      }
    }
  }

  Expression _buildConstExpression(UnlinkedConst uc) {
    return new _ConstExprBuilder(this, uc).build();
  }

  /**
   * Return the defining type for a [ConstructorElement] by applying
   * [typeArgumentRefs] to the given linked [info].
   */
  InterfaceType _createConstructorDefiningType(
      _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
    bool isClass = info.element is ClassElement;
    _ReferenceInfo classInfo = isClass ? info : info.enclosing;
    List<DartType> typeArguments = typeArgumentRefs
        .map((t) => buildType(t, _currentTypeParameterizedElement))
        .toList();
    return classInfo.buildType(true, typeArguments.length, (i) {
      if (i < typeArguments.length) {
        return typeArguments[i];
      } else {
        return DynamicTypeImpl.instance;
      }
    }, const <int>[]);
  }

  /**
   * Return 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 _createConstructorElement(
      InterfaceType classType, _ReferenceInfo info) {
    bool isClass = info.element is ClassElement;
    String name = isClass ? '' : info.name;
    _DeferredConstructorElement element =
        new _DeferredConstructorElement(classType, name);
    if (info.numTypeParameters != 0) {
      return new ConstructorMember(element, classType);
    } else {
      return element;
    }
  }

  /**
   * 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;
  }
}
