// Copyright (c) 2014, 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 analyzer.src.dart.element.element;

import 'dart:collection';
import 'dart:math' show min;

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart' show CompileTimeErrorCode;
import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
    show AnalysisContext, AnalysisEngine;
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/ast_factory.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/task/dart.dart';

/**
 * Assert that the given [object] is null, which in the places where this
 * function is called means that the element is not resynthesized.
 */
void _assertNotResynthesized(Object object) {
  // TODO(scheglov) I comment this check for now.
  // When we make a decision about switch to the new analysis driver,
  // we will need to rework the analysis code to don't call the setters
  // or restore / inline it.
//  assert(object == null);
}

/**
 * A concrete implementation of a [ClassElement].
 */
abstract class AbstractClassElementImpl extends ElementImpl
    implements ClassElement {
  /**
   * A list containing all of the accessors (getters and setters) contained in
   * this class.
   */
  List<PropertyAccessorElement> _accessors;

  /**
   * A list containing all of the fields contained in this class.
   */
  List<FieldElement> _fields;

  /**
   * Initialize a newly created class element to have the given [name] at the
   * given [offset] in the file that contains the declaration of this element.
   */
  AbstractClassElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created class element to have the given [name].
   */
  AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  AbstractClassElementImpl.forSerialized(
      CompilationUnitElementImpl enclosingUnit)
      : super.forSerialized(enclosingUnit);

  @override
  List<PropertyAccessorElement> get accessors {
    return _accessors ?? const <PropertyAccessorElement>[];
  }

  /**
   * Set the accessors contained in this class to the given [accessors].
   */
  void set accessors(List<PropertyAccessorElement> accessors) {
    for (PropertyAccessorElement accessor in accessors) {
      (accessor as PropertyAccessorElementImpl).enclosingElement = this;
    }
    this._accessors = accessors;
  }

  @override
  String get displayName => name;

  @override
  List<FieldElement> get fields => _fields ?? const <FieldElement>[];

  /**
   * Set the fields contained in this class to the given [fields].
   */
  void set fields(List<FieldElement> fields) {
    for (FieldElement field in fields) {
      (field as FieldElementImpl).enclosingElement = this;
    }
    this._fields = fields;
  }

  @override
  bool get isEnum;

  @override
  ElementKind get kind => ElementKind.CLASS;

  @override
  accept(ElementVisitor visitor) => visitor.visitClassElement(this);

  @override
  NamedCompilationUnitMember computeNode() {
    if (isEnum) {
      return getNodeMatching((node) => node is EnumDeclaration);
    } else {
      return getNodeMatching(
          (node) => node is ClassDeclaration || node is ClassTypeAlias);
    }
  }

  @override
  ElementImpl getChild(String identifier) {
    //
    // The casts in this method are safe because the set methods would have
    // thrown a CCE if any of the elements in the arrays were not of the
    // expected types.
    //
    for (PropertyAccessorElement accessor in accessors) {
      PropertyAccessorElementImpl accessorImpl = accessor;
      if (accessorImpl.identifier == identifier) {
        return accessorImpl;
      }
    }
    for (FieldElement field in fields) {
      FieldElementImpl fieldImpl = field;
      if (fieldImpl.identifier == identifier) {
        return fieldImpl;
      }
    }
    return null;
  }

  @override
  FieldElement getField(String name) {
    for (FieldElement fieldElement in fields) {
      if (name == fieldElement.name) {
        return fieldElement;
      }
    }
    return null;
  }

  @override
  PropertyAccessorElement getGetter(String getterName) {
    int length = accessors.length;
    for (int i = 0; i < length; i++) {
      PropertyAccessorElement accessor = accessors[i];
      if (accessor.isGetter && accessor.name == getterName) {
        return accessor;
      }
    }
    return null;
  }

  @override
  PropertyAccessorElement getSetter(String setterName) {
    // TODO (jwren) revisit- should we append '=' here or require clients to
    // include it?
    // Do we need the check for isSetter below?
    if (!StringUtilities.endsWithChar(setterName, 0x3D)) {
      setterName += '=';
    }
    for (PropertyAccessorElement accessor in accessors) {
      if (accessor.isSetter && accessor.name == setterName) {
        return accessor;
      }
    }
    return null;
  }

  @override
  MethodElement lookUpConcreteMethod(
          String methodName, LibraryElement library) =>
      _first(_implementationsOfMethod(methodName).where(
          (MethodElement method) =>
              !method.isAbstract && method.isAccessibleIn(library)));

  @override
  PropertyAccessorElement lookUpGetter(
          String getterName, LibraryElement library) =>
      _first(_implementationsOfGetter(getterName).where(
          (PropertyAccessorElement getter) => getter.isAccessibleIn(library)));

  @override
  PropertyAccessorElement lookUpInheritedConcreteGetter(
          String getterName, LibraryElement library) =>
      _first(_implementationsOfGetter(getterName).where(
          (PropertyAccessorElement getter) =>
              !getter.isAbstract &&
              getter.isAccessibleIn(library) &&
              getter.enclosingElement != this));

  @override
  MethodElement lookUpInheritedConcreteMethod(
          String methodName, LibraryElement library) =>
      _first(_implementationsOfMethod(methodName).where(
          (MethodElement method) =>
              !method.isAbstract &&
              method.isAccessibleIn(library) &&
              method.enclosingElement != this));

  @override
  PropertyAccessorElement lookUpInheritedConcreteSetter(
          String setterName, LibraryElement library) =>
      _first(_implementationsOfSetter(setterName).where(
          (PropertyAccessorElement setter) =>
              !setter.isAbstract &&
              setter.isAccessibleIn(library) &&
              setter.enclosingElement != this));

  @override
  MethodElement lookUpInheritedMethod(
          String methodName, LibraryElement library) =>
      _first(_implementationsOfMethod(methodName).where(
          (MethodElement method) =>
              method.isAccessibleIn(library) &&
              method.enclosingElement != this));

  @override
  MethodElement lookUpMethod(String methodName, LibraryElement library) =>
      _first(_implementationsOfMethod(methodName)
          .where((MethodElement method) => method.isAccessibleIn(library)));

  @override
  PropertyAccessorElement lookUpSetter(
          String setterName, LibraryElement library) =>
      _first(_implementationsOfSetter(setterName).where(
          (PropertyAccessorElement setter) => setter.isAccessibleIn(library)));

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(accessors, visitor);
    safelyVisitChildren(fields, visitor);
  }

  /**
   * Return the first element from the given [iterable], or `null` if the
   * iterable is empty.
   */
  Object/*=E*/ _first/*<E>*/(Iterable/*<E>*/ iterable) {
    if (iterable.isEmpty) {
      return null;
    }
    return iterable.first;
  }

  /**
   * Return an iterable containing all of the implementations of a getter with
   * the given [getterName] that are defined in this class any any superclass of
   * this class (but not in interfaces).
   *
   * The getters that are returned are not filtered in any way. In particular,
   * they can include getters that are not visible in some context. Clients must
   * perform any necessary filtering.
   *
   * The getters are returned based on the depth of their defining class; if
   * this class contains a definition of the getter it will occur first, if
   * Object contains a definition of the getter it will occur last.
   */
  Iterable<PropertyAccessorElement> _implementationsOfGetter(
      String getterName) sync* {
    ClassElement classElement = this;
    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
    while (classElement != null && visitedClasses.add(classElement)) {
      PropertyAccessorElement getter = classElement.getGetter(getterName);
      if (getter != null) {
        yield getter;
      }
      for (InterfaceType mixin in classElement.mixins.reversed) {
        getter = mixin.element?.getGetter(getterName);
        if (getter != null) {
          yield getter;
        }
      }
      classElement = classElement.supertype?.element;
    }
  }

  /**
   * Return an iterable containing all of the implementations of a method with
   * the given [methodName] that are defined in this class any any superclass of
   * this class (but not in interfaces).
   *
   * The methods that are returned are not filtered in any way. In particular,
   * they can include methods that are not visible in some context. Clients must
   * perform any necessary filtering.
   *
   * The methods are returned based on the depth of their defining class; if
   * this class contains a definition of the method it will occur first, if
   * Object contains a definition of the method it will occur last.
   */
  Iterable<MethodElement> _implementationsOfMethod(String methodName) sync* {
    ClassElement classElement = this;
    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
    while (classElement != null && visitedClasses.add(classElement)) {
      MethodElement method = classElement.getMethod(methodName);
      if (method != null) {
        yield method;
      }
      for (InterfaceType mixin in classElement.mixins.reversed) {
        method = mixin.element?.getMethod(methodName);
        if (method != null) {
          yield method;
        }
      }
      classElement = classElement.supertype?.element;
    }
  }

  /**
   * Return an iterable containing all of the implementations of a setter with
   * the given [setterName] that are defined in this class any any superclass of
   * this class (but not in interfaces).
   *
   * The setters that are returned are not filtered in any way. In particular,
   * they can include setters that are not visible in some context. Clients must
   * perform any necessary filtering.
   *
   * The setters are returned based on the depth of their defining class; if
   * this class contains a definition of the setter it will occur first, if
   * Object contains a definition of the setter it will occur last.
   */
  Iterable<PropertyAccessorElement> _implementationsOfSetter(
      String setterName) sync* {
    ClassElement classElement = this;
    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
    while (classElement != null && visitedClasses.add(classElement)) {
      PropertyAccessorElement setter = classElement.getSetter(setterName);
      if (setter != null) {
        yield setter;
      }
      for (InterfaceType mixin in classElement.mixins.reversed) {
        setter = mixin.element?.getSetter(setterName);
        if (setter != null) {
          yield setter;
        }
      }
      classElement = classElement.supertype?.element;
    }
  }

  /**
   * Return the [AbstractClassElementImpl] of the given [classElement].  May
   * throw an exception if the [AbstractClassElementImpl] cannot be provided
   * (should not happen though).
   */
  static AbstractClassElementImpl getImpl(ClassElement classElement) {
    if (classElement is ClassElementHandle) {
      return getImpl(classElement.actualElement);
    }
    return classElement as AbstractClassElementImpl;
  }
}

/**
 * For AST nodes that could be in both the getter and setter contexts
 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved
 * elements are stored in the AST node, in an [AuxiliaryElements]. Because
 * resolved elements are either statically resolved or resolved using propagated
 * type information, this class is a wrapper for a pair of [ExecutableElement]s,
 * not just a single [ExecutableElement].
 */
class AuxiliaryElements {
  /**
   * The element based on propagated type information, or `null` if the AST
   * structure has not been resolved or if the node could not be resolved.
   */
  final ExecutableElement propagatedElement;

  /**
   * The element based on static type information, or `null` if the AST
   * structure has not been resolved or if the node could not be resolved.
   */
  final ExecutableElement staticElement;

  /**
   * Initialize a newly created pair to have both the [staticElement] and the
   * [propagatedElement].
   */
  AuxiliaryElements(this.staticElement, this.propagatedElement);
}

/**
 * An [AbstractClassElementImpl] which is a class.
 */
class ClassElementImpl extends AbstractClassElementImpl
    with TypeParameterizedElementMixin {
  /**
   * The unlinked representation of the class in the summary.
   */
  final UnlinkedClass _unlinkedClass;

  /**
   * A list containing all of the type parameters defined for this class.
   */
  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;

  /**
   * The superclass of the class, or `null` for [Object].
   */
  InterfaceType _supertype;

  /**
   * The type defined by the class.
   */
  InterfaceType _type;

  /**
   * A list containing all of the mixins that are applied to the class being
   * extended in order to derive the superclass of this class.
   */
  List<InterfaceType> _mixins;

  /**
   * A list containing all of the interfaces that are implemented by this class.
   */
  List<InterfaceType> _interfaces;

  /**
   * For classes which are not mixin applications, a list containing all of the
   * constructors contained in this class, or `null` if the list of
   * constructors has not yet been built.
   *
   * For classes which are mixin applications, the list of constructors is
   * computed on the fly by the [constructors] getter, and this field is
   * `null`.
   */
  List<ConstructorElement> _constructors;

  /**
   * A list containing all of the methods contained in this class.
   */
  List<MethodElement> _methods;

  /**
   * A flag indicating whether the types associated with the instance members of
   * this class have been inferred.
   */
  bool _hasBeenInferred = false;

  /**
   * The version of this element. The version is changed when the element is
   * incrementally updated, so that its lists of constructors, accessors and
   * methods might be different.
   */
  int version = 0;

  /**
   * Initialize a newly created class element to have the given [name] at the
   * given [offset] in the file that contains the declaration of this element.
   */
  ClassElementImpl(String name, int offset)
      : _unlinkedClass = null,
        super(name, offset);

  /**
   * Initialize a newly created class element to have the given [name].
   */
  ClassElementImpl.forNode(Identifier name)
      : _unlinkedClass = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ClassElementImpl.forSerialized(
      this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
      : super.forSerialized(enclosingUnit);

  /**
   * Set whether this class is abstract.
   */
  void set abstract(bool isAbstract) {
    _assertNotResynthesized(_unlinkedClass);
    setModifier(Modifier.ABSTRACT, isAbstract);
  }

  @override
  List<PropertyAccessorElement> get accessors {
    if (_unlinkedClass != null && _accessors == null) {
      _resynthesizeFieldsAndPropertyAccessors();
    }
    return _accessors ?? const <PropertyAccessorElement>[];
  }

  @override
  void set accessors(List<PropertyAccessorElement> accessors) {
    _assertNotResynthesized(_unlinkedClass);
    super.accessors = accessors;
  }

  @override
  List<InterfaceType> get allSupertypes {
    List<InterfaceType> list = new List<InterfaceType>();
    _collectAllSupertypes(list);
    return list;
  }

  @override
  int get codeLength {
    if (_unlinkedClass != null) {
      return _unlinkedClass.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedClass != null) {
      return _unlinkedClass.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  List<ConstructorElement> get constructors {
    if (isMixinApplication) {
      return _computeMixinAppConstructors();
    }
    if (_unlinkedClass != null && _constructors == null) {
      _constructors = _unlinkedClass.executables
          .where((e) => e.kind == UnlinkedExecutableKind.constructor)
          .map((e) => new ConstructorElementImpl.forSerialized(e, this))
          .toList(growable: false);
      // Ensure at least implicit default constructor.
      if (_constructors.isEmpty) {
        ConstructorElementImpl constructor = new ConstructorElementImpl('', -1);
        constructor.synthetic = true;
        constructor.enclosingElement = this;
        _constructors = <ConstructorElement>[constructor];
      }
    }
    assert(_constructors != null);
    return _constructors ?? const <ConstructorElement>[];
  }

  /**
   * Set the constructors contained in this class to the given [constructors].
   *
   * Should only be used for class elements that are not mixin applications.
   */
  void set constructors(List<ConstructorElement> constructors) {
    _assertNotResynthesized(_unlinkedClass);
    assert(!isMixinApplication);
    for (ConstructorElement constructor in constructors) {
      (constructor as ConstructorElementImpl).enclosingElement = this;
    }
    this._constructors = constructors;
  }

  @override
  String get documentationComment {
    if (_unlinkedClass != null) {
      return _unlinkedClass?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  /**
   * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should
   * be reported for this class.
   */
  bool get doesMixinLackConstructors {
    if (!isMixinApplication && mixins.isEmpty) {
      // This class is not a mixin application and it doesn't have a "with"
      // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is
      // inapplicable.
      return false;
    }
    if (supertype == null) {
      // Should never happen, since Object is the only class that has no
      // supertype, and it should have been caught by the test above.
      assert(false);
      return false;
    }
    // Find the nearest class in the supertype chain that is not a mixin
    // application.
    ClassElement nearestNonMixinClass = supertype.element;
    if (nearestNonMixinClass.isMixinApplication) {
      // Use a list to keep track of the classes we've seen, so that we won't
      // go into an infinite loop in the event of a non-trivial loop in the
      // class hierarchy.
      List<ClassElement> classesSeen = <ClassElement>[this];
      while (nearestNonMixinClass.isMixinApplication) {
        if (classesSeen.contains(nearestNonMixinClass)) {
          // Loop in the class hierarchy (which is reported elsewhere).  Don't
          // confuse the user with further errors.
          return false;
        }
        classesSeen.add(nearestNonMixinClass);
        if (nearestNonMixinClass.supertype == null) {
          // Should never happen, since Object is the only class that has no
          // supertype, and it is not a mixin application.
          assert(false);
          return false;
        }
        nearestNonMixinClass = nearestNonMixinClass.supertype.element;
      }
    }
    return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible);
  }

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;

  @override
  List<FieldElement> get fields {
    if (_unlinkedClass != null && _fields == null) {
      _resynthesizeFieldsAndPropertyAccessors();
    }
    return _fields ?? const <FieldElement>[];
  }

  @override
  void set fields(List<FieldElement> fields) {
    _assertNotResynthesized(_unlinkedClass);
    super.fields = fields;
  }

  bool get hasBeenInferred {
    if (_unlinkedClass != null) {
      return context.analysisOptions.strongMode;
    }
    return _hasBeenInferred;
  }

  void set hasBeenInferred(bool hasBeenInferred) {
    _assertNotResynthesized(_unlinkedClass);
    _hasBeenInferred = hasBeenInferred;
  }

  @override
  bool get hasNonFinalField {
    List<ClassElement> classesToVisit = new List<ClassElement>();
    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
    classesToVisit.add(this);
    while (!classesToVisit.isEmpty) {
      ClassElement currentElement = classesToVisit.removeAt(0);
      if (visitedClasses.add(currentElement)) {
        // check fields
        for (FieldElement field in currentElement.fields) {
          if (!field.isFinal &&
              !field.isConst &&
              !field.isStatic &&
              !field.isSynthetic) {
            return true;
          }
        }
        // check mixins
        for (InterfaceType mixinType in currentElement.mixins) {
          ClassElement mixinElement = mixinType.element;
          classesToVisit.add(mixinElement);
        }
        // check super
        InterfaceType supertype = currentElement.supertype;
        if (supertype != null) {
          ClassElement superElement = supertype.element;
          if (superElement != null) {
            classesToVisit.add(superElement);
          }
        }
      }
    }
    // not found
    return false;
  }

  /**
   * Return `true` if the class has a `noSuchMethod()` method distinct from the
   * one declared in class `Object`, as per the Dart Language Specification
   * (section 10.4).
   */
  bool get hasNoSuchMethod {
    MethodElement method =
        lookUpMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library);
    ClassElement definingClass = method?.enclosingElement;
    return definingClass != null && !definingClass.type.isObject;
  }

  @override
  bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER);

  /**
   * Set whether this class references 'super'.
   */
  void set hasReferenceToSuper(bool isReferencedSuper) {
    setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
  }

  @override
  bool get hasStaticMember {
    for (MethodElement method in methods) {
      if (method.isStatic) {
        return true;
      }
    }
    for (PropertyAccessorElement accessor in accessors) {
      if (accessor.isStatic) {
        return true;
      }
    }
    return false;
  }

  @override
  List<InterfaceType> get interfaces {
    if (_unlinkedClass != null && _interfaces == null) {
      ResynthesizerContext context = enclosingUnit.resynthesizerContext;
      _interfaces = _unlinkedClass.interfaces
          .map((EntityRef t) => context.resolveTypeRef(t, this))
          .where((DartType type) => type is InterfaceType)
          .toList(growable: false);
    }
    return _interfaces ?? const <InterfaceType>[];
  }

  void set interfaces(List<InterfaceType> interfaces) {
    _assertNotResynthesized(_unlinkedClass);
    _interfaces = interfaces;
  }

  @override
  bool get isAbstract {
    if (_unlinkedClass != null) {
      return _unlinkedClass.isAbstract;
    }
    return hasModifier(Modifier.ABSTRACT);
  }

  @override
  bool get isEnum => false;

  @override
  bool get isMixinApplication {
    if (_unlinkedClass != null) {
      return _unlinkedClass.isMixinApplication;
    }
    return hasModifier(Modifier.MIXIN_APPLICATION);
  }

  @override
  bool get isOrInheritsProxy =>
      _safeIsOrInheritsProxy(this, new HashSet<ClassElement>());

  @override
  bool get isProxy {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isProxy) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isValidMixin {
    if (!context.analysisOptions.enableSuperMixins) {
      if (hasReferenceToSuper) {
        return false;
      }
      if (!supertype.isObject) {
        return false;
      }
    }
    for (ConstructorElement constructor in constructors) {
      if (!constructor.isSynthetic && !constructor.isFactory) {
        return false;
      }
    }
    return true;
  }

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedClass != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedClass.annotations);
    }
    return super.metadata;
  }

  @override
  List<MethodElement> get methods {
    if (_unlinkedClass != null) {
      _methods ??= _unlinkedClass.executables
          .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
          .map((e) => new MethodElementImpl.forSerialized(e, this))
          .toList(growable: false);
    }
    return _methods ?? const <MethodElement>[];
  }

  /**
   * Set the methods contained in this class to the given [methods].
   */
  void set methods(List<MethodElement> methods) {
    _assertNotResynthesized(_unlinkedClass);
    for (MethodElement method in methods) {
      (method as MethodElementImpl).enclosingElement = this;
    }
    _methods = methods;
  }

  /**
   * Set whether this class is a mixin application.
   */
  void set mixinApplication(bool isMixinApplication) {
    _assertNotResynthesized(_unlinkedClass);
    setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication);
  }

  @override
  List<InterfaceType> get mixins {
    if (_unlinkedClass != null && _mixins == null) {
      ResynthesizerContext context = enclosingUnit.resynthesizerContext;
      _mixins = _unlinkedClass.mixins
          .map((EntityRef t) => context.resolveTypeRef(t, this))
          .where((DartType type) => type is InterfaceType)
          .toList(growable: false);
    }
    return _mixins ?? const <InterfaceType>[];
  }

  void set mixins(List<InterfaceType> mixins) {
    _assertNotResynthesized(_unlinkedClass);
    _mixins = mixins;
  }

  @override
  String get name {
    if (_unlinkedClass != null) {
      return _unlinkedClass.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedClass != null) {
      return _unlinkedClass.nameOffset;
    }
    return offset;
  }

  @override
  InterfaceType get supertype {
    if (_unlinkedClass != null && _supertype == null) {
      if (_unlinkedClass.supertype != null) {
        DartType type = enclosingUnit.resynthesizerContext
            .resolveTypeRef(_unlinkedClass.supertype, this);
        if (type is InterfaceType) {
          _supertype = type;
        } else {
          _supertype = context.typeProvider.objectType;
        }
      } else if (_unlinkedClass.hasNoSupertype) {
        return null;
      } else {
        _supertype = context.typeProvider.objectType;
      }
    }
    return _supertype;
  }

  void set supertype(InterfaceType supertype) {
    _assertNotResynthesized(_unlinkedClass);
    _supertype = supertype;
  }

  @override
  InterfaceType get type {
    if (_type == null) {
      InterfaceTypeImpl type = new InterfaceTypeImpl(this);
      type.typeArguments = typeParameterTypes;
      _type = type;
    }
    return _type;
  }

  @override
  TypeParameterizedElementMixin get typeParameterContext => this;

  @override
  List<TypeParameterElement> get typeParameters {
    if (_unlinkedClass != null) {
      return super.typeParameters;
    }
    return _typeParameters;
  }

  /**
   * Set the type parameters defined for this class to the given
   * [typeParameters].
   */
  void set typeParameters(List<TypeParameterElement> typeParameters) {
    _assertNotResynthesized(_unlinkedClass);
    for (TypeParameterElement typeParameter in typeParameters) {
      (typeParameter as TypeParameterElementImpl).enclosingElement = this;
    }
    this._typeParameters = typeParameters;
  }

  @override
  List<UnlinkedTypeParam> get unlinkedTypeParams =>
      _unlinkedClass.typeParameters;

  @override
  ConstructorElement get unnamedConstructor {
    for (ConstructorElement element in constructors) {
      String name = element.displayName;
      if (name == null || name.isEmpty) {
        return element;
      }
    }
    return null;
  }

  @override
  void appendTo(StringBuffer buffer) {
    if (isAbstract) {
      buffer.write('abstract ');
    }
    buffer.write('class ');
    String name = displayName;
    if (name == null) {
      buffer.write("{unnamed class}");
    } else {
      buffer.write(name);
    }
    int variableCount = typeParameters.length;
    if (variableCount > 0) {
      buffer.write("<");
      for (int i = 0; i < variableCount; i++) {
        if (i > 0) {
          buffer.write(", ");
        }
        (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
      }
      buffer.write(">");
    }
    if (supertype != null && !supertype.isObject) {
      buffer.write(' extends ');
      buffer.write(supertype.displayName);
    }
    if (mixins.isNotEmpty) {
      buffer.write(' with ');
      buffer.write(mixins.map((t) => t.displayName).join(', '));
    }
    if (interfaces.isNotEmpty) {
      buffer.write(' implements ');
      buffer.write(interfaces.map((t) => t.displayName).join(', '));
    }
  }

  @override
  ElementImpl getChild(String identifier) {
    ElementImpl child = super.getChild(identifier);
    if (child != null) {
      return child;
    }
    //
    // The casts in this method are safe because the set methods would have
    // thrown a CCE if any of the elements in the arrays were not of the
    // expected types.
    //
    for (ConstructorElement constructor in _constructors) {
      ConstructorElementImpl constructorImpl = constructor;
      if (constructorImpl.identifier == identifier) {
        return constructorImpl;
      }
    }
    for (MethodElement method in methods) {
      MethodElementImpl methodImpl = method;
      if (methodImpl.identifier == identifier) {
        return methodImpl;
      }
    }
    for (TypeParameterElement typeParameter in typeParameters) {
      TypeParameterElementImpl typeParameterImpl = typeParameter;
      if (typeParameterImpl.identifier == identifier) {
        return typeParameterImpl;
      }
    }
    return null;
  }

  @override
  MethodElement getMethod(String methodName) {
    int length = methods.length;
    for (int i = 0; i < length; i++) {
      MethodElement method = methods[i];
      if (method.name == methodName) {
        return method;
      }
    }
    return null;
  }

  @override
  ConstructorElement getNamedConstructor(String name) {
    for (ConstructorElement element in constructors) {
      String elementName = element.name;
      if (elementName != null && elementName == name) {
        return element;
      }
    }
    return null;
  }

  @override
  bool isSuperConstructorAccessible(ConstructorElement constructor) {
    // If this class has no mixins, then all superclass constructors are
    // accessible.
    if (mixins.isEmpty) {
      return true;
    }
    // Otherwise only constructors that lack optional parameters are
    // accessible (see dartbug.com/19576).
    for (ParameterElement parameter in constructor.parameters) {
      if (parameter.parameterKind != ParameterKind.REQUIRED) {
        return false;
      }
    }
    return true;
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(_constructors, visitor);
    safelyVisitChildren(methods, visitor);
    safelyVisitChildren(_typeParameters, visitor);
  }

  void _collectAllSupertypes(List<InterfaceType> supertypes) {
    List<InterfaceType> typesToVisit = new List<InterfaceType>();
    List<ClassElement> visitedClasses = new List<ClassElement>();
    typesToVisit.add(this.type);
    while (!typesToVisit.isEmpty) {
      InterfaceType currentType = typesToVisit.removeAt(0);
      ClassElement currentElement = currentType.element;
      if (!visitedClasses.contains(currentElement)) {
        visitedClasses.add(currentElement);
        if (!identical(currentType, this.type)) {
          supertypes.add(currentType);
        }
        InterfaceType supertype = currentType.superclass;
        if (supertype != null) {
          typesToVisit.add(supertype);
        }
        for (InterfaceType type in currentElement.interfaces) {
          typesToVisit.add(type);
        }
        for (InterfaceType type in currentElement.mixins) {
          ClassElement element = type.element;
          if (!visitedClasses.contains(element)) {
            supertypes.add(type);
          }
        }
      }
    }
  }

  /**
   * Compute a list of constructors for this class, which is a mixin
   * application.  If specified, [visitedClasses] is a list of the other mixin
   * application classes which have been visited on the way to reaching this
   * one (this is used to detect circularities).
   */
  List<ConstructorElement> _computeMixinAppConstructors(
      [List<ClassElementImpl> visitedClasses = null]) {
    // First get the list of constructors of the superclass which need to be
    // forwarded to this class.
    Iterable<ConstructorElement> constructorsToForward;
    if (supertype == null) {
      // Shouldn't ever happen, since the only class with no supertype is
      // Object, and it isn't a mixin application.  But for safety's sake just
      // assume an empty list.
      assert(false);
      constructorsToForward = <ConstructorElement>[];
    } else if (!supertype.element.isMixinApplication) {
      List<ConstructorElement> superclassConstructors =
          supertype.element.constructors;
      // Filter out any constructors with optional parameters (see
      // dartbug.com/15101).
      constructorsToForward =
          superclassConstructors.where(isSuperConstructorAccessible);
    } else {
      if (visitedClasses == null) {
        visitedClasses = <ClassElementImpl>[this];
      } else {
        if (visitedClasses.contains(this)) {
          // Loop in the class hierarchy.  Don't try to forward any
          // constructors.
          return <ConstructorElement>[];
        }
        visitedClasses.add(this);
      }
      try {
        ClassElementImpl superElement = AbstractClassElementImpl
            .getImpl(supertype.element) as ClassElementImpl;
        constructorsToForward =
            superElement._computeMixinAppConstructors(visitedClasses);
      } finally {
        visitedClasses.removeLast();
      }
    }

    // Figure out the type parameter substitution we need to perform in order
    // to produce constructors for this class.  We want to be robust in the
    // face of errors, so drop any extra type arguments and fill in any missing
    // ones with `dynamic`.
    List<DartType> parameterTypes =
        TypeParameterTypeImpl.getTypes(supertype.typeParameters);
    List<DartType> argumentTypes = new List<DartType>.filled(
        parameterTypes.length, DynamicTypeImpl.instance);
    for (int i = 0; i < supertype.typeArguments.length; i++) {
      if (i >= argumentTypes.length) {
        break;
      }
      argumentTypes[i] = supertype.typeArguments[i];
    }

    // Now create an implicit constructor for every constructor found above,
    // substituting type parameters as appropriate.
    return constructorsToForward
        .map((ConstructorElement superclassConstructor) {
      ConstructorElementImpl implicitConstructor =
          new ConstructorElementImpl(superclassConstructor.name, -1);
      implicitConstructor.synthetic = true;
      implicitConstructor.redirectedConstructor = superclassConstructor;
      List<ParameterElement> superParameters = superclassConstructor.parameters;
      int count = superParameters.length;
      if (count > 0) {
        List<ParameterElement> implicitParameters =
            new List<ParameterElement>(count);
        for (int i = 0; i < count; i++) {
          ParameterElement superParameter = superParameters[i];
          ParameterElementImpl implicitParameter =
              new ParameterElementImpl(superParameter.name, -1);
          implicitParameter.const3 = superParameter.isConst;
          implicitParameter.final2 = superParameter.isFinal;
          implicitParameter.parameterKind = superParameter.parameterKind;
          implicitParameter.synthetic = true;
          implicitParameter.type =
              superParameter.type.substitute2(argumentTypes, parameterTypes);
          implicitParameters[i] = implicitParameter;
        }
        implicitConstructor.parameters = implicitParameters;
      }
      implicitConstructor.enclosingElement = this;
      return implicitConstructor;
    }).toList(growable: false);
  }

  /**
   * Resynthesize explicit fields and property accessors and fill [_fields] and
   * [_accessors] with explicit and implicit elements.
   */
  void _resynthesizeFieldsAndPropertyAccessors() {
    assert(_fields == null);
    assert(_accessors == null);
    // Build explicit fields and implicit property accessors.
    var explicitFields = <FieldElement>[];
    var implicitAccessors = <PropertyAccessorElement>[];
    for (UnlinkedVariable v in _unlinkedClass.fields) {
      FieldElementImpl field =
          new FieldElementImpl.forSerializedFactory(v, this);
      explicitFields.add(field);
      implicitAccessors.add(
          new PropertyAccessorElementImpl_ImplicitGetter(field)
            ..enclosingElement = this);
      if (!field.isConst && !field.isFinal) {
        implicitAccessors.add(
            new PropertyAccessorElementImpl_ImplicitSetter(field)
              ..enclosingElement = this);
      }
    }
    // Build explicit property accessors and implicit fields.
    var explicitAccessors = <PropertyAccessorElement>[];
    var implicitFields = <String, FieldElementImpl>{};
    for (UnlinkedExecutable e in _unlinkedClass.executables) {
      if (e.kind == UnlinkedExecutableKind.getter ||
          e.kind == UnlinkedExecutableKind.setter) {
        PropertyAccessorElementImpl accessor =
            new PropertyAccessorElementImpl.forSerialized(e, this);
        explicitAccessors.add(accessor);
        // Prepare the field type.
        DartType fieldType;
        if (e.kind == UnlinkedExecutableKind.getter) {
          fieldType = accessor.returnType;
        } else {
          fieldType = accessor.parameters[0].type;
        }
        // Create or update the implicit field.
        String fieldName = accessor.displayName;
        FieldElementImpl field = implicitFields[fieldName];
        if (field == null) {
          field = new FieldElementImpl(fieldName, -1);
          implicitFields[fieldName] = field;
          field.enclosingElement = this;
          field.synthetic = true;
          field.final2 = e.kind == UnlinkedExecutableKind.getter;
          field.type = fieldType;
          field.static = e.isStatic;
        } else {
          field.final2 = false;
        }
        accessor.variable = field;
        if (e.kind == UnlinkedExecutableKind.getter) {
          field.getter = accessor;
        } else {
          field.setter = accessor;
        }
      }
    }
    // Combine explicit and implicit fields and property accessors.
    _fields = <FieldElement>[]
      ..addAll(explicitFields)
      ..addAll(implicitFields.values);
    _accessors = <PropertyAccessorElement>[]
      ..addAll(explicitAccessors)
      ..addAll(implicitAccessors);
  }

  bool _safeIsOrInheritsProxy(
      ClassElement element, HashSet<ClassElement> visited) {
    if (visited.contains(element)) {
      return false;
    }
    visited.add(element);
    if (element.isProxy) {
      return true;
    } else if (element.supertype != null &&
        _safeIsOrInheritsProxy(element.supertype.element, visited)) {
      return true;
    }
    List<InterfaceType> supertypes = element.interfaces;
    for (int i = 0; i < supertypes.length; i++) {
      if (_safeIsOrInheritsProxy(supertypes[i].element, visited)) {
        return true;
      }
    }
    supertypes = element.mixins;
    for (int i = 0; i < supertypes.length; i++) {
      if (_safeIsOrInheritsProxy(supertypes[i].element, visited)) {
        return true;
      }
    }
    return false;
  }
}

/**
 * A concrete implementation of a [CompilationUnitElement].
 */
class CompilationUnitElementImpl extends UriReferencedElementImpl
    implements CompilationUnitElement {
  /**
   * The context in which this unit is resynthesized, or `null` if the
   * element is not resynthesized a summary.
   */
  final ResynthesizerContext resynthesizerContext;

  /**
   * The unlinked representation of the unit in the summary.
   */
  final UnlinkedUnit _unlinkedUnit;

  /**
   * The unlinked representation of the part in the summary.
   */
  final UnlinkedPart _unlinkedPart;

  /**
   * The source that corresponds to this compilation unit.
   */
  @override
  Source source;

  /**
   * The source of the library containing this compilation unit.
   *
   * This is the same as the source of the containing [LibraryElement],
   * except that it does not require the containing [LibraryElement] to be
   * computed.
   */
  Source librarySource;

  /**
   * A table mapping the offset of a directive to the annotations associated
   * with that directive, or `null` if none of the annotations in the
   * compilation unit have annotations.
   */
  Map<int, List<ElementAnnotation>> annotationMap = null;

  /**
   * A list containing all of the top-level accessors (getters and setters)
   * contained in this compilation unit.
   */
  List<PropertyAccessorElement> _accessors;

  /**
   * A list containing all of the enums contained in this compilation unit.
   */
  List<ClassElement> _enums;

  /**
   * A list containing all of the top-level functions contained in this
   * compilation unit.
   */
  List<FunctionElement> _functions;

  /**
   * A list containing all of the function type aliases contained in this
   * compilation unit.
   */
  List<FunctionTypeAliasElement> _typeAliases;

  /**
   * A list containing all of the types contained in this compilation unit.
   */
  List<ClassElement> _types;

  /**
   * A list containing all of the variables contained in this compilation unit.
   */
  List<TopLevelVariableElement> _variables;

  /**
   * A map from offsets to elements of this unit at these offsets.
   */
  final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>();

  /**
   * Resynthesized explicit top-level property accessors.
   */
  UnitExplicitTopLevelAccessors _explicitTopLevelAccessors;

  /**
   * Resynthesized explicit top-level variables.
   */
  UnitExplicitTopLevelVariables _explicitTopLevelVariables;

  /**
   * Description of top-level variable replacements that should be applied
   * to implicit top-level variables because of re-linking top-level property
   * accessors between different unit of the same library.
   */
  Map<TopLevelVariableElement, TopLevelVariableElement>
      _topLevelVariableReplaceMap;

  /**
   * Initialize a newly created compilation unit element to have the given
   * [name].
   */
  CompilationUnitElementImpl(String name)
      : resynthesizerContext = null,
        _unlinkedUnit = null,
        _unlinkedPart = null,
        super(name, -1);

  /**
   * Initialize using the given serialized information.
   */
  CompilationUnitElementImpl.forSerialized(
      LibraryElementImpl enclosingLibrary,
      this.resynthesizerContext,
      this._unlinkedUnit,
      this._unlinkedPart,
      String name)
      : super.forSerialized(null) {
    _enclosingElement = enclosingLibrary;
    _name = name;
    _nameOffset = -1;
  }

  @override
  List<PropertyAccessorElement> get accessors {
    if (_unlinkedUnit != null) {
      if (_accessors == null) {
        _explicitTopLevelAccessors ??=
            resynthesizerContext.buildTopLevelAccessors();
        _explicitTopLevelVariables ??=
            resynthesizerContext.buildTopLevelVariables();
        List<PropertyAccessorElementImpl> accessors =
            <PropertyAccessorElementImpl>[];
        accessors.addAll(_explicitTopLevelAccessors.accessors);
        accessors.addAll(_explicitTopLevelVariables.implicitAccessors);
        _accessors = accessors;
      }
    }
    return _accessors ?? PropertyAccessorElement.EMPTY_LIST;
  }

  /**
   * Set the top-level accessors (getters and setters) contained in this
   * compilation unit to the given [accessors].
   */
  void set accessors(List<PropertyAccessorElement> accessors) {
    for (PropertyAccessorElement accessor in accessors) {
      (accessor as PropertyAccessorElementImpl).enclosingElement = this;
    }
    this._accessors = accessors;
  }

  @override
  int get codeLength {
    if (_unlinkedUnit != null) {
      return _unlinkedUnit.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedUnit != null) {
      return _unlinkedUnit.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  LibraryElement get enclosingElement =>
      super.enclosingElement as LibraryElement;

  @override
  CompilationUnitElementImpl get enclosingUnit {
    return this;
  }

  @override
  List<ClassElement> get enums {
    if (_unlinkedUnit != null) {
      _enums ??= _unlinkedUnit.enums
          .map((e) => new EnumElementImpl.forSerialized(e, this))
          .toList(growable: false);
    }
    return _enums ?? const <ClassElement>[];
  }

  /**
   * Set the enums contained in this compilation unit to the given [enums].
   */
  void set enums(List<ClassElement> enums) {
    _assertNotResynthesized(_unlinkedUnit);
    for (ClassElement enumDeclaration in enums) {
      (enumDeclaration as EnumElementImpl).enclosingElement = this;
    }
    this._enums = enums;
  }

  @override
  List<FunctionElement> get functions {
    if (_unlinkedUnit != null) {
      _functions ??= _unlinkedUnit.executables
          .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
          .map((e) => new FunctionElementImpl.forSerialized(e, this))
          .toList(growable: false);
    }
    return _functions ?? const <FunctionElement>[];
  }

  /**
   * Set the top-level functions contained in this compilation unit to the given
   * [functions].
   */
  void set functions(List<FunctionElement> functions) {
    for (FunctionElement function in functions) {
      (function as FunctionElementImpl).enclosingElement = this;
    }
    this._functions = functions;
  }

  @override
  List<FunctionTypeAliasElement> get functionTypeAliases {
    if (_unlinkedUnit != null) {
      _typeAliases ??= _unlinkedUnit.typedefs
          .map((t) => new FunctionTypeAliasElementImpl.forSerialized(t, this))
          .toList(growable: false);
    }
    return _typeAliases ?? const <FunctionTypeAliasElement>[];
  }

  @override
  int get hashCode => source.hashCode;

  @override
  bool get hasLoadLibraryFunction {
    List<FunctionElement> functions = this.functions;
    for (int i = 0; i < functions.length; i++) {
      if (functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) {
        return true;
      }
    }
    return false;
  }

  @override
  String get identifier => source.encoding;

  @override
  ElementKind get kind => ElementKind.COMPILATION_UNIT;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedPart != null) {
      return _metadata ??= _buildAnnotations(
          library.definingCompilationUnit as CompilationUnitElementImpl,
          _unlinkedPart.annotations);
    }
    return super.metadata;
  }

  @override
  List<TopLevelVariableElement> get topLevelVariables {
    if (_unlinkedUnit != null) {
      if (_variables == null) {
        _explicitTopLevelAccessors ??=
            resynthesizerContext.buildTopLevelAccessors();
        _explicitTopLevelVariables ??=
            resynthesizerContext.buildTopLevelVariables();
        List<TopLevelVariableElementImpl> variables =
            <TopLevelVariableElementImpl>[];
        variables.addAll(_explicitTopLevelVariables.variables);
        variables.addAll(_explicitTopLevelAccessors.implicitVariables);
        // Ensure that getters and setters in different units use
        // the same top-level variables.
        (enclosingElement as LibraryElementImpl)
            .resynthesizerContext
            .patchTopLevelAccessors();
        _variables = variables;
        _topLevelVariableReplaceMap?.forEach((from, to) {
          int index = _variables.indexOf(from);
          _variables[index] = to;
        });
        _topLevelVariableReplaceMap = null;
      }
    }
    return _variables ?? TopLevelVariableElement.EMPTY_LIST;
  }

  /**
   * Set the top-level variables contained in this compilation unit to the given
   * [variables].
   */
  void set topLevelVariables(List<TopLevelVariableElement> variables) {
    assert(!isResynthesized);
    for (TopLevelVariableElement field in variables) {
      (field as TopLevelVariableElementImpl).enclosingElement = this;
    }
    this._variables = variables;
  }

  /**
   * Set the function type aliases contained in this compilation unit to the
   * given [typeAliases].
   */
  void set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
    _assertNotResynthesized(_unlinkedUnit);
    for (FunctionTypeAliasElement typeAlias in typeAliases) {
      (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this;
    }
    this._typeAliases = typeAliases;
  }

  @override
  TypeParameterizedElementMixin get typeParameterContext => null;

  @override
  List<ClassElement> get types {
    if (_unlinkedUnit != null) {
      _types ??= _unlinkedUnit.classes
          .map((c) => new ClassElementImpl.forSerialized(c, this))
          .toList(growable: false);
    }
    return _types ?? const <ClassElement>[];
  }

  /**
   * Set the types contained in this compilation unit to the given [types].
   */
  void set types(List<ClassElement> types) {
    _assertNotResynthesized(_unlinkedUnit);
    for (ClassElement type in types) {
      // Another implementation of ClassElement is _DeferredClassElement,
      // which is used to resynthesize classes lazily. We cannot cast it
      // to ClassElementImpl, and it already can provide correct values of the
      // 'enclosingElement' property.
      if (type is ClassElementImpl) {
        type.enclosingElement = this;
      }
    }
    this._types = types;
  }

  @override
  bool operator ==(Object object) =>
      object is CompilationUnitElementImpl && source == object.source;

  @override
  accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this);

  /**
   * This method is invoked after this unit was incrementally resolved.
   */
  void afterIncrementalResolution() {
    _offsetToElementMap.clear();
  }

  @override
  void appendTo(StringBuffer buffer) {
    if (source == null) {
      buffer.write("{compilation unit}");
    } else {
      buffer.write(source.fullName);
    }
  }

  @override
  CompilationUnit computeNode() => unit;

  /**
   * Return the annotations associated with the directive at the given [offset],
   * or an empty list if the directive has no annotations or if there is no
   * directive at the given offset.
   */
  List<ElementAnnotation> getAnnotations(int offset) {
    if (annotationMap == null) {
      return const <ElementAnnotation>[];
    }
    return annotationMap[offset] ?? const <ElementAnnotation>[];
  }

  @override
  ElementImpl getChild(String identifier) {
    //
    // The casts in this method are safe because the set methods would have
    // thrown a CCE if any of the elements in the arrays were not of the
    // expected types.
    //
    for (PropertyAccessorElement accessor in accessors) {
      PropertyAccessorElementImpl accessorImpl = accessor;
      if (accessorImpl.identifier == identifier) {
        return accessorImpl;
      }
    }
    for (TopLevelVariableElement variable in topLevelVariables) {
      TopLevelVariableElementImpl variableImpl = variable;
      if (variableImpl.identifier == identifier) {
        return variableImpl;
      }
    }
    for (FunctionElement function in functions) {
      FunctionElementImpl functionImpl = function;
      if (functionImpl.identifier == identifier) {
        return functionImpl;
      }
    }
    for (FunctionTypeAliasElement typeAlias in functionTypeAliases) {
      FunctionTypeAliasElementImpl typeAliasImpl = typeAlias;
      if (typeAliasImpl.identifier == identifier) {
        return typeAliasImpl;
      }
    }
    for (ClassElement type in types) {
      ClassElementImpl typeImpl = type;
      if (typeImpl.name == identifier) {
        return typeImpl;
      }
    }
    for (ClassElement type in _enums) {
      EnumElementImpl typeImpl = type;
      if (typeImpl.identifier == identifier) {
        return typeImpl;
      }
    }
    return null;
  }

  @override
  Element getElementAt(int offset) {
    if (_offsetToElementMap.isEmpty) {
      accept(new _BuildOffsetToElementMap(_offsetToElementMap));
    }
    return _offsetToElementMap[offset];
  }

  @override
  ClassElement getEnum(String enumName) {
    for (ClassElement enumDeclaration in _enums) {
      if (enumDeclaration.name == enumName) {
        return enumDeclaration;
      }
    }
    return null;
  }

  @override
  ClassElement getType(String className) {
    for (ClassElement type in types) {
      if (type.name == className) {
        return type;
      }
    }
    return null;
  }

  /**
   * Replace the given [from] top-level variable with [to] in this compilation unit.
   */
  void replaceTopLevelVariable(
      TopLevelVariableElement from, TopLevelVariableElement to) {
    if (_unlinkedUnit != null) {
      // Getters and setter in different units should be patched to use the
      // same variables before these variables were asked and returned.
      assert(_variables == null);
      _topLevelVariableReplaceMap ??=
          <TopLevelVariableElement, TopLevelVariableElement>{};
      _topLevelVariableReplaceMap[from] = to;
    } else {
      int index = _variables.indexOf(from);
      _variables[index] = to;
    }
  }

  /**
   * Set the annotations associated with the directive at the given [offset] to
   * the given list of [annotations].
   */
  void setAnnotations(int offset, List<ElementAnnotation> annotations) {
    annotationMap ??= new HashMap<int, List<ElementAnnotation>>();
    annotationMap[offset] = annotations;
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(accessors, visitor);
    safelyVisitChildren(_enums, visitor);
    safelyVisitChildren(functions, visitor);
    safelyVisitChildren(functionTypeAliases, visitor);
    safelyVisitChildren(types, visitor);
    safelyVisitChildren(topLevelVariables, visitor);
  }
}

/**
 * A [FieldElement] for a 'const' or 'final' field that has an initializer.
 *
 * TODO(paulberry): we should rename this class to reflect the fact that it's
 * used for both const and final fields.  However, we shouldn't do so until
 * we've created an API for reading the values of constants; until that API is
 * available, clients are likely to read constant values by casting to
 * ConstFieldElementImpl, so it would be a breaking change to rename this
 * class.
 */
class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement {
  /**
   * Initialize a newly created synthetic field element to have the given
   * [name] and [offset].
   */
  ConstFieldElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created field element to have the given [name].
   */
  ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ConstFieldElementImpl.forSerialized(
      UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedVariable, enclosingElement);
}

/**
 * A field element representing an enum constant.
 */
class ConstFieldElementImpl_EnumValue extends ConstFieldElementImpl_ofEnum {
  final UnlinkedEnumValue _unlinkedEnumValue;
  final int _index;

  ConstFieldElementImpl_EnumValue(
      EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
      : super(enumElement);

  @override
  String get documentationComment {
    if (_unlinkedEnumValue != null) {
      return _unlinkedEnumValue?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  @override
  EvaluationResultImpl get evaluationResult {
    if (_evaluationResult == null) {
      Map<String, DartObjectImpl> fieldMap = <String, DartObjectImpl>{
        name: new DartObjectImpl(
            context.typeProvider.intType, new IntState(_index))
      };
      DartObjectImpl value =
          new DartObjectImpl(type, new GenericState(fieldMap));
      _evaluationResult = new EvaluationResultImpl(value);
    }
    return _evaluationResult;
  }

  @override
  String get name {
    if (_unlinkedEnumValue != null) {
      return _unlinkedEnumValue.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == -1 && _unlinkedEnumValue != null) {
      return _unlinkedEnumValue.nameOffset;
    }
    return offset;
  }

  @override
  InterfaceType get type => _enum.type;
}

/**
 * The synthetic `values` field of an enum.
 */
class ConstFieldElementImpl_EnumValues extends ConstFieldElementImpl_ofEnum {
  ConstFieldElementImpl_EnumValues(EnumElementImpl enumElement)
      : super(enumElement) {
    synthetic = true;
  }

  @override
  EvaluationResultImpl get evaluationResult {
    if (_evaluationResult == null) {
      List<DartObjectImpl> constantValues = <DartObjectImpl>[];
      for (FieldElement field in _enum.fields) {
        if (field is ConstFieldElementImpl_EnumValue) {
          constantValues.add(field.evaluationResult.value);
        }
      }
      _evaluationResult = new EvaluationResultImpl(
          new DartObjectImpl(type, new ListState(constantValues)));
    }
    return _evaluationResult;
  }

  @override
  String get name => 'values';

  @override
  InterfaceType get type {
    if (_type == null) {
      InterfaceType listType = context.typeProvider.listType;
      return _type = listType.instantiate(<DartType>[_enum.type]);
    }
    return _type;
  }
}

/**
 * An abstract constant field of an enum.
 */
abstract class ConstFieldElementImpl_ofEnum extends ConstFieldElementImpl {
  final EnumElementImpl _enum;

  ConstFieldElementImpl_ofEnum(this._enum) : super(null, -1) {
    enclosingElement = _enum;
  }

  @override
  void set const3(bool isConst) {
    assert(false);
  }

  @override
  void set evaluationResult(_) {
    assert(false);
  }

  @override
  void set final2(bool isFinal) {
    assert(false);
  }

  @override
  bool get isConst => true;

  @override
  bool get isStatic => true;

  @override
  void set static(bool isStatic) {
    assert(false);
  }

  void set type(DartType type) {
    assert(false);
  }
}

/**
 * A [LocalVariableElement] for a local 'const' variable that has an
 * initializer.
 */
class ConstLocalVariableElementImpl extends LocalVariableElementImpl
    with ConstVariableElement {
  /**
   * Initialize a newly created local variable element to have the given [name]
   * and [offset].
   */
  ConstLocalVariableElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created local variable element to have the given [name].
   */
  ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ConstLocalVariableElementImpl.forSerialized(UnlinkedVariable unlinkedVariable,
      ExecutableElementImpl enclosingExecutable)
      : super.forSerialized(unlinkedVariable, enclosingExecutable);
}

/**
 * A concrete implementation of a [ConstructorElement].
 */
class ConstructorElementImpl extends ExecutableElementImpl
    implements ConstructorElement {
  /**
   * The constructor to which this constructor is redirecting.
   */
  ConstructorElement _redirectedConstructor;

  /**
   * The initializers for this constructor (used for evaluating constant
   * instance creation expressions).
   */
  List<ConstructorInitializer> _constantInitializers;

  /**
   * The offset of the `.` before this constructor name or `null` if not named.
   */
  int _periodOffset;

  /**
   * Return the offset of the character immediately following the last character
   * of this constructor's name, or `null` if not named.
   */
  int _nameEnd;

  /**
   * True if this constructor has been found by constant evaluation to be free
   * of redirect cycles, and is thus safe to evaluate.
   */
  bool _isCycleFree = false;

  /**
   * Initialize a newly created constructor element to have the given [name] and
   * [offset].
   */
  ConstructorElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created constructor element to have the given [name].
   */
  ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ConstructorElementImpl.forSerialized(
      UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
      : super.forSerialized(serializedExecutable, enclosingClass);

  /**
   * Set whether this constructor represents a 'const' constructor.
   */
  void set const2(bool isConst) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.CONST, isConst);
  }

  List<ConstructorInitializer> get constantInitializers {
    if (serializedExecutable != null && _constantInitializers == null) {
      _constantInitializers ??= serializedExecutable.constantInitializers
          .map((i) => _buildConstructorInitializer(i))
          .toList(growable: false);
    }
    return _constantInitializers;
  }

  void set constantInitializers(
      List<ConstructorInitializer> constantInitializers) {
    _assertNotResynthesized(serializedExecutable);
    _constantInitializers = constantInitializers;
  }

  @override
  ClassElementImpl get enclosingElement =>
      super.enclosingElement as ClassElementImpl;

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
      super.enclosingElement as ClassElementImpl;

  /**
   * Set whether this constructor represents a factory method.
   */
  void set factory(bool isFactory) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.FACTORY, isFactory);
  }

  @override
  bool get isConst {
    if (serializedExecutable != null) {
      return serializedExecutable.isConst;
    }
    return hasModifier(Modifier.CONST);
  }

  bool get isCycleFree {
    if (serializedExecutable != null) {
      return serializedExecutable.isConst &&
          !enclosingUnit.resynthesizerContext
              .isInConstCycle(serializedExecutable.constCycleSlot);
    }
    return _isCycleFree;
  }

  void set isCycleFree(bool isCycleFree) {
    // This property is updated in ConstantEvaluationEngine even for
    // resynthesized constructors, so we don't have the usual assert here.
    _isCycleFree = isCycleFree;
  }

  @override
  bool get isDefaultConstructor {
    // unnamed
    String name = this.name;
    if (name != null && name.length != 0) {
      return false;
    }
    // no required parameters
    for (ParameterElement parameter in parameters) {
      if (parameter.parameterKind == ParameterKind.REQUIRED) {
        return false;
      }
    }
    // OK, can be used as default constructor
    return true;
  }

  @override
  bool get isFactory {
    if (serializedExecutable != null) {
      return serializedExecutable.isFactory;
    }
    return hasModifier(Modifier.FACTORY);
  }

  @override
  bool get isStatic => false;

  @override
  ElementKind get kind => ElementKind.CONSTRUCTOR;

  @override
  int get nameEnd {
    if (serializedExecutable != null) {
      if (serializedExecutable.name.isNotEmpty) {
        return serializedExecutable.nameEnd;
      } else {
        return serializedExecutable.nameOffset + enclosingElement.name.length;
      }
    }
    return _nameEnd;
  }

  void set nameEnd(int nameEnd) {
    _assertNotResynthesized(serializedExecutable);
    _nameEnd = nameEnd;
  }

  @override
  int get periodOffset {
    if (serializedExecutable != null) {
      if (serializedExecutable.name.isNotEmpty) {
        return serializedExecutable.periodOffset;
      }
    }
    return _periodOffset;
  }

  void set periodOffset(int periodOffset) {
    _assertNotResynthesized(serializedExecutable);
    _periodOffset = periodOffset;
  }

  @override
  ConstructorElement get redirectedConstructor {
    if (serializedExecutable != null && _redirectedConstructor == null) {
      if (serializedExecutable.isRedirectedConstructor) {
        if (serializedExecutable.isFactory) {
          _redirectedConstructor = enclosingUnit.resynthesizerContext
              .resolveConstructorRef(
                  enclosingElement, serializedExecutable.redirectedConstructor);
        } else {
          _redirectedConstructor = enclosingElement.getNamedConstructor(
              serializedExecutable.redirectedConstructorName);
        }
      } else {
        return null;
      }
    }
    return _redirectedConstructor;
  }

  void set redirectedConstructor(ConstructorElement redirectedConstructor) {
    _assertNotResynthesized(serializedExecutable);
    _redirectedConstructor = redirectedConstructor;
  }

  @override
  DartType get returnType => enclosingElement.type;

  void set returnType(DartType returnType) {
    assert(false);
  }

  @override
  FunctionType get type {
    return _type ??= new FunctionTypeImpl(this);
  }

  void set type(FunctionType type) {
    assert(false);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    if (enclosingElement == null) {
      String message;
      String name = displayName;
      if (name != null && !name.isEmpty) {
        message =
            'Found constructor element named $name with no enclosing element';
      } else {
        message = 'Found unnamed constructor element with no enclosing element';
      }
      AnalysisEngine.instance.logger.logError(message);
      buffer.write('<unknown class>');
    } else {
      buffer.write(enclosingElement.displayName);
    }
    String name = displayName;
    if (name != null && !name.isEmpty) {
      buffer.write(".");
      buffer.write(name);
    }
    super.appendTo(buffer);
  }

  @override
  ConstructorDeclaration computeNode() =>
      getNodeMatching((node) => node is ConstructorDeclaration);

  /**
   * Resynthesize the AST for the given serialized constructor initializer.
   */
  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 = enclosingUnit.resynthesizerContext
            .buildExpression(this, 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:
        ConstructorFieldInitializer initializer =
            AstFactory.constructorFieldInitializer(
                false,
                name,
                enclosingUnit.resynthesizerContext
                    .buildExpression(this, serialized.expression));
        initializer.fieldName.staticElement = enclosingElement.getField(name);
        return initializer;
      case UnlinkedConstructorInitializerKind.superInvocation:
        SuperConstructorInvocation initializer =
            AstFactory.superConstructorInvocation2(
                name.isNotEmpty ? name : null, arguments);
        ClassElement superElement = enclosingElement.supertype.element;
        ConstructorElement element = name.isEmpty
            ? superElement.unnamedConstructor
            : superElement.getNamedConstructor(name);
        initializer.staticElement = element;
        initializer.constructorName?.staticElement = element;
        return initializer;
      case UnlinkedConstructorInitializerKind.thisInvocation:
        RedirectingConstructorInvocation initializer =
            AstFactory.redirectingConstructorInvocation2(
                name.isNotEmpty ? name : null, arguments);
        ConstructorElement element = name.isEmpty
            ? enclosingElement.unnamedConstructor
            : enclosingElement.getNamedConstructor(name);
        initializer.staticElement = element;
        initializer.constructorName?.staticElement = element;
        return initializer;
    }
    return null;
  }
}

/**
 * A [TopLevelVariableElement] for a top-level 'const' variable that has an
 * initializer.
 */
class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
    with ConstVariableElement {
  /**
   * Initialize a newly created synthetic top-level variable element to have the
   * given [name] and [offset].
   */
  ConstTopLevelVariableElementImpl(String name, int offset)
      : super(name, offset);

  /**
   * Initialize a newly created top-level variable element to have the given
   * [name].
   */
  ConstTopLevelVariableElementImpl.forNode(Identifier name)
      : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ConstTopLevelVariableElementImpl.forSerialized(
      UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedVariable, enclosingElement);
}

/**
 * Mixin used by elements that represent constant variables and have
 * initializers.
 *
 * Note that in correct Dart code, all constant variables must have
 * initializers.  However, analyzer also needs to handle incorrect Dart code,
 * in which case there might be some constant variables that lack initializers.
 * This interface is only used for constant variables that have initializers.
 *
 * This class is not intended to be part of the public API for analyzer.
 */
abstract class ConstVariableElement
    implements ElementImpl, ConstantEvaluationTarget {
  /**
   * If this element represents a constant variable, and it has an initializer,
   * a copy of the initializer for the constant.  Otherwise `null`.
   *
   * Note that in correct Dart code, all constant variables must have
   * initializers.  However, analyzer also needs to handle incorrect Dart code,
   * in which case there might be some constant variables that lack
   * initializers.
   */
  Expression _constantInitializer;

  EvaluationResultImpl _evaluationResult;

  Expression get constantInitializer {
    if (_constantInitializer == null && _unlinkedConst != null) {
      _constantInitializer = enclosingUnit.resynthesizerContext
          .buildExpression(this, _unlinkedConst);
    }
    return _constantInitializer;
  }

  void set constantInitializer(Expression constantInitializer) {
    _assertNotResynthesized(_unlinkedConst);
    _constantInitializer = constantInitializer;
  }

  EvaluationResultImpl get evaluationResult => _evaluationResult;

  void set evaluationResult(EvaluationResultImpl evaluationResult) {
    _evaluationResult = evaluationResult;
  }

  /**
   * If this element is resynthesized from the summary, return the unlinked
   * initializer, otherwise return `null`.
   */
  UnlinkedConst get _unlinkedConst;

  /**
   * Return a representation of the value of this variable, forcing the value
   * to be computed if it had not previously been computed, or `null` if either
   * this variable was not declared with the 'const' modifier or if the value of
   * this variable could not be computed because of errors.
   */
  DartObject computeConstantValue() {
    if (evaluationResult == null) {
      context?.computeResult(this, CONSTANT_VALUE);
    }
    return evaluationResult?.value;
  }
}

/**
 * A [FieldFormalParameterElementImpl] for parameters that have an initializer.
 */
class DefaultFieldFormalParameterElementImpl
    extends FieldFormalParameterElementImpl with ConstVariableElement {
  /**
   * Initialize a newly created parameter element to have the given [name] and
   * [nameOffset].
   */
  DefaultFieldFormalParameterElementImpl(String name, int nameOffset)
      : super(name, nameOffset);

  /**
   * Initialize a newly created parameter element to have the given [name].
   */
  DefaultFieldFormalParameterElementImpl.forNode(Identifier name)
      : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  DefaultFieldFormalParameterElementImpl.forSerialized(
      UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedParam, enclosingElement);
}

/**
 * A [ParameterElement] for parameters that have an initializer.
 */
class DefaultParameterElementImpl extends ParameterElementImpl
    with ConstVariableElement {
  /**
   * Initialize a newly created parameter element to have the given [name] and
   * [nameOffset].
   */
  DefaultParameterElementImpl(String name, int nameOffset)
      : super(name, nameOffset);

  /**
   * Initialize a newly created parameter element to have the given [name].
   */
  DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  DefaultParameterElementImpl.forSerialized(
      UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedParam, enclosingElement);

  @override
  DefaultFormalParameter computeNode() =>
      getNodeMatching((node) => node is DefaultFormalParameter);
}

/**
 * The synthetic element representing the declaration of the type `dynamic`.
 */
class DynamicElementImpl extends ElementImpl implements TypeDefiningElement {
  /**
   * Return the unique instance of this class.
   */
  static DynamicElementImpl get instance =>
      DynamicTypeImpl.instance.element as DynamicElementImpl;

  @override
  DynamicTypeImpl type;

  /**
   * Initialize a newly created instance of this class. Instances of this class
   * should <b>not</b> be created except as part of creating the type associated
   * with this element. The single instance of this class should be accessed
   * through the method [instance].
   */
  DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) {
    setModifier(Modifier.SYNTHETIC, true);
  }

  @override
  ElementKind get kind => ElementKind.DYNAMIC;

  @override
  accept(ElementVisitor visitor) => null;
}

/**
 * A concrete implementation of an [ElementAnnotation].
 */
class ElementAnnotationImpl implements ElementAnnotation {
  /**
   * The name of the top-level variable used to mark a method parameter as
   * covariant.
   */
  static String _COVARIANT_VARIABLE_NAME = "checked";

  /**
   * The name of the class used to mark an element as being deprecated.
   */
  static String _DEPRECATED_CLASS_NAME = "Deprecated";

  /**
   * The name of the top-level variable used to mark an element as being
   * deprecated.
   */
  static String _DEPRECATED_VARIABLE_NAME = "deprecated";

  /**
   * The name of the top-level variable used to mark a method as being a
   * factory.
   */
  static String _FACTORY_VARIABLE_NAME = "factory";

  /**
   * The name of the class used to JS annotate an element.
   */
  static String _JS_CLASS_NAME = "JS";

  /**
   * The name of `js` library, used to define JS annotations.
   */
  static String _JS_LIB_NAME = "js";

  /**
   * The name of `meta` library, used to define analysis annotations.
   */
  static String _META_LIB_NAME = "meta";

  /**
   * The name of the top-level variable used to mark a method as requiring
   * overriders to call super.
   */
  static String _MUST_CALL_SUPER_VARIABLE_NAME = "mustCallSuper";

  /**
   * The name of the top-level variable used to mark a method as being expected
   * to override an inherited method.
   */
  static String _OVERRIDE_VARIABLE_NAME = "override";

  /**
   * The name of the top-level variable used to mark a method as being
   * protected.
   */
  static String _PROTECTED_VARIABLE_NAME = "protected";

  /**
   * The name of the top-level variable used to mark a class as implementing a
   * proxy object.
   */
  static String PROXY_VARIABLE_NAME = "proxy";

  /**
   * The name of the class used to mark a parameter as being required.
   */
  static String _REQUIRED_CLASS_NAME = "Required";

  /**
   * The name of the top-level variable used to mark a parameter as being
   * required.
   */
  static String _REQUIRED_VARIABLE_NAME = "required";

  /**
   * The name of the top-level variable used to mark a member as intended to be
   * overridden.
   */
  static String _VIRTUAL_VARIABLE_NAME = "virtual";

  /**
   * The element representing the field, variable, or constructor being used as
   * an annotation.
   */
  Element element;

  /**
   * The compilation unit in which this annotation appears.
   */
  CompilationUnitElementImpl compilationUnit;

  /**
   * The AST of the annotation itself, cloned from the resolved AST for the
   * source code.
   */
  Annotation annotationAst;

  /**
   * The result of evaluating this annotation as a compile-time constant
   * expression, or `null` if the compilation unit containing the variable has
   * not been resolved.
   */
  EvaluationResultImpl evaluationResult;

  /**
   * Initialize a newly created annotation. The given [compilationUnit] is the
   * compilation unit in which the annotation appears.
   */
  ElementAnnotationImpl(this.compilationUnit);

  @override
  DartObject get constantValue => evaluationResult?.value;

  @override
  AnalysisContext get context => compilationUnit.library.context;

  /**
   * Return `true` if this annotation marks the associated parameter as being
   * covariant, meaning it is allowed to have a narrower type in an override.
   */
  bool get isCovariant =>
      element is PropertyAccessorElement &&
      element.name == _COVARIANT_VARIABLE_NAME &&
      element.library?.name == _META_LIB_NAME;

  @override
  bool get isDeprecated {
    if (element?.library?.isDartCore == true) {
      if (element is ConstructorElement) {
        return element.enclosingElement.name == _DEPRECATED_CLASS_NAME;
      } else if (element is PropertyAccessorElement) {
        return element.name == _DEPRECATED_VARIABLE_NAME;
      }
    }
    return false;
  }

  @override
  bool get isFactory =>
      element is PropertyAccessorElement &&
      element.name == _FACTORY_VARIABLE_NAME &&
      element.library?.name == _META_LIB_NAME;

  @override
  bool get isJS =>
      element is ConstructorElement &&
      element.enclosingElement.name == _JS_CLASS_NAME &&
      element.library?.name == _JS_LIB_NAME;

  @override
  bool get isMustCallSuper =>
      element is PropertyAccessorElement &&
      element.name == _MUST_CALL_SUPER_VARIABLE_NAME &&
      element.library?.name == _META_LIB_NAME;

  @override
  bool get isOverride =>
      element is PropertyAccessorElement &&
      element.name == _OVERRIDE_VARIABLE_NAME &&
      element.library?.isDartCore == true;

  @override
  bool get isProtected =>
      element is PropertyAccessorElement &&
      element.name == _PROTECTED_VARIABLE_NAME &&
      element.library?.name == _META_LIB_NAME;

  @override
  bool get isProxy =>
      element is PropertyAccessorElement &&
      element.name == PROXY_VARIABLE_NAME &&
      element.library?.isDartCore == true;

  @override
  bool get isRequired =>
      element is ConstructorElement &&
          element.enclosingElement.name == _REQUIRED_CLASS_NAME &&
          element.library?.name == _META_LIB_NAME ||
      element is PropertyAccessorElement &&
          element.name == _REQUIRED_VARIABLE_NAME &&
          element.library?.name == _META_LIB_NAME;

  /**
   * Return `true` if this annotation marks the associated member as supporting
   * overrides.
   *
   * This is currently used by fields in Strong Mode, as other members are
   * already virtual-by-default.
   */
  bool get isVirtual =>
      element is PropertyAccessorElement &&
      element.name == _VIRTUAL_VARIABLE_NAME &&
      element.library?.name == _META_LIB_NAME;

  /**
   * Get the library containing this annotation.
   */
  Source get librarySource => compilationUnit.librarySource;

  @override
  Source get source => compilationUnit.source;

  @override
  DartObject computeConstantValue() {
    if (evaluationResult == null) {
      context?.computeResult(this, CONSTANT_VALUE);
    }
    return constantValue;
  }

  @override
  String toString() => '@$element';
}

/**
 * A base class for concrete implementations of an [Element].
 */
abstract class ElementImpl implements Element {
  /**
   * An Unicode right arrow.
   */
  static final String RIGHT_ARROW = " \u2192 ";

  static int _NEXT_ID = 0;

  final int id = _NEXT_ID++;

  /**
   * The enclosing element of this element, or `null` if this element is at the
   * root of the element structure.
   */
  ElementImpl _enclosingElement;

  /**
   * The name of this element.
   */
  String _name;

  /**
   * The offset of the name of this element in the file that contains the
   * declaration of this element.
   */
  int _nameOffset = 0;

  /**
   * A bit-encoded form of the modifiers associated with this element.
   */
  int _modifiers = 0;

  /**
   * A list containing all of the metadata associated with this element.
   */
  List<ElementAnnotation> _metadata;

  /**
   * A cached copy of the calculated hashCode for this element.
   */
  int _cachedHashCode;

  /**
   * A cached copy of the calculated location for this element.
   */
  ElementLocation _cachedLocation;

  /**
   * The documentation comment for this element.
   */
  String _docComment;

  /**
   * The offset of the beginning of the element's code in the file that contains
   * the element, or `null` if the element is synthetic.
   */
  int _codeOffset;

  /**
   * The length of the element's code, or `null` if the element is synthetic.
   */
  int _codeLength;

  /**
   * Initialize a newly created element to have the given [name] at the given
   * [_nameOffset].
   */
  ElementImpl(String name, this._nameOffset) {
    this._name = StringUtilities.intern(name);
  }

  /**
   * Initialize a newly created element to have the given [name].
   */
  ElementImpl.forNode(Identifier name)
      : this(name == null ? "" : name.name, name == null ? -1 : name.offset);

  /**
   * Initialize from serialized information.
   */
  ElementImpl.forSerialized(this._enclosingElement);

  /**
   * The length of the element's code, or `null` if the element is synthetic.
   */
  int get codeLength => _codeLength;

  /**
   * The offset of the beginning of the element's code in the file that contains
   * the element, or `null` if the element is synthetic.
   */
  int get codeOffset => _codeOffset;

  @override
  AnalysisContext get context {
    if (_enclosingElement == null) {
      return null;
    }
    return _enclosingElement.context;
  }

  @override
  String get displayName => _name;

  @override
  String get documentationComment => _docComment;

  /**
   * The documentation comment source for this element.
   */
  void set documentationComment(String doc) {
    assert(!isResynthesized);
    _docComment = doc?.replaceAll('\r\n', '\n');
  }

  @override
  Element get enclosingElement => _enclosingElement;

  /**
   * Set the enclosing element of this element to the given [element].
   *
   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
   */
  void set enclosingElement(Element element) {
    _enclosingElement = element as ElementImpl;
  }

  /**
   * Return the enclosing unit element (which might be the same as `this`), or
   * `null` if this element is not contained in any compilation unit.
   */
  CompilationUnitElementImpl get enclosingUnit {
    return _enclosingElement?.enclosingUnit;
  }

  @override
  int get hashCode {
    // TODO: We might want to re-visit this optimization in the future.
    // We cache the hash code value as this is a very frequently called method.
    if (_cachedHashCode == null) {
      _cachedHashCode = location.hashCode;
    }
    return _cachedHashCode;
  }

  /**
   * Return an identifier that uniquely identifies this element among the
   * children of this element's parent.
   */
  String get identifier => name;

  @override
  bool get isDeprecated {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isDeprecated) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isFactory {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isFactory) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isJS {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isJS) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isOverride {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isOverride) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isPrivate {
    String name = displayName;
    if (name == null) {
      return true;
    }
    return Identifier.isPrivateName(name);
  }

  @override
  bool get isProtected {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isProtected) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isPublic => !isPrivate;

  @override
  bool get isRequired {
    for (ElementAnnotation annotation in metadata) {
      if (annotation.isRequired) {
        return true;
      }
    }
    return false;
  }

  /**
   * Return `true` if this element is resynthesized from a summary.
   */
  bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;

  @override
  bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);

  @override
  LibraryElement get library =>
      getAncestor((element) => element is LibraryElement);

  @override
  Source get librarySource => library?.source;

  @override
  ElementLocation get location {
    if (_cachedLocation == null) {
      if (library == null) {
        return new ElementLocationImpl.con1(this);
      }
      _cachedLocation = new ElementLocationImpl.con1(this);
    }
    return _cachedLocation;
  }

  List<ElementAnnotation> get metadata {
    return _metadata ?? const <ElementAnnotation>[];
  }

  void set metadata(List<ElementAnnotation> metadata) {
    assert(!isResynthesized);
    _metadata = metadata;
  }

  @override
  String get name => _name;

  /**
   * Changes the name of this element.
   *
   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
   */
  void set name(String name) {
    this._name = name;
  }

  @override
  int get nameLength => displayName != null ? displayName.length : 0;

  @override
  int get nameOffset => _nameOffset;

  /**
   * Sets the offset of the name of this element in the file that contains the
   * declaration of this element.
   *
   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
   */
  void set nameOffset(int offset) {
    _nameOffset = offset;
  }

  @override
  Source get source {
    if (_enclosingElement == null) {
      return null;
    }
    return _enclosingElement.source;
  }

  /**
   * Set whether this element is synthetic.
   */
  void set synthetic(bool isSynthetic) {
    setModifier(Modifier.SYNTHETIC, isSynthetic);
  }

  /**
   * Return the context to resolve type parameters in, or `null` if neither this
   * element nor any of its ancestors is of a kind that can declare type
   * parameters.
   */
  TypeParameterizedElementMixin get typeParameterContext {
    return _enclosingElement?.typeParameterContext;
  }

  @override
  CompilationUnit get unit => context.resolveCompilationUnit(source, library);

  @override
  bool operator ==(Object object) {
    if (identical(this, object)) {
      return true;
    }
    return object is Element &&
        object.kind == kind &&
        object.location == location;
  }

  /**
   * Append to the given [buffer] a comma-separated list of the names of the
   * types of this element and every enclosing element.
   */
  void appendPathTo(StringBuffer buffer) {
    Element element = this;
    while (element != null) {
      if (element != this) {
        buffer.write(', ');
      }
      buffer.write(element.runtimeType);
      String name = element.name;
      if (name != null) {
        buffer.write(' (');
        buffer.write(name);
        buffer.write(')');
      }
      element = element.enclosingElement;
    }
  }

  /**
   * Append a textual representation of this element to the given [buffer].
   */
  void appendTo(StringBuffer buffer) {
    if (_name == null) {
      buffer.write("<unnamed ");
      buffer.write(runtimeType.toString());
      buffer.write(">");
    } else {
      buffer.write(_name);
    }
  }

  @override
  String computeDocumentationComment() => documentationComment;

  @override
  AstNode computeNode() => getNodeMatching((node) => node is AstNode);

  /**
   * Set this element as the enclosing element for given [element].
   */
  void encloseElement(ElementImpl element) {
    element.enclosingElement = this;
  }

  @override
  Element/*=E*/ getAncestor/*<E extends Element >*/(
      Predicate<Element> predicate) {
    Element ancestor = _enclosingElement;
    while (ancestor != null && !predicate(ancestor)) {
      ancestor = ancestor.enclosingElement;
    }
    return ancestor as Element/*=E*/;
  }

  /**
   * Return the child of this element that is uniquely identified by the given
   * [identifier], or `null` if there is no such child.
   */
  ElementImpl getChild(String identifier) => null;

  @override
  String getExtendedDisplayName(String shortName) {
    if (shortName == null) {
      shortName = displayName;
    }
    Source source = this.source;
    if (source != null) {
      return "$shortName (${source.fullName})";
    }
    return shortName;
  }

  /**
   * Return the resolved [AstNode] of the given type enclosing [getNameOffset].
   */
  AstNode getNodeMatching(Predicate<AstNode> predicate) {
    CompilationUnit unit = this.unit;
    if (unit == null) {
      return null;
    }
    int offset = nameOffset;
    AstNode node = new NodeLocator(offset).searchWithin(unit);
    if (node == null) {
      return null;
    }
    return node.getAncestor(predicate);
  }

  /**
   * Return `true` if this element has the given [modifier] associated with it.
   */
  bool hasModifier(Modifier modifier) =>
      BooleanArray.get(_modifiers, modifier.ordinal);

  @override
  bool isAccessibleIn(LibraryElement library) {
    if (Identifier.isPrivateName(name)) {
      return library == this.library;
    }
    return true;
  }

  /**
   * Use the given [visitor] to visit all of the [children] in the given array.
   */
  void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
    if (children != null) {
      for (Element child in children) {
        child.accept(visitor);
      }
    }
  }

  /**
   * Set the code range for this element.
   */
  void setCodeRange(int offset, int length) {
    assert(!isResynthesized);
    _codeOffset = offset;
    _codeLength = length;
  }

  /**
   * Set whether the given [modifier] is associated with this element to
   * correspond to the given [value].
   */
  void setModifier(Modifier modifier, bool value) {
    _modifiers = BooleanArray.set(_modifiers, modifier.ordinal, value);
  }

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    appendTo(buffer);
    return buffer.toString();
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    // There are no children to visit
  }

  /**
   * Return annotations for the given [unlinkedConsts] in the [unit].
   */
  List<ElementAnnotation> _buildAnnotations(
      CompilationUnitElementImpl unit, List<UnlinkedConst> unlinkedConsts) {
    int length = unlinkedConsts.length;
    if (length != 0) {
      List<ElementAnnotation> annotations = new List<ElementAnnotation>(length);
      ResynthesizerContext context = unit.resynthesizerContext;
      for (int i = 0; i < length; i++) {
        annotations[i] = context.buildAnnotation(this, unlinkedConsts[i]);
      }
      return annotations;
    } else {
      return const <ElementAnnotation>[];
    }
  }

  static int _findElementIndexUsingIdentical(List items, Object item) {
    int length = items.length;
    for (int i = 0; i < length; i++) {
      if (identical(items[i], item)) {
        return i;
      }
    }
    throw new StateError('Unable to find $item in $items');
  }
}

/**
 * A concrete implementation of an [ElementLocation].
 */
class ElementLocationImpl implements ElementLocation {
  /**
   * The character used to separate components in the encoded form.
   */
  static int _SEPARATOR_CHAR = 0x3B;

  /**
   * The path to the element whose location is represented by this object.
   */
  List<String> _components;

  /**
   * The object managing [indexKeyId] and [indexLocationId].
   */
  Object indexOwner;

  /**
   * A cached id of this location in index.
   */
  int indexKeyId;

  /**
   * A cached id of this location in index.
   */
  int indexLocationId;

  /**
   * Initialize a newly created location to represent the given [element].
   */
  ElementLocationImpl.con1(Element element) {
    List<String> components = new List<String>();
    Element ancestor = element;
    while (ancestor != null) {
      components.insert(0, (ancestor as ElementImpl).identifier);
      ancestor = ancestor.enclosingElement;
    }
    this._components = components;
  }

  /**
   * Initialize a newly created location from the given [encoding].
   */
  ElementLocationImpl.con2(String encoding) {
    this._components = _decode(encoding);
  }

  /**
   * Initialize a newly created location from the given [components].
   */
  ElementLocationImpl.con3(List<String> components) {
    this._components = components;
  }

  @override
  List<String> get components => _components;

  @override
  String get encoding {
    StringBuffer buffer = new StringBuffer();
    int length = _components.length;
    for (int i = 0; i < length; i++) {
      if (i > 0) {
        buffer.writeCharCode(_SEPARATOR_CHAR);
      }
      _encode(buffer, _components[i]);
    }
    return buffer.toString();
  }

  @override
  int get hashCode {
    int result = 0;
    for (int i = 0; i < _components.length; i++) {
      String component = _components[i];
      result = JenkinsSmiHash.combine(result, component.hashCode);
    }
    return result;
  }

  @override
  bool operator ==(Object object) {
    if (identical(this, object)) {
      return true;
    }
    if (object is ElementLocationImpl) {
      List<String> otherComponents = object._components;
      int length = _components.length;
      if (otherComponents.length != length) {
        return false;
      }
      for (int i = 0; i < length; i++) {
        if (_components[i] != otherComponents[i]) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  @override
  String toString() => encoding;

  /**
   * Decode the [encoding] of a location into a list of components and return
   * the components.
   */
  List<String> _decode(String encoding) {
    List<String> components = new List<String>();
    StringBuffer buffer = new StringBuffer();
    int index = 0;
    int length = encoding.length;
    while (index < length) {
      int currentChar = encoding.codeUnitAt(index);
      if (currentChar == _SEPARATOR_CHAR) {
        if (index + 1 < length &&
            encoding.codeUnitAt(index + 1) == _SEPARATOR_CHAR) {
          buffer.writeCharCode(_SEPARATOR_CHAR);
          index += 2;
        } else {
          components.add(buffer.toString());
          buffer = new StringBuffer();
          index++;
        }
      } else {
        buffer.writeCharCode(currentChar);
        index++;
      }
    }
    components.add(buffer.toString());
    return components;
  }

  /**
   * Append an encoded form of the given [component] to the given [buffer].
   */
  void _encode(StringBuffer buffer, String component) {
    int length = component.length;
    for (int i = 0; i < length; i++) {
      int currentChar = component.codeUnitAt(i);
      if (currentChar == _SEPARATOR_CHAR) {
        buffer.writeCharCode(_SEPARATOR_CHAR);
      }
      buffer.writeCharCode(currentChar);
    }
  }
}

/**
 * An [AbstractClassElementImpl] which is an enum.
 */
class EnumElementImpl extends AbstractClassElementImpl {
  /**
   * The unlinked representation of the enum in the summary.
   */
  final UnlinkedEnum _unlinkedEnum;

  /**
   * The type defined by the enum.
   */
  InterfaceType _type;

  /**
   * Initialize a newly created class element to have the given [name] at the
   * given [offset] in the file that contains the declaration of this element.
   */
  EnumElementImpl(String name, int offset)
      : _unlinkedEnum = null,
        super(name, offset);

  /**
   * Initialize a newly created class element to have the given [name].
   */
  EnumElementImpl.forNode(Identifier name)
      : _unlinkedEnum = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  EnumElementImpl.forSerialized(
      this._unlinkedEnum, CompilationUnitElementImpl enclosingUnit)
      : super.forSerialized(enclosingUnit);

  /**
   * Set whether this class is abstract.
   */
  void set abstract(bool isAbstract) {
    _assertNotResynthesized(_unlinkedEnum);
  }

  @override
  List<PropertyAccessorElement> get accessors {
    if (_unlinkedEnum != null && _accessors == null) {
      _resynthesizeFieldsAndPropertyAccessors();
    }
    return _accessors ?? const <PropertyAccessorElement>[];
  }

  @override
  void set accessors(List<PropertyAccessorElement> accessors) {
    _assertNotResynthesized(_unlinkedEnum);
    super.accessors = accessors;
  }

  @override
  List<InterfaceType> get allSupertypes => <InterfaceType>[supertype];

  @override
  int get codeLength {
    if (_unlinkedEnum != null) {
      return _unlinkedEnum.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedEnum != null) {
      return _unlinkedEnum.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  List<ConstructorElement> get constructors {
    // The equivalent code for enums in the spec shows a single constructor,
    // but that constructor is not callable (since it is a compile-time error
    // to subclass, mix-in, implement, or explicitly instantiate an enum).
    // So we represent this as having no constructors.
    return const <ConstructorElement>[];
  }

  @override
  String get documentationComment {
    if (_unlinkedEnum != null) {
      return _unlinkedEnum?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  @override
  List<FieldElement> get fields {
    if (_unlinkedEnum != null && _fields == null) {
      _resynthesizeFieldsAndPropertyAccessors();
    }
    return _fields ?? const <FieldElement>[];
  }

  @override
  void set fields(List<FieldElement> fields) {
    _assertNotResynthesized(_unlinkedEnum);
    super.fields = fields;
  }

  @override
  bool get hasNonFinalField => false;

  @override
  bool get hasReferenceToSuper => false;

  @override
  bool get hasStaticMember => true;

  @override
  List<InterfaceType> get interfaces => const <InterfaceType>[];

  @override
  bool get isAbstract => false;

  @override
  bool get isEnum => true;

  @override
  bool get isMixinApplication => false;

  @override
  bool get isOrInheritsProxy => false;

  @override
  bool get isProxy => false;

  @override
  bool get isValidMixin => false;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedEnum != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedEnum.annotations);
    }
    return super.metadata;
  }

  @override
  List<MethodElement> get methods => const <MethodElement>[];

  @override
  List<InterfaceType> get mixins => const <InterfaceType>[];

  @override
  String get name {
    if (_unlinkedEnum != null) {
      return _unlinkedEnum.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedEnum != null && _unlinkedEnum.nameOffset != 0) {
      return _unlinkedEnum.nameOffset;
    }
    return offset;
  }

  @override
  InterfaceType get supertype => context.typeProvider.objectType;

  @override
  InterfaceType get type {
    if (_type == null) {
      InterfaceTypeImpl type = new InterfaceTypeImpl(this);
      type.typeArguments = const <DartType>[];
      _type = type;
    }
    return _type;
  }

  @override
  List<TypeParameterElement> get typeParameters =>
      const <TypeParameterElement>[];

  @override
  ConstructorElement get unnamedConstructor => null;

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write('enum ');
    String name = displayName;
    if (name == null) {
      buffer.write("{unnamed enum}");
    } else {
      buffer.write(name);
    }
  }

  @override
  MethodElement getMethod(String name) => null;

  @override
  ConstructorElement getNamedConstructor(String name) => null;

  @override
  bool isSuperConstructorAccessible(ConstructorElement constructor) => false;

  void _resynthesizeFieldsAndPropertyAccessors() {
    List<FieldElementImpl> fields = <FieldElementImpl>[];
    // Build the 'index' field.
    fields.add(new FieldElementImpl('index', -1)
      ..enclosingElement = this
      ..synthetic = true
      ..final2 = true
      ..type = context.typeProvider.intType);
    // Build the 'values' field.
    fields.add(new ConstFieldElementImpl_EnumValues(this));
    // Build fields for all enum constants.
    for (int i = 0; i < _unlinkedEnum.values.length; i++) {
      UnlinkedEnumValue unlinkedValue = _unlinkedEnum.values[i];
      ConstFieldElementImpl_EnumValue field =
          new ConstFieldElementImpl_EnumValue(this, unlinkedValue, i);
      fields.add(field);
    }
    // done
    _fields = fields;
    _accessors = fields
        .map((FieldElementImpl field) =>
            new PropertyAccessorElementImpl_ImplicitGetter(field)
              ..enclosingElement = this)
        .toList(growable: false);
  }
}

/**
 * A base class for concrete implementations of an [ExecutableElement].
 */
abstract class ExecutableElementImpl extends ElementImpl
    with TypeParameterizedElementMixin
    implements ExecutableElement {
  /**
   * The unlinked representation of the executable in the summary.
   */
  final UnlinkedExecutable serializedExecutable;

  /**
   * A list containing all of the functions defined within this executable
   * element.
   */
  List<FunctionElement> _functions;

  /**
   * A list containing all of the labels defined within this executable element.
   */
  List<LabelElement> _labels;

  /**
   * A list containing all of the local variables defined within this executable
   * element.
   */
  List<LocalVariableElement> _localVariables;

  /**
   * A list containing all of the parameters defined by this executable element.
   */
  List<ParameterElement> _parameters;

  /**
   * A list containing all of the type parameters defined for this executable
   * element.
   */
  List<TypeParameterElement> _typeParameters;

  /**
   * The return type defined by this executable element.
   */
  DartType _returnType;

  /**
   * The type of function defined by this executable element.
   */
  FunctionType _type;

  /**
   * Initialize a newly created executable element to have the given [name] and
   * [offset].
   */
  ExecutableElementImpl(String name, int offset)
      : serializedExecutable = null,
        super(name, offset);

  /**
   * Initialize a newly created executable element to have the given [name].
   */
  ExecutableElementImpl.forNode(Identifier name)
      : serializedExecutable = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ExecutableElementImpl.forSerialized(
      this.serializedExecutable, ElementImpl enclosingElement)
      : super.forSerialized(enclosingElement);

  /**
   * Set whether this executable element's body is asynchronous.
   */
  void set asynchronous(bool isAsynchronous) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.ASYNCHRONOUS, isAsynchronous);
  }

  @override
  int get codeLength {
    if (serializedExecutable != null) {
      return serializedExecutable.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (serializedExecutable != null) {
      return serializedExecutable.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  String get displayName {
    if (serializedExecutable != null) {
      return serializedExecutable.name;
    }
    return super.displayName;
  }

  @override
  String get documentationComment {
    if (serializedExecutable != null) {
      return serializedExecutable?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  /**
   * Set whether this executable element is external.
   */
  void set external(bool isExternal) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.EXTERNAL, isExternal);
  }

  @override
  List<FunctionElement> get functions {
    if (serializedExecutable != null) {
      _functions ??= FunctionElementImpl.resynthesizeList(
          this, serializedExecutable.localFunctions);
    }
    return _functions ?? const <FunctionElement>[];
  }

  /**
   * Set the functions defined within this executable element to the given
   * [functions].
   */
  void set functions(List<FunctionElement> functions) {
    _assertNotResynthesized(serializedExecutable);
    for (FunctionElement function in functions) {
      (function as FunctionElementImpl).enclosingElement = this;
    }
    this._functions = functions;
  }

  /**
   * Set whether this method's body is a generator.
   */
  void set generator(bool isGenerator) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.GENERATOR, isGenerator);
  }

  @override
  bool get hasImplicitReturnType {
    if (serializedExecutable != null) {
      return serializedExecutable.returnType == null &&
          serializedExecutable.kind != UnlinkedExecutableKind.constructor;
    }
    return hasModifier(Modifier.IMPLICIT_TYPE);
  }

  /**
   * Set whether this executable element has an implicit return type.
   */
  void set hasImplicitReturnType(bool hasImplicitReturnType) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType);
  }

  @override
  bool get isAbstract {
    if (serializedExecutable != null) {
      return serializedExecutable.isAbstract;
    }
    return hasModifier(Modifier.ABSTRACT);
  }

  @override
  bool get isAsynchronous {
    if (serializedExecutable != null) {
      return serializedExecutable.isAsynchronous;
    }
    return hasModifier(Modifier.ASYNCHRONOUS);
  }

  @override
  bool get isExternal {
    if (serializedExecutable != null) {
      return serializedExecutable.isExternal;
    }
    return hasModifier(Modifier.EXTERNAL);
  }

  @override
  bool get isGenerator {
    if (serializedExecutable != null) {
      return serializedExecutable.isGenerator;
    }
    return hasModifier(Modifier.GENERATOR);
  }

  @override
  bool get isOperator => false;

  @override
  bool get isSynchronous => !isAsynchronous;

  @override
  List<LabelElement> get labels {
    if (serializedExecutable != null) {
      _labels ??= LabelElementImpl.resynthesizeList(
          this, serializedExecutable.localLabels);
    }
    return _labels ?? const <LabelElement>[];
  }

  /**
   * Set the labels defined within this executable element to the given
   * [labels].
   */
  void set labels(List<LabelElement> labels) {
    _assertNotResynthesized(serializedExecutable);
    for (LabelElement label in labels) {
      (label as LabelElementImpl).enclosingElement = this;
    }
    this._labels = labels;
  }

  @override
  List<LocalVariableElement> get localVariables {
    if (serializedExecutable != null && _localVariables == null) {
      List<UnlinkedVariable> unlinkedVariables =
          serializedExecutable.localVariables;
      int length = unlinkedVariables.length;
      if (length != 0) {
        List<LocalVariableElementImpl> localVariables =
            new List<LocalVariableElementImpl>(length);
        for (int i = 0; i < length; i++) {
          localVariables[i] = new LocalVariableElementImpl.forSerializedFactory(
              unlinkedVariables[i], this);
        }
        _localVariables = localVariables;
      } else {
        _localVariables = const <LocalVariableElement>[];
      }
    }
    return _localVariables ?? const <LocalVariableElement>[];
  }

  /**
   * Set the local variables defined within this executable element to the given
   * [variables].
   */
  void set localVariables(List<LocalVariableElement> variables) {
    _assertNotResynthesized(serializedExecutable);
    for (LocalVariableElement variable in variables) {
      (variable as LocalVariableElementImpl).enclosingElement = this;
    }
    this._localVariables = variables;
  }

  @override
  List<ElementAnnotation> get metadata {
    if (serializedExecutable != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, serializedExecutable.annotations);
    }
    return super.metadata;
  }

  @override
  String get name {
    if (serializedExecutable != null) {
      return serializedExecutable.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && serializedExecutable != null) {
      return serializedExecutable.nameOffset;
    }
    return offset;
  }

  @override
  List<ParameterElement> get parameters {
    if (serializedExecutable != null) {
      _parameters ??= ParameterElementImpl.resynthesizeList(
          serializedExecutable.parameters, this);
    }
    return _parameters ?? const <ParameterElement>[];
  }

  /**
   * Set the parameters defined by this executable element to the given
   * [parameters].
   */
  void set parameters(List<ParameterElement> parameters) {
    _assertNotResynthesized(serializedExecutable);
    for (ParameterElement parameter in parameters) {
      (parameter as ParameterElementImpl).enclosingElement = this;
    }
    this._parameters = parameters;
  }

  @override
  DartType get returnType {
    if (serializedExecutable != null && _returnType == null) {
      bool isSetter =
          serializedExecutable.kind == UnlinkedExecutableKind.setter;
      _returnType = enclosingUnit.resynthesizerContext.resolveLinkedType(
              serializedExecutable.inferredReturnTypeSlot,
              typeParameterContext) ??
          enclosingUnit.resynthesizerContext.resolveTypeRef(
              serializedExecutable.returnType, typeParameterContext,
              defaultVoid: isSetter && context.analysisOptions.strongMode);
    }
    return _returnType;
  }

  void set returnType(DartType returnType) {
    _assertNotResynthesized(serializedExecutable);
    _returnType = returnType;
  }

  @override
  FunctionType get type {
    if (serializedExecutable != null) {
      _type ??= new FunctionTypeImpl.elementWithNameAndArgs(
          this, null, allEnclosingTypeParameterTypes, false);
    }
    return _type;
  }

  void set type(FunctionType type) {
    _assertNotResynthesized(serializedExecutable);
    _type = type;
  }

  @override
  TypeParameterizedElementMixin get typeParameterContext => this;

  @override
  List<TypeParameterElement> get typeParameters {
    if (serializedExecutable != null) {
      return super.typeParameters;
    }
    return _typeParameters ?? const <TypeParameterElement>[];
  }

  /**
   * Set the type parameters defined by this executable element to the given
   * [typeParameters].
   */
  void set typeParameters(List<TypeParameterElement> typeParameters) {
    _assertNotResynthesized(serializedExecutable);
    for (TypeParameterElement parameter in typeParameters) {
      (parameter as TypeParameterElementImpl).enclosingElement = this;
    }
    this._typeParameters = typeParameters;
  }

  @override
  List<UnlinkedTypeParam> get unlinkedTypeParams =>
      serializedExecutable.typeParameters;

  @override
  void appendTo(StringBuffer buffer) {
    if (this.kind != ElementKind.GETTER) {
      int typeParameterCount = typeParameters.length;
      if (typeParameterCount > 0) {
        buffer.write('<');
        for (int i = 0; i < typeParameterCount; i++) {
          if (i > 0) {
            buffer.write(", ");
          }
          (typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
        }
        buffer.write('>');
      }
      buffer.write("(");
      String closing = null;
      ParameterKind kind = ParameterKind.REQUIRED;
      int parameterCount = parameters.length;
      for (int i = 0; i < parameterCount; i++) {
        if (i > 0) {
          buffer.write(", ");
        }
        ParameterElement parameter = parameters[i];
        ParameterKind parameterKind = parameter.parameterKind;
        if (parameterKind != kind) {
          if (closing != null) {
            buffer.write(closing);
          }
          if (parameterKind == ParameterKind.POSITIONAL) {
            buffer.write("[");
            closing = "]";
          } else if (parameterKind == ParameterKind.NAMED) {
            buffer.write("{");
            closing = "}";
          } else {
            closing = null;
          }
        }
        kind = parameterKind;
        parameter.appendToWithoutDelimiters(buffer);
      }
      if (closing != null) {
        buffer.write(closing);
      }
      buffer.write(")");
    }
    if (type != null) {
      buffer.write(ElementImpl.RIGHT_ARROW);
      buffer.write(type.returnType);
    }
  }

  @override
  ElementImpl getChild(String identifier) {
    for (FunctionElement function in _functions) {
      FunctionElementImpl functionImpl = function;
      if (functionImpl.identifier == identifier) {
        return functionImpl;
      }
    }
    for (LabelElement label in _labels) {
      LabelElementImpl labelImpl = label;
      if (labelImpl.identifier == identifier) {
        return labelImpl;
      }
    }
    for (LocalVariableElement variable in _localVariables) {
      LocalVariableElementImpl variableImpl = variable;
      if (variableImpl.identifier == identifier) {
        return variableImpl;
      }
    }
    for (ParameterElement parameter in parameters) {
      ParameterElementImpl parameterImpl = parameter;
      if (parameterImpl.identifier == identifier) {
        return parameterImpl;
      }
    }
    return null;
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(typeParameters, visitor);
    safelyVisitChildren(parameters, visitor);
    safelyVisitChildren(_functions, visitor);
    safelyVisitChildren(_labels, visitor);
    safelyVisitChildren(_localVariables, visitor);
  }
}

/**
 * A concrete implementation of an [ExportElement].
 */
class ExportElementImpl extends UriReferencedElementImpl
    implements ExportElement {
  /**
   * The unlinked representation of the export in the summary.
   */
  final UnlinkedExportPublic _unlinkedExportPublic;

  /**
   * The unlinked representation of the export in the summary.
   */
  final UnlinkedExportNonPublic _unlinkedExportNonPublic;

  /**
   * The library that is exported from this library by this export directive.
   */
  LibraryElement _exportedLibrary;

  /**
   * The combinators that were specified as part of the export directive in the
   * order in which they were specified.
   */
  List<NamespaceCombinator> _combinators;

  /**
   * The URI that was selected based on the [context] declared variables.
   */
  String _selectedUri;

  /**
   * Initialize a newly created export element at the given [offset].
   */
  ExportElementImpl(int offset)
      : _unlinkedExportPublic = null,
        _unlinkedExportNonPublic = null,
        super(null, offset);

  /**
   * Initialize using the given serialized information.
   */
  ExportElementImpl.forSerialized(this._unlinkedExportPublic,
      this._unlinkedExportNonPublic, LibraryElementImpl enclosingLibrary)
      : super.forSerialized(enclosingLibrary);

  @override
  List<NamespaceCombinator> get combinators {
    if (_unlinkedExportPublic != null && _combinators == null) {
      _combinators = ImportElementImpl
          ._buildCombinators(_unlinkedExportPublic.combinators);
    }
    return _combinators ?? const <NamespaceCombinator>[];
  }

  void set combinators(List<NamespaceCombinator> combinators) {
    _assertNotResynthesized(_unlinkedExportPublic);
    _combinators = combinators;
  }

  @override
  LibraryElement get exportedLibrary {
    if (_unlinkedExportNonPublic != null && _exportedLibrary == null) {
      LibraryElementImpl library = enclosingElement as LibraryElementImpl;
      _exportedLibrary = library.resynthesizerContext.buildExportedLibrary(uri);
    }
    return _exportedLibrary;
  }

  void set exportedLibrary(LibraryElement exportedLibrary) {
    _assertNotResynthesized(_unlinkedExportNonPublic);
    _exportedLibrary = exportedLibrary;
  }

  @override
  String get identifier => exportedLibrary.name;

  @override
  ElementKind get kind => ElementKind.EXPORT;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedExportNonPublic != null) {
      return _metadata ??= _buildAnnotations(
          library.definingCompilationUnit as CompilationUnitElementImpl,
          _unlinkedExportNonPublic.annotations);
    }
    return super.metadata;
  }

  void set metadata(List<ElementAnnotation> metadata) {
    _assertNotResynthesized(_unlinkedExportNonPublic);
    super.metadata = metadata;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedExportNonPublic != null) {
      return _unlinkedExportNonPublic.offset;
    }
    return offset;
  }

  @override
  String get uri {
    if (_unlinkedExportPublic != null) {
      return _selectedUri ??= _selectUri(
          _unlinkedExportPublic.uri, _unlinkedExportPublic.configurations);
    }
    return super.uri;
  }

  @override
  void set uri(String uri) {
    _assertNotResynthesized(_unlinkedExportPublic);
    super.uri = uri;
  }

  @override
  int get uriEnd {
    if (_unlinkedExportNonPublic != null) {
      return _unlinkedExportNonPublic.uriEnd;
    }
    return super.uriEnd;
  }

  @override
  void set uriEnd(int uriEnd) {
    _assertNotResynthesized(_unlinkedExportNonPublic);
    super.uriEnd = uriEnd;
  }

  @override
  int get uriOffset {
    if (_unlinkedExportNonPublic != null) {
      return _unlinkedExportNonPublic.uriOffset;
    }
    return super.uriOffset;
  }

  @override
  void set uriOffset(int uriOffset) {
    _assertNotResynthesized(_unlinkedExportNonPublic);
    super.uriOffset = uriOffset;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitExportElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write("export ");
    (exportedLibrary as LibraryElementImpl).appendTo(buffer);
  }
}

/**
 * A concrete implementation of a [FieldElement].
 */
class FieldElementImpl extends PropertyInducingElementImpl
    implements FieldElement {
  /**
   * Initialize a newly created synthetic field element to have the given [name]
   * at the given [offset].
   */
  FieldElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created field element to have the given [name].
   */
  FieldElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  FieldElementImpl.forSerialized(
      UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedVariable, enclosingElement);

  /**
   * Initialize using the given serialized information.
   */
  factory FieldElementImpl.forSerializedFactory(
      UnlinkedVariable unlinkedVariable, ClassElementImpl enclosingClass) {
    if (unlinkedVariable.initializer?.bodyExpr != null &&
        (unlinkedVariable.isConst ||
            unlinkedVariable.isFinal && !unlinkedVariable.isStatic)) {
      return new ConstFieldElementImpl.forSerialized(
          unlinkedVariable, enclosingClass);
    } else {
      return new FieldElementImpl.forSerialized(
          unlinkedVariable, enclosingClass);
    }
  }

  @override
  ClassElement get enclosingElement => super.enclosingElement as ClassElement;

  @override
  bool get isEnumConstant =>
      enclosingElement != null ? enclosingElement.isEnum : false;

  @override
  bool get isStatic {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.isStatic;
    }
    return hasModifier(Modifier.STATIC);
  }

  @override
  bool get isVirtual {
    for (ElementAnnotationImpl annotation in metadata) {
      if (annotation.isVirtual) {
        return true;
      }
    }
    return false;
  }

  @override
  ElementKind get kind => ElementKind.FIELD;

  /**
   * Set whether this field is static.
   */
  void set static(bool isStatic) {
    _assertNotResynthesized(_unlinkedVariable);
    setModifier(Modifier.STATIC, isStatic);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitFieldElement(this);

  @override
  AstNode computeNode() {
    if (isEnumConstant) {
      return getNodeMatching((node) => node is EnumConstantDeclaration);
    } else {
      return getNodeMatching((node) => node is VariableDeclaration);
    }
  }
}

/**
 * A [ParameterElementImpl] that has the additional information of the
 * [FieldElement] associated with the parameter.
 */
class FieldFormalParameterElementImpl extends ParameterElementImpl
    implements FieldFormalParameterElement {
  /**
   * The field associated with this field formal parameter.
   */
  FieldElement _field;

  /**
   * Initialize a newly created parameter element to have the given [name] and
   * [nameOffset].
   */
  FieldFormalParameterElementImpl(String name, int nameOffset)
      : super(name, nameOffset);

  /**
   * Initialize a newly created parameter element to have the given [name].
   */
  FieldFormalParameterElementImpl.forNode(Identifier name)
      : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  FieldFormalParameterElementImpl.forSerialized(
      UnlinkedParam unlinkedParam, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedParam, enclosingElement);

  @override
  FieldElement get field {
    if (_unlinkedParam != null && _field == null) {
      Element enclosingClass = enclosingElement?.enclosingElement;
      if (enclosingClass is ClassElement) {
        _field = enclosingClass.getField(_unlinkedParam.name);
      }
    }
    return _field;
  }

  void set field(FieldElement field) {
    _assertNotResynthesized(_unlinkedParam);
    _field = field;
  }

  @override
  bool get isInitializingFormal => true;

  @override
  DartType get type {
    if (_unlinkedParam != null && _unlinkedParam.type == null) {
      _type ??= field?.type ?? DynamicTypeImpl.instance;
    }
    return super.type;
  }

  @override
  void set type(DartType type) {
    _assertNotResynthesized(_unlinkedParam);
    _type = type;
  }

  @override
  accept(ElementVisitor visitor) =>
      visitor.visitFieldFormalParameterElement(this);
}

/**
 * A concrete implementation of a [FunctionElement].
 */
class FunctionElementImpl extends ExecutableElementImpl
    implements FunctionElement {
  /**
   * The offset to the beginning of the visible range for this element.
   */
  int _visibleRangeOffset = 0;

  /**
   * The length of the visible range for this element, or `-1` if this element
   * does not have a visible range.
   */
  int _visibleRangeLength = -1;

  /**
   * Initialize a newly created function element to have the given [name] and
   * [offset].
   */
  FunctionElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created function element to have the given [name].
   */
  FunctionElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize a newly created function element to have no name and the given
   * [nameOffset]. This is used for function expressions, that have no name.
   */
  FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset);

  /**
   * Initialize using the given serialized information.
   */
  FunctionElementImpl.forSerialized(
      UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement)
      : super.forSerialized(serializedExecutable, enclosingElement);

  /**
   * Synthesize an unnamed function element that takes [parameters] and returns
   * [returnType].
   */
  FunctionElementImpl.synthetic(
      List<ParameterElement> parameters, DartType returnType)
      : super("", -1) {
    synthetic = true;
    this.returnType = returnType;
    this.parameters = parameters;

    type = new FunctionTypeImpl(this);
  }

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext {
    return (enclosingElement as ElementImpl).typeParameterContext;
  }

  @override
  String get identifier {
    String identifier = super.identifier;
    Element enclosing = this.enclosingElement;
    if (enclosing is ExecutableElement) {
      int id = ElementImpl._findElementIndexUsingIdentical(
          enclosing.functions, this);
      identifier += "@$id";
    }
    return identifier;
  }

  @override
  bool get isEntryPoint {
    return isStatic && displayName == FunctionElement.MAIN_FUNCTION_NAME;
  }

  @override
  bool get isStatic => enclosingElement is CompilationUnitElement;

  @override
  ElementKind get kind => ElementKind.FUNCTION;

  @override
  SourceRange get visibleRange {
    if (serializedExecutable != null) {
      if (serializedExecutable.visibleLength == 0) {
        return null;
      }
      return new SourceRange(serializedExecutable.visibleOffset,
          serializedExecutable.visibleLength);
    }
    if (_visibleRangeLength < 0) {
      return null;
    }
    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    String name = displayName;
    if (name != null) {
      buffer.write(name);
    }
    super.appendTo(buffer);
  }

  @override
  FunctionDeclaration computeNode() =>
      getNodeMatching((node) => node is FunctionDeclaration);

  /**
   * Set the visible range for this element to the range starting at the given
   * [offset] with the given [length].
   */
  void setVisibleRange(int offset, int length) {
    _assertNotResynthesized(serializedExecutable);
    _visibleRangeOffset = offset;
    _visibleRangeLength = length;
  }

  /**
   * Set the parameters defined by this type alias to the given [parameters]
   * without becoming the parent of the parameters. This should only be used by
   * the [TypeResolverVisitor] when creating a synthetic type alias.
   */
  void shareParameters(List<ParameterElement> parameters) {
    this._parameters = parameters;
  }

  /**
   * Set the type parameters defined by this type alias to the given
   * [parameters] without becoming the parent of the parameters. This should
   * only be used by the [TypeResolverVisitor] when creating a synthetic type
   * alias.
   */
  void shareTypeParameters(List<TypeParameterElement> typeParameters) {
    this._typeParameters = typeParameters;
  }

  /**
   * Create and return [FunctionElement]s for the given [unlinkedFunctions].
   */
  static List<FunctionElement> resynthesizeList(
      ExecutableElementImpl executableElement,
      List<UnlinkedExecutable> unlinkedFunctions) {
    int length = unlinkedFunctions.length;
    if (length != 0) {
      List<FunctionElement> elements = new List<FunctionElement>(length);
      for (int i = 0; i < length; i++) {
        elements[i] = new FunctionElementImpl.forSerialized(
            unlinkedFunctions[i], executableElement);
      }
      return elements;
    } else {
      return const <FunctionElement>[];
    }
  }
}

/**
 * Implementation of [FunctionElementImpl] for a function typed parameter.
 */
class FunctionElementImpl_forFunctionTypedParameter
    extends FunctionElementImpl {
  @override
  final CompilationUnitElementImpl enclosingUnit;

  /**
   * The enclosing function typed [ParameterElementImpl].
   */
  final ParameterElementImpl _parameter;

  FunctionElementImpl_forFunctionTypedParameter(
      this.enclosingUnit, this._parameter)
      : super('', -1);

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
      _parameter.typeParameterContext;

  @override
  bool get isSynthetic => true;
}

/**
 * Implementation of [FunctionElementImpl] for a synthetic function element
 * that was synthesized by a LUB computation.
 */
class FunctionElementImpl_forLUB extends FunctionElementImpl {
  @override
  final CompilationUnitElementImpl enclosingUnit;

  @override
  final TypeParameterizedElementMixin enclosingTypeParameterContext;

  final EntityRef _entityRef;

  FunctionElementImpl_forLUB(
      this.enclosingUnit, this.enclosingTypeParameterContext, this._entityRef)
      : super('', -1);

  @override
  bool get isSynthetic => true;

  @override
  List<ParameterElement> get parameters {
    return _parameters ??= ParameterElementImpl
        .resynthesizeList(_entityRef.syntheticParams, this, synthetic: true);
  }

  @override
  void set parameters(List<ParameterElement> parameters) {
    assert(false);
  }

  @override
  DartType get returnType {
    return _returnType ??= enclosingUnit.resynthesizerContext
        .resolveTypeRef(_entityRef.syntheticReturnType, typeParameterContext);
  }

  @override
  void set returnType(DartType returnType) {
    assert(false);
  }

  @override
  FunctionType get type {
    return _type ??=
        new FunctionTypeImpl.elementWithNameAndArgs(this, null, null, false);
  }

  @override
  void set type(FunctionType type) {
    assert(false);
  }
}

/**
 * A concrete implementation of a [FunctionTypeAliasElement].
 */
class FunctionTypeAliasElementImpl extends ElementImpl
    with TypeParameterizedElementMixin
    implements FunctionTypeAliasElement {
  /**
   * The unlinked representation of the type in the summary.
   */
  final UnlinkedTypedef _unlinkedTypedef;

  /**
   * A list containing all of the parameters defined by this type alias.
   */
  List<ParameterElement> _parameters;

  /**
   * The return type defined by this type alias.
   */
  DartType _returnType;

  /**
   * The type of function defined by this type alias.
   */
  FunctionType _type;

  /**
   * A list containing all of the type parameters defined for this type.
   */
  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;

  /**
   * Initialize a newly created type alias element to have the given name.
   *
   * [name] the name of this element
   * [nameOffset] the offset of the name of this element in the file that
   *    contains the declaration of this element
   */
  FunctionTypeAliasElementImpl(String name, int nameOffset)
      : _unlinkedTypedef = null,
        super(name, nameOffset);

  /**
   * Initialize a newly created type alias element to have the given [name].
   */
  FunctionTypeAliasElementImpl.forNode(Identifier name)
      : _unlinkedTypedef = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  FunctionTypeAliasElementImpl.forSerialized(
      this._unlinkedTypedef, CompilationUnitElementImpl enclosingUnit)
      : super.forSerialized(enclosingUnit);

  @override
  int get codeLength {
    if (_unlinkedTypedef != null) {
      return _unlinkedTypedef.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedTypedef != null) {
      return _unlinkedTypedef.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  String get displayName => name;

  @override
  String get documentationComment {
    if (_unlinkedTypedef != null) {
      return _unlinkedTypedef?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  @override
  CompilationUnitElement get enclosingElement =>
      super.enclosingElement as CompilationUnitElement;

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;

  @override
  CompilationUnitElementImpl get enclosingUnit =>
      _enclosingElement as CompilationUnitElementImpl;

  @override
  ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedTypedef != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedTypedef.annotations);
    }
    return super.metadata;
  }

  @override
  String get name {
    if (_unlinkedTypedef != null) {
      return _unlinkedTypedef.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedTypedef != null) {
      return _unlinkedTypedef.nameOffset;
    }
    return offset;
  }

  @override
  List<ParameterElement> get parameters {
    if (_unlinkedTypedef != null) {
      _parameters ??= ParameterElementImpl.resynthesizeList(
          _unlinkedTypedef.parameters, this);
    }
    return _parameters ?? const <ParameterElement>[];
  }

  /**
   * Set the parameters defined by this type alias to the given [parameters].
   */
  void set parameters(List<ParameterElement> parameters) {
    _assertNotResynthesized(_unlinkedTypedef);
    if (parameters != null) {
      for (ParameterElement parameter in parameters) {
        (parameter as ParameterElementImpl).enclosingElement = this;
      }
    }
    this._parameters = parameters;
  }

  @override
  DartType get returnType {
    if (_unlinkedTypedef != null && _returnType == null) {
      _returnType = enclosingUnit.resynthesizerContext
          .resolveTypeRef(_unlinkedTypedef.returnType, this);
    }
    return _returnType;
  }

  void set returnType(DartType returnType) {
    _assertNotResynthesized(_unlinkedTypedef);
    _returnType = returnType;
  }

  @override
  FunctionType get type {
    if (_unlinkedTypedef != null && _type == null) {
      _type = new FunctionTypeImpl.forTypedef(this);
    }
    return _type;
  }

  void set type(FunctionType type) {
    _assertNotResynthesized(_unlinkedTypedef);
    _type = type;
  }

  @override
  TypeParameterizedElementMixin get typeParameterContext => this;

  @override
  List<TypeParameterElement> get typeParameters {
    if (_unlinkedTypedef != null) {
      return super.typeParameters;
    }
    return _typeParameters;
  }

  /**
   * Set the type parameters defined for this type to the given
   * [typeParameters].
   */
  void set typeParameters(List<TypeParameterElement> typeParameters) {
    _assertNotResynthesized(_unlinkedTypedef);
    for (TypeParameterElement typeParameter in typeParameters) {
      (typeParameter as TypeParameterElementImpl).enclosingElement = this;
    }
    this._typeParameters = typeParameters;
  }

  @override
  List<UnlinkedTypeParam> get unlinkedTypeParams =>
      _unlinkedTypedef.typeParameters;

  @override
  accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write("typedef ");
    buffer.write(displayName);
    int typeParameterCount = _typeParameters.length;
    if (typeParameterCount > 0) {
      buffer.write("<");
      for (int i = 0; i < typeParameterCount; i++) {
        if (i > 0) {
          buffer.write(", ");
        }
        (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
      }
      buffer.write(">");
    }
    buffer.write("(");
    int parameterCount = _parameters.length;
    for (int i = 0; i < parameterCount; i++) {
      if (i > 0) {
        buffer.write(", ");
      }
      (_parameters[i] as ParameterElementImpl).appendTo(buffer);
    }
    buffer.write(")");
    if (type != null) {
      buffer.write(ElementImpl.RIGHT_ARROW);
      buffer.write(type.returnType);
    } else if (returnType != null) {
      buffer.write(ElementImpl.RIGHT_ARROW);
      buffer.write(returnType);
    }
  }

  @override
  FunctionTypeAlias computeNode() =>
      getNodeMatching((node) => node is FunctionTypeAlias);

  @override
  ElementImpl getChild(String identifier) {
    for (ParameterElement parameter in parameters) {
      ParameterElementImpl parameterImpl = parameter;
      if (parameterImpl.identifier == identifier) {
        return parameterImpl;
      }
    }
    for (TypeParameterElement typeParameter in _typeParameters) {
      TypeParameterElementImpl typeParameterImpl = typeParameter;
      if (typeParameterImpl.identifier == identifier) {
        return typeParameterImpl;
      }
    }
    return null;
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(parameters, visitor);
    safelyVisitChildren(_typeParameters, visitor);
  }
}

/**
 * A concrete implementation of a [HideElementCombinator].
 */
class HideElementCombinatorImpl implements HideElementCombinator {
  /**
   * The unlinked representation of the combinator in the summary.
   */
  final UnlinkedCombinator _unlinkedCombinator;

  /**
   * The names that are not to be made visible in the importing library even if
   * they are defined in the imported library.
   */
  List<String> _hiddenNames;

  HideElementCombinatorImpl() : _unlinkedCombinator = null;

  /**
   * Initialize using the given serialized information.
   */
  HideElementCombinatorImpl.forSerialized(this._unlinkedCombinator);

  @override
  List<String> get hiddenNames {
    if (_unlinkedCombinator != null) {
      _hiddenNames ??= _unlinkedCombinator.hides.toList(growable: false);
    }
    return _hiddenNames ?? const <String>[];
  }

  void set hiddenNames(List<String> hiddenNames) {
    _assertNotResynthesized(_unlinkedCombinator);
    _hiddenNames = hiddenNames;
  }

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    buffer.write("show ");
    int count = hiddenNames.length;
    for (int i = 0; i < count; i++) {
      if (i > 0) {
        buffer.write(", ");
      }
      buffer.write(hiddenNames[i]);
    }
    return buffer.toString();
  }
}

/**
 * A concrete implementation of an [ImportElement].
 */
class ImportElementImpl extends UriReferencedElementImpl
    implements ImportElement {
  /**
   * The unlinked representation of the import in the summary.
   */
  final UnlinkedImport _unlinkedImport;

  /**
   * The index of the dependency in the `imports` list.
   */
  final int _linkedDependency;

  /**
   * The offset of the prefix of this import in the file that contains the this
   * import directive, or `-1` if this import is synthetic.
   */
  int _prefixOffset = 0;

  /**
   * The library that is imported into this library by this import directive.
   */
  LibraryElement _importedLibrary;

  /**
   * The combinators that were specified as part of the import directive in the
   * order in which they were specified.
   */
  List<NamespaceCombinator> _combinators;

  /**
   * The prefix that was specified as part of the import directive, or `null` if
   * there was no prefix specified.
   */
  PrefixElement _prefix;

  /**
   * The URI that was selected based on the [context] declared variables.
   */
  String _selectedUri;

  /**
   * Initialize a newly created import element at the given [offset].
   * The offset may be `-1` if the import is synthetic.
   */
  ImportElementImpl(int offset)
      : _unlinkedImport = null,
        _linkedDependency = null,
        super(null, offset);

  /**
   * Initialize using the given serialized information.
   */
  ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
      LibraryElementImpl enclosingLibrary)
      : super.forSerialized(enclosingLibrary);

  @override
  List<NamespaceCombinator> get combinators {
    if (_unlinkedImport != null && _combinators == null) {
      _combinators = _buildCombinators(_unlinkedImport.combinators);
    }
    return _combinators ?? const <NamespaceCombinator>[];
  }

  void set combinators(List<NamespaceCombinator> combinators) {
    _assertNotResynthesized(_unlinkedImport);
    _combinators = combinators;
  }

  /**
   * Set whether this import is for a deferred library.
   */
  void set deferred(bool isDeferred) {
    _assertNotResynthesized(_unlinkedImport);
    setModifier(Modifier.DEFERRED, isDeferred);
  }

  @override
  String get identifier => "${importedLibrary.identifier}@$nameOffset";

  @override
  LibraryElement get importedLibrary {
    if (_linkedDependency != null) {
      if (_importedLibrary == null) {
        LibraryElementImpl library = enclosingElement as LibraryElementImpl;
        if (_linkedDependency == 0) {
          _importedLibrary = library;
        } else {
          _importedLibrary = library.resynthesizerContext
              .buildImportedLibrary(_linkedDependency);
        }
      }
    }
    return _importedLibrary;
  }

  void set importedLibrary(LibraryElement importedLibrary) {
    _assertNotResynthesized(_unlinkedImport);
    _importedLibrary = importedLibrary;
  }

  @override
  bool get isDeferred {
    if (_unlinkedImport != null) {
      return _unlinkedImport.isDeferred;
    }
    return hasModifier(Modifier.DEFERRED);
  }

  @override
  bool get isSynthetic {
    if (_unlinkedImport != null) {
      return _unlinkedImport.isImplicit;
    }
    return super.isSynthetic;
  }

  @override
  ElementKind get kind => ElementKind.IMPORT;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedImport != null) {
      return _metadata ??= _buildAnnotations(
          library.definingCompilationUnit as CompilationUnitElementImpl,
          _unlinkedImport.annotations);
    }
    return super.metadata;
  }

  void set metadata(List<ElementAnnotation> metadata) {
    _assertNotResynthesized(_unlinkedImport);
    super.metadata = metadata;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedImport != null) {
      if (_unlinkedImport.isImplicit) {
        return -1;
      }
      return _unlinkedImport.offset;
    }
    return offset;
  }

  PrefixElement get prefix {
    if (_unlinkedImport != null) {
      if (_unlinkedImport.prefixReference != 0 && _prefix == null) {
        LibraryElementImpl library = enclosingElement as LibraryElementImpl;
        _prefix = new PrefixElementImpl.forSerialized(_unlinkedImport, library);
      }
    }
    return _prefix;
  }

  void set prefix(PrefixElement prefix) {
    _assertNotResynthesized(_unlinkedImport);
    _prefix = prefix;
  }

  @override
  int get prefixOffset {
    if (_unlinkedImport != null) {
      return _unlinkedImport.prefixOffset;
    }
    return _prefixOffset;
  }

  void set prefixOffset(int prefixOffset) {
    _assertNotResynthesized(_unlinkedImport);
    _prefixOffset = prefixOffset;
  }

  @override
  String get uri {
    if (_unlinkedImport != null) {
      if (_unlinkedImport.isImplicit) {
        return null;
      }
      return _selectedUri ??=
          _selectUri(_unlinkedImport.uri, _unlinkedImport.configurations);
    }
    return super.uri;
  }

  @override
  void set uri(String uri) {
    _assertNotResynthesized(_unlinkedImport);
    super.uri = uri;
  }

  @override
  int get uriEnd {
    if (_unlinkedImport != null) {
      if (_unlinkedImport.isImplicit) {
        return -1;
      }
      return _unlinkedImport.uriEnd;
    }
    return super.uriEnd;
  }

  @override
  void set uriEnd(int uriEnd) {
    _assertNotResynthesized(_unlinkedImport);
    super.uriEnd = uriEnd;
  }

  @override
  int get uriOffset {
    if (_unlinkedImport != null) {
      if (_unlinkedImport.isImplicit) {
        return -1;
      }
      return _unlinkedImport.uriOffset;
    }
    return super.uriOffset;
  }

  @override
  void set uriOffset(int uriOffset) {
    _assertNotResynthesized(_unlinkedImport);
    super.uriOffset = uriOffset;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitImportElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write("import ");
    (importedLibrary as LibraryElementImpl).appendTo(buffer);
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    prefix?.accept(visitor);
  }

  static List<NamespaceCombinator> _buildCombinators(
      List<UnlinkedCombinator> unlinkedCombinators) {
    int length = unlinkedCombinators.length;
    if (length != 0) {
      List<NamespaceCombinator> combinators =
          new List<NamespaceCombinator>(length);
      for (int i = 0; i < length; i++) {
        UnlinkedCombinator unlinkedCombinator = unlinkedCombinators[i];
        combinators[i] = unlinkedCombinator.shows.isNotEmpty
            ? new ShowElementCombinatorImpl.forSerialized(unlinkedCombinator)
            : new HideElementCombinatorImpl.forSerialized(unlinkedCombinator);
      }
      return combinators;
    } else {
      return const <NamespaceCombinator>[];
    }
  }
}

/**
 * A concrete implementation of a [LabelElement].
 */
class LabelElementImpl extends ElementImpl implements LabelElement {
  /**
   * The unlinked representation of the label in the summary.
   */
  final UnlinkedLabel _unlinkedLabel;

  /**
   * A flag indicating whether this label is associated with a `switch`
   * statement.
   */
  // TODO(brianwilkerson) Make this a modifier.
  final bool _onSwitchStatement;

  /**
   * A flag indicating whether this label is associated with a `switch` member
   * (`case` or `default`).
   */
  // TODO(brianwilkerson) Make this a modifier.
  final bool _onSwitchMember;

  /**
   * Initialize a newly created label element to have the given [name].
   * [onSwitchStatement] should be `true` if this label is associated with a
   * `switch` statement and [onSwitchMember] should be `true` if this label is
   * associated with a `switch` member.
   */
  LabelElementImpl(String name, int nameOffset, this._onSwitchStatement,
      this._onSwitchMember)
      : _unlinkedLabel = null,
        super(name, nameOffset);

  /**
   * Initialize a newly created label element to have the given [name].
   * [_onSwitchStatement] should be `true` if this label is associated with a
   * `switch` statement and [_onSwitchMember] should be `true` if this label is
   * associated with a `switch` member.
   */
  LabelElementImpl.forNode(
      Identifier name, this._onSwitchStatement, this._onSwitchMember)
      : _unlinkedLabel = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  LabelElementImpl.forSerialized(
      UnlinkedLabel unlinkedLabel, ExecutableElementImpl enclosingExecutable)
      : _unlinkedLabel = unlinkedLabel,
        _onSwitchStatement = unlinkedLabel.isOnSwitchStatement,
        _onSwitchMember = unlinkedLabel.isOnSwitchMember,
        super.forSerialized(enclosingExecutable);

  @override
  String get displayName => name;

  @override
  ExecutableElement get enclosingElement =>
      super.enclosingElement as ExecutableElement;

  /**
   * Return `true` if this label is associated with a `switch` member (`case` or
   * `default`).
   */
  bool get isOnSwitchMember => _onSwitchMember;

  /**
   * Return `true` if this label is associated with a `switch` statement.
   */
  bool get isOnSwitchStatement => _onSwitchStatement;

  @override
  ElementKind get kind => ElementKind.LABEL;

  @override
  String get name {
    if (_unlinkedLabel != null) {
      return _unlinkedLabel.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 &&
        _unlinkedLabel != null &&
        _unlinkedLabel.nameOffset != 0) {
      return _unlinkedLabel.nameOffset;
    }
    return offset;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitLabelElement(this);

  /**
   * Create and return [LabelElement]s for the given [unlinkedLabels].
   */
  static List<LabelElement> resynthesizeList(
      ExecutableElementImpl enclosingExecutable,
      List<UnlinkedLabel> unlinkedLabels) {
    int length = unlinkedLabels.length;
    if (length != 0) {
      List<LabelElement> elements = new List<LabelElement>(length);
      for (int i = 0; i < length; i++) {
        elements[i] = new LabelElementImpl.forSerialized(
            unlinkedLabels[i], enclosingExecutable);
      }
      return elements;
    } else {
      return const <LabelElement>[];
    }
  }
}

/**
 * A concrete implementation of a [LibraryElement].
 */
class LibraryElementImpl extends ElementImpl implements LibraryElement {
  /**
   * The analysis context in which this library is defined.
   */
  final AnalysisContext context;

  final LibraryResynthesizerContext resynthesizerContext;

  final UnlinkedUnit _unlinkedDefiningUnit;

  /**
   * The compilation unit that defines this library.
   */
  CompilationUnitElement _definingCompilationUnit;

  /**
   * The entry point for this library, or `null` if this library does not have
   * an entry point.
   */
  FunctionElement _entryPoint;

  /**
   * A list containing specifications of all of the imports defined in this
   * library.
   */
  List<ImportElement> _imports;

  /**
   * A list containing specifications of all of the exports defined in this
   * library.
   */
  List<ExportElement> _exports;

  /**
   * A list containing the strongly connected component in the import/export
   * graph in which the current library resides.  Computed on demand, null
   * if not present.  If _libraryCycle is set, then the _libraryCycle field
   * for all libraries reachable from this library in the import/export graph
   * is also set.
   */
  List<LibraryElement> _libraryCycle = null;

  /**
   * A list containing all of the compilation units that are included in this
   * library using a `part` directive.
   */
  List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST;

  /**
   * The element representing the synthetic function `loadLibrary` that is
   * defined for this library, or `null` if the element has not yet been created.
   */
  FunctionElement _loadLibraryFunction;

  @override
  final int nameLength;

  /**
   * The export [Namespace] of this library, `null` if it has not been
   * computed yet.
   */
  Namespace _exportNamespace;

  /**
   * The public [Namespace] of this library, `null` if it has not been
   * computed yet.
   */
  Namespace _publicNamespace;

  /**
   * A bit-encoded form of the capabilities associated with this library.
   */
  int _resolutionCapabilities = 0;

  /**
   * The cached list of prefixes.
   */
  List<PrefixElement> _prefixes;

  /**
   * Initialize a newly created library element in the given [context] to have
   * the given [name] and [offset].
   */
  LibraryElementImpl(this.context, String name, int offset, this.nameLength)
      : resynthesizerContext = null,
        _unlinkedDefiningUnit = null,
        super(name, offset);

  /**
   * Initialize a newly created library element in the given [context] to have
   * the given [name].
   */
  LibraryElementImpl.forNode(this.context, LibraryIdentifier name)
      : nameLength = name != null ? name.length : 0,
        resynthesizerContext = null,
        _unlinkedDefiningUnit = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  LibraryElementImpl.forSerialized(this.context, String name, int offset,
      this.nameLength, this.resynthesizerContext, this._unlinkedDefiningUnit)
      : super.forSerialized(null) {
    _name = name;
    _nameOffset = offset;
    setResolutionCapability(
        LibraryResolutionCapability.resolvedTypeNames, true);
    setResolutionCapability(
        LibraryResolutionCapability.constantExpressions, true);
  }

  @override
  int get codeLength {
    CompilationUnitElement unit = _definingCompilationUnit;
    if (unit is CompilationUnitElementImpl) {
      return unit.codeLength;
    }
    return null;
  }

  @override
  int get codeOffset {
    CompilationUnitElement unit = _definingCompilationUnit;
    if (unit is CompilationUnitElementImpl) {
      return unit.codeOffset;
    }
    return null;
  }

  @override
  CompilationUnitElement get definingCompilationUnit =>
      _definingCompilationUnit;

  /**
   * Set the compilation unit that defines this library to the given compilation
   * [unit].
   */
  void set definingCompilationUnit(CompilationUnitElement unit) {
    assert((unit as CompilationUnitElementImpl).librarySource == unit.source);
    (unit as CompilationUnitElementImpl).enclosingElement = this;
    this._definingCompilationUnit = unit;
  }

  @override
  String get documentationComment {
    if (_unlinkedDefiningUnit != null) {
      return _unlinkedDefiningUnit?.libraryDocumentationComment?.text;
    }
    return super.documentationComment;
  }

  FunctionElement get entryPoint {
    if (resynthesizerContext != null) {
      _entryPoint ??= resynthesizerContext.findEntryPoint();
    }
    return _entryPoint;
  }

  void set entryPoint(FunctionElement entryPoint) {
    _entryPoint = entryPoint;
  }

  @override
  List<LibraryElement> get exportedLibraries {
    HashSet<LibraryElement> libraries = new HashSet<LibraryElement>();
    for (ExportElement element in exports) {
      LibraryElement library = element.exportedLibrary;
      if (library != null) {
        libraries.add(library);
      }
    }
    return libraries.toList(growable: false);
  }

  @override
  Namespace get exportNamespace {
    if (resynthesizerContext != null) {
      _exportNamespace ??= resynthesizerContext.buildExportNamespace();
    }
    return _exportNamespace;
  }

  void set exportNamespace(Namespace exportNamespace) {
    _exportNamespace = exportNamespace;
  }

  @override
  List<ExportElement> get exports {
    if (_unlinkedDefiningUnit != null && _exports == null) {
      List<UnlinkedExportNonPublic> unlinkedNonPublicExports =
          _unlinkedDefiningUnit.exports;
      List<UnlinkedExportPublic> unlinkedPublicExports =
          _unlinkedDefiningUnit.publicNamespace.exports;
      assert(
          _unlinkedDefiningUnit.exports.length == unlinkedPublicExports.length);
      int length = unlinkedNonPublicExports.length;
      if (length != 0) {
        List<ExportElement> exports = new List<ExportElement>(length);
        for (int i = 0; i < length; i++) {
          UnlinkedExportPublic serializedExportPublic =
              unlinkedPublicExports[i];
          UnlinkedExportNonPublic serializedExportNonPublic =
              unlinkedNonPublicExports[i];
          exports[i] = new ExportElementImpl.forSerialized(
              serializedExportPublic, serializedExportNonPublic, library);
        }
        _exports = exports;
      } else {
        _exports = const <ExportElement>[];
      }
    }
    return _exports ?? const <ExportElement>[];
  }

  /**
   * Set the specifications of all of the exports defined in this library to the
   * given list of [exports].
   */
  void set exports(List<ExportElement> exports) {
    _assertNotResynthesized(_unlinkedDefiningUnit);
    for (ExportElement exportElement in exports) {
      (exportElement as ExportElementImpl).enclosingElement = this;
    }
    this._exports = exports;
  }

  @override
  bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI);

  /**
   * Set whether this library has an import of a "dart-ext" URI.
   */
  void set hasExtUri(bool hasExtUri) {
    setModifier(Modifier.HAS_EXT_URI, hasExtUri);
  }

  @override
  bool get hasLoadLibraryFunction {
    if (_definingCompilationUnit.hasLoadLibraryFunction) {
      return true;
    }
    for (int i = 0; i < _parts.length; i++) {
      if (_parts[i].hasLoadLibraryFunction) {
        return true;
      }
    }
    return false;
  }

  @override
  String get identifier => _definingCompilationUnit.source.encoding;

  @override
  List<LibraryElement> get importedLibraries {
    HashSet<LibraryElement> libraries = new HashSet<LibraryElement>();
    for (ImportElement element in imports) {
      LibraryElement library = element.importedLibrary;
      if (library != null) {
        libraries.add(library);
      }
    }
    return libraries.toList(growable: false);
  }

  @override
  List<ImportElement> get imports {
    if (_unlinkedDefiningUnit != null && _imports == null) {
      List<UnlinkedImport> unlinkedImports = _unlinkedDefiningUnit.imports;
      int length = unlinkedImports.length;
      if (length != 0) {
        List<ImportElement> imports = new List<ImportElement>(length);
        LinkedLibrary linkedLibrary = resynthesizerContext.linkedLibrary;
        for (int i = 0; i < length; i++) {
          imports[i] = new ImportElementImpl.forSerialized(
              unlinkedImports[i], linkedLibrary.importDependencies[i], library);
        }
        _imports = imports;
      } else {
        _imports = const <ImportElement>[];
      }
    }
    return _imports ?? ImportElement.EMPTY_LIST;
  }

  /**
   * Set the specifications of all of the imports defined in this library to the
   * given list of [imports].
   */
  void set imports(List<ImportElement> imports) {
    _assertNotResynthesized(_unlinkedDefiningUnit);
    for (ImportElement importElement in imports) {
      (importElement as ImportElementImpl).enclosingElement = this;
      PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl;
      if (prefix != null) {
        prefix.enclosingElement = this;
      }
    }
    this._imports = imports;
    this._prefixes = null;
  }

  @override
  bool get isBrowserApplication =>
      entryPoint != null && isOrImportsBrowserLibrary;

  @override
  bool get isDartAsync => name == "dart.async";

  @override
  bool get isDartCore => name == "dart.core";

  @override
  bool get isInSdk =>
      StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E);

  /**
   * Return `true` if the receiver directly or indirectly imports the
   * 'dart:html' libraries.
   */
  bool get isOrImportsBrowserLibrary {
    List<LibraryElement> visited = new List<LibraryElement>();
    Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
    visited.add(this);
    for (int index = 0; index < visited.length; index++) {
      LibraryElement library = visited[index];
      Source source = library.definingCompilationUnit.source;
      if (source == htmlLibSource) {
        return true;
      }
      for (LibraryElement importedLibrary in library.importedLibraries) {
        if (!visited.contains(importedLibrary)) {
          visited.add(importedLibrary);
        }
      }
      for (LibraryElement exportedLibrary in library.exportedLibraries) {
        if (!visited.contains(exportedLibrary)) {
          visited.add(exportedLibrary);
        }
      }
    }
    return false;
  }

  @override
  bool get isResynthesized {
    return resynthesizerContext != null;
  }

  @override
  ElementKind get kind => ElementKind.LIBRARY;

  @override
  LibraryElement get library => this;

  @override
  List<LibraryElement> get libraryCycle {
    if (_libraryCycle != null) {
      return _libraryCycle;
    }

    // Global counter for this run of the algorithm
    int counter = 0;
    // The discovery times of each library
    Map<LibraryElementImpl, int> indices = {};
    // The set of scc candidates
    Set<LibraryElementImpl> active = new Set();
    // The stack of discovered elements
    List<LibraryElementImpl> stack = [];
    // For a given library that has not yet been processed by this run of the
    // algorithm, compute the strongly connected components.
    int scc(LibraryElementImpl library) {
      int index = counter++;
      int root = index;
      indices[library] = index;
      active.add(library);
      stack.add(library);
      LibraryElementImpl getActualLibrary(LibraryElement lib) {
        // TODO(paulberry): this means that computing a library cycle will be
        // expensive for libraries resynthesized from summaries, since it will
        // require fully resynthesizing all the libraries in the cycle as well
        // as any libraries they import or export.  Try to find a better way.
        if (lib is LibraryElementHandle) {
          return lib.actualElement;
        } else {
          return lib;
        }
      }

      void recurse(LibraryElementImpl child) {
        if (!indices.containsKey(child)) {
          // We haven't visited this child yet, so recurse on the child,
          // returning the lowest numbered node reachable from the child.  If
          // the child can reach a root which is lower numbered than anything
          // we've reached so far, update the root.
          root = min(root, scc(child));
        } else if (active.contains(child)) {
          // The child has been visited, but has not yet been placed into a
          // component.  If the child is higher than anything we've seen so far
          // update the root appropriately.
          root = min(root, indices[child]);
        }
      }

      // Recurse on all of the children in the import/export graph, filtering
      // out those for which library cycles have already been computed.
      library.exportedLibraries
          .map(getActualLibrary)
          .where((l) => l._libraryCycle == null)
          .forEach(recurse);
      library.importedLibraries
          .map(getActualLibrary)
          .where((l) => l._libraryCycle == null)
          .forEach(recurse);

      if (root == index) {
        // This is the root of a strongly connected component.
        // Pop the elements, and share the component across all
        // of the elements.
        List<LibraryElement> component = <LibraryElement>[];
        LibraryElementImpl cur = null;
        do {
          cur = stack.removeLast();
          active.remove(cur);
          component.add(cur);
          cur._libraryCycle = component;
        } while (cur != library);
      }
      return root;
    }

    scc(library);
    return _libraryCycle;
  }

  @override
  FunctionElement get loadLibraryFunction {
    assert(_loadLibraryFunction != null);
    return _loadLibraryFunction;
  }

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedDefiningUnit != null) {
      _metadata ??= _buildAnnotations(
          _definingCompilationUnit as CompilationUnitElementImpl,
          _unlinkedDefiningUnit.libraryAnnotations);
      return _metadata;
    }
    return super.metadata;
  }

  @override
  List<CompilationUnitElement> get parts => _parts;

  /**
   * Set the compilation units that are included in this library using a `part`
   * directive to the given list of [parts].
   */
  void set parts(List<CompilationUnitElement> parts) {
    for (CompilationUnitElement compilationUnit in parts) {
      assert((compilationUnit as CompilationUnitElementImpl).librarySource ==
          source);
      (compilationUnit as CompilationUnitElementImpl).enclosingElement = this;
    }
    this._parts = parts;
  }

  @override
  List<PrefixElement> get prefixes {
    if (_prefixes == null) {
      HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>();
      for (ImportElement element in imports) {
        PrefixElement prefix = element.prefix;
        if (prefix != null) {
          prefixes.add(prefix);
        }
      }
      _prefixes = prefixes.toList(growable: false);
    }
    return _prefixes;
  }

  @override
  Namespace get publicNamespace {
    if (resynthesizerContext != null) {
      _publicNamespace ??= resynthesizerContext.buildPublicNamespace();
    }
    return _publicNamespace;
  }

  void set publicNamespace(Namespace publicNamespace) {
    _publicNamespace = publicNamespace;
  }

  @override
  Source get source {
    if (_definingCompilationUnit == null) {
      return null;
    }
    return _definingCompilationUnit.source;
  }

  @override
  List<CompilationUnitElement> get units {
    List<CompilationUnitElement> units = new List<CompilationUnitElement>();
    units.add(_definingCompilationUnit);
    units.addAll(_parts);
    return units;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);

  /**
   * Create the [FunctionElement] to be returned by [loadLibraryFunction],
   * using types provided by [typeProvider].
   */
  void createLoadLibraryFunction(TypeProvider typeProvider) {
    FunctionElementImpl function =
        new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1);
    function.synthetic = true;
    function.enclosingElement = this;
    function.returnType = typeProvider.futureDynamicType;
    function.type = new FunctionTypeImpl(function);
    _loadLibraryFunction = function;
  }

  @override
  ElementImpl getChild(String identifier) {
    CompilationUnitElementImpl unitImpl = _definingCompilationUnit;
    if (unitImpl.identifier == identifier) {
      return unitImpl;
    }
    for (CompilationUnitElement part in _parts) {
      CompilationUnitElementImpl partImpl = part;
      if (partImpl.identifier == identifier) {
        return partImpl;
      }
    }
    for (ImportElement importElement in imports) {
      ImportElementImpl importElementImpl = importElement;
      if (importElementImpl.identifier == identifier) {
        return importElementImpl;
      }
    }
    for (ExportElement exportElement in exports) {
      ExportElementImpl exportElementImpl = exportElement;
      if (exportElementImpl.identifier == identifier) {
        return exportElementImpl;
      }
    }
    return null;
  }

  @override
  List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) {
    var imports = this.imports;
    int count = imports.length;
    List<ImportElement> importList = new List<ImportElement>();
    for (int i = 0; i < count; i++) {
      if (identical(imports[i].prefix, prefixElement)) {
        importList.add(imports[i]);
      }
    }
    return importList;
  }

  @override
  ClassElement getType(String className) {
    ClassElement type = _definingCompilationUnit.getType(className);
    if (type != null) {
      return type;
    }
    for (CompilationUnitElement part in _parts) {
      type = part.getType(className);
      if (type != null) {
        return type;
      }
    }
    return null;
  }

  /** Given an update to this library which may have added or deleted edges
   * in the import/export graph originating from this node only, remove any
   * cached library cycles in the element model which may have been invalidated.
   */
  void invalidateLibraryCycles() {
    // If we have pre-computed library cycle information, then we must
    // invalidate the information both on this element, and on certain
    // other elements.  Edges originating at this node may have been
    // added or deleted.  A deleted edge that points outside of this cycle
    // cannot change the cycle information for anything outside of this cycle,
    // and so it is sufficient to delete the cached library information on this
    // cycle.  An added edge which points to another node within the cycle
    // only invalidates the cycle.  An added edge which points to a node earlier
    // in the topological sort of cycles induces no invalidation (since there
    // are by definition no back edges from earlier cycles in the topological
    // order, and hence no possible cycle can have been introduced.  The only
    // remaining case is that we have added an edge to a node which is later
    // in the topological sort of cycles.  This can induce cycles, since it
    // represents a new back edge.  It would be sufficient to invalidate the
    // cycle information for all nodes that are between the target and the
    // node in the topological order.  For simplicity, we simply invalidate
    // all nodes which are reachable from the source node.
    // Note that in the invalidation phase, we do not cut off when we encounter
    // a node with no library cycle information, since we do not know whether
    // we are in the case where invalidation has already been performed, or we
    // are in the case where library cycles have simply never been computed from
    // a newly reachable node.
    Set<LibraryElementImpl> active = new HashSet();
    void invalidate(LibraryElement element) {
      LibraryElementImpl library =
          element is LibraryElementHandle ? element.actualElement : element;
      if (active.add(library)) {
        if (library._libraryCycle != null) {
          library._libraryCycle.forEach(invalidate);
          library._libraryCycle = null;
        }
        library.exportedLibraries.forEach(invalidate);
        library.importedLibraries.forEach(invalidate);
      }
    }

    invalidate(this);
  }

  /**
   * Set whether the library has the given [capability] to
   * correspond to the given [value].
   */
  void setResolutionCapability(
      LibraryResolutionCapability capability, bool value) {
    _resolutionCapabilities =
        BooleanArray.set(_resolutionCapabilities, capability.index, value);
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    _definingCompilationUnit?.accept(visitor);
    safelyVisitChildren(exports, visitor);
    safelyVisitChildren(imports, visitor);
    safelyVisitChildren(_parts, visitor);
  }

  /**
   * Return `true` if the [library] has the given [capability].
   */
  static bool hasResolutionCapability(
      LibraryElement library, LibraryResolutionCapability capability) {
    return library is LibraryElementImpl &&
        BooleanArray.get(library._resolutionCapabilities, capability.index);
  }
}

/**
 * Enum of possible resolution capabilities that a [LibraryElementImpl] has.
 */
enum LibraryResolutionCapability {
  /**
   * All elements have their types resolved.
   */
  resolvedTypeNames,

  /**
   * All (potentially) constants expressions are set into corresponding
   * elements.
   */
  constantExpressions,
}

/**
 * The context in which the library is resynthesized.
 */
abstract class LibraryResynthesizerContext {
  /**
   * Return the [LinkedLibrary] that corresponds to the library being
   * resynthesized.
   */
  LinkedLibrary get linkedLibrary;

  /**
   * Return the exported [LibraryElement] for with the given [relativeUri].
   */
  LibraryElement buildExportedLibrary(String relativeUri);

  /**
   * Return the export namespace of the library.
   */
  Namespace buildExportNamespace();

  /**
   * Return the imported [LibraryElement] for the given dependency in the
   * linked library.
   */
  LibraryElement buildImportedLibrary(int dependency);

  /**
   * Return the public namespace of the library.
   */
  Namespace buildPublicNamespace();

  /**
   * Find the entry point of the library.
   */
  FunctionElement findEntryPoint();

  /**
   * Ensure that getters and setters in different units use the same
   * top-level variables.
   */
  void patchTopLevelAccessors();
}

/**
 * A concrete implementation of a [LocalVariableElement].
 */
class LocalVariableElementImpl extends NonParameterVariableElementImpl
    implements LocalVariableElement {
  /**
   * The offset to the beginning of the visible range for this element.
   */
  int _visibleRangeOffset = 0;

  /**
   * The length of the visible range for this element, or `-1` if this element
   * does not have a visible range.
   */
  int _visibleRangeLength = -1;

  /**
   * Initialize a newly created method element to have the given [name] and
   * [offset].
   */
  LocalVariableElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created local variable element to have the given [name].
   */
  LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  LocalVariableElementImpl.forSerialized(UnlinkedVariable unlinkedVariable,
      ExecutableElementImpl enclosingExecutable)
      : super.forSerialized(unlinkedVariable, enclosingExecutable);

  /**
   * Initialize using the given serialized information.
   */
  factory LocalVariableElementImpl.forSerializedFactory(
      UnlinkedVariable unlinkedVariable,
      ExecutableElementImpl enclosingExecutable) {
    if (unlinkedVariable.isConst &&
        unlinkedVariable.initializer?.bodyExpr != null) {
      return new ConstLocalVariableElementImpl.forSerialized(
          unlinkedVariable, enclosingExecutable);
    } else {
      return new LocalVariableElementImpl.forSerialized(
          unlinkedVariable, enclosingExecutable);
    }
  }

  @override
  String get identifier {
    String identifier = super.identifier;
    Element enclosing = this.enclosingElement;
    if (enclosing is ExecutableElement) {
      int id = ElementImpl._findElementIndexUsingIdentical(
          enclosing.localVariables, this);
      identifier += "@$id";
    }
    return identifier;
  }

  @override
  bool get isPotentiallyMutatedInClosure => true;

  @override
  bool get isPotentiallyMutatedInScope => true;

  @override
  ElementKind get kind => ElementKind.LOCAL_VARIABLE;

  @override
  SourceRange get visibleRange {
    if (_unlinkedVariable != null) {
      if (_unlinkedVariable.visibleLength == 0) {
        return null;
      }
      return new SourceRange(
          _unlinkedVariable.visibleOffset, _unlinkedVariable.visibleLength);
    }
    if (_visibleRangeLength < 0) {
      return null;
    }
    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write(type);
    buffer.write(" ");
    buffer.write(displayName);
  }

  @override
  Declaration computeNode() => getNodeMatching(
      (node) => node is DeclaredIdentifier || node is VariableDeclaration);

  /**
   * Set the visible range for this element to the range starting at the given
   * [offset] with the given [length].
   */
  void setVisibleRange(int offset, int length) {
    _assertNotResynthesized(_unlinkedVariable);
    _visibleRangeOffset = offset;
    _visibleRangeLength = length;
  }
}

/**
 * A concrete implementation of a [MethodElement].
 */
class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
  /**
   * Initialize a newly created method element to have the given [name] at the
   * given [offset].
   */
  MethodElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created method element to have the given [name].
   */
  MethodElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  MethodElementImpl.forSerialized(
      UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
      : super.forSerialized(serializedExecutable, enclosingClass);

  /**
   * Set whether this method is abstract.
   */
  void set abstract(bool isAbstract) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.ABSTRACT, isAbstract);
  }

  @override
  List<TypeParameterType> get allEnclosingTypeParameterTypes {
    if (isStatic) {
      return const <TypeParameterType>[];
    }
    return super.allEnclosingTypeParameterTypes;
  }

  @override
  String get displayName {
    String displayName = super.displayName;
    if ("unary-" == displayName) {
      return "-";
    }
    return displayName;
  }

  @override
  ClassElement get enclosingElement => super.enclosingElement as ClassElement;

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
      super.enclosingElement as ClassElementImpl;

  @override
  bool get isOperator {
    String name = displayName;
    if (name.isEmpty) {
      return false;
    }
    int first = name.codeUnitAt(0);
    return !((0x61 <= first && first <= 0x7A) ||
        (0x41 <= first && first <= 0x5A) ||
        first == 0x5F ||
        first == 0x24);
  }

  @override
  bool get isStatic {
    if (serializedExecutable != null) {
      return serializedExecutable.isStatic;
    }
    return hasModifier(Modifier.STATIC);
  }

  @override
  ElementKind get kind => ElementKind.METHOD;

  @override
  String get name {
    String name = super.name;
    if (name == '-' && parameters.isEmpty) {
      return 'unary-';
    }
    return super.name;
  }

  /**
   * Set whether this method is static.
   */
  void set static(bool isStatic) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.STATIC, isStatic);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitMethodElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write(displayName);
    super.appendTo(buffer);
  }

  @override
  MethodDeclaration computeNode() =>
      getNodeMatching((node) => node is MethodDeclaration);
}

/**
 * The constants for all of the modifiers defined by the Dart language and for a
 * few additional flags that are useful.
 *
 * Clients may not extend, implement or mix-in this class.
 */
class Modifier implements Comparable<Modifier> {
  /**
   * Indicates that the modifier 'abstract' was applied to the element.
   */
  static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);

  /**
   * Indicates that an executable element has a body marked as being
   * asynchronous.
   */
  static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1);

  /**
   * Indicates that the modifier 'const' was applied to the element.
   */
  static const Modifier CONST = const Modifier('CONST', 2);

  /**
   * Indicates that the import element represents a deferred library.
   */
  static const Modifier DEFERRED = const Modifier('DEFERRED', 3);

  /**
   * Indicates that a class element was defined by an enum declaration.
   */
  static const Modifier ENUM = const Modifier('ENUM', 4);

  /**
   * Indicates that a class element was defined by an enum declaration.
   */
  static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5);

  /**
   * Indicates that the modifier 'factory' was applied to the element.
   */
  static const Modifier FACTORY = const Modifier('FACTORY', 6);

  /**
   * Indicates that the modifier 'final' was applied to the element.
   */
  static const Modifier FINAL = const Modifier('FINAL', 7);

  /**
   * Indicates that an executable element has a body marked as being a
   * generator.
   */
  static const Modifier GENERATOR = const Modifier('GENERATOR', 8);

  /**
   * Indicates that the pseudo-modifier 'get' was applied to the element.
   */
  static const Modifier GETTER = const Modifier('GETTER', 9);

  /**
   * A flag used for libraries indicating that the defining compilation unit
   * contains at least one import directive whose URI uses the "dart-ext"
   * scheme.
   */
  static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10);

  /**
   * Indicates that the associated element did not have an explicit type
   * associated with it. If the element is an [ExecutableElement], then the
   * type being referred to is the return type.
   */
  static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11);

  /**
   * Indicates that a class is a mixin application.
   */
  static const Modifier MIXIN_APPLICATION =
      const Modifier('MIXIN_APPLICATION', 12);

  /**
   * Indicates that a class contains an explicit reference to 'super'.
   */
  static const Modifier REFERENCES_SUPER =
      const Modifier('REFERENCES_SUPER', 13);

  /**
   * Indicates that the pseudo-modifier 'set' was applied to the element.
   */
  static const Modifier SETTER = const Modifier('SETTER', 14);

  /**
   * Indicates that the modifier 'static' was applied to the element.
   */
  static const Modifier STATIC = const Modifier('STATIC', 15);

  /**
   * Indicates that the element does not appear in the source code but was
   * implicitly created. For example, if a class does not define any
   * constructors, an implicit zero-argument constructor will be created and it
   * will be marked as being synthetic.
   */
  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);

  static const List<Modifier> values = const [
    ABSTRACT,
    ASYNCHRONOUS,
    CONST,
    DEFERRED,
    ENUM,
    EXTERNAL,
    FACTORY,
    FINAL,
    GENERATOR,
    GETTER,
    HAS_EXT_URI,
    IMPLICIT_TYPE,
    MIXIN_APPLICATION,
    REFERENCES_SUPER,
    SETTER,
    STATIC,
    SYNTHETIC
  ];

  /**
   * The name of this modifier.
   */
  final String name;

  /**
   * The ordinal value of the modifier.
   */
  final int ordinal;

  const Modifier(this.name, this.ordinal);

  @override
  int get hashCode => ordinal;

  @override
  int compareTo(Modifier other) => ordinal - other.ordinal;

  @override
  String toString() => name;
}

/**
 * A concrete implementation of a [MultiplyDefinedElement].
 */
class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
  /**
   * The unique integer identifier of this element.
   */
  final int id = ElementImpl._NEXT_ID++;

  /**
   * The analysis context in which the multiply defined elements are defined.
   */
  final AnalysisContext context;

  /**
   * The name of the conflicting elements.
   */
  String _name;

  /**
   * A list containing all of the elements defined in SDK libraries that
   * conflict.
   */
  final List<Element> sdkElements;

  /**
   * A list containing all of the elements defined in non-SDK libraries that
   * conflict.
   */
  final List<Element> nonSdkElements;

  /**
   * Initialize a newly created element in the given [context] to represent a
   * list of conflicting [sdkElements] and [nonSdkElements]. At least one of the
   * lists must contain more than one element.
   */
  MultiplyDefinedElementImpl(
      this.context, this.sdkElements, this.nonSdkElements) {
    if (nonSdkElements.length > 0) {
      _name = nonSdkElements[0].name;
    } else {
      _name = sdkElements[0].name;
    }
  }

  @override
  List<Element> get conflictingElements {
    if (sdkElements.isEmpty) {
      return nonSdkElements;
    } else if (nonSdkElements.isEmpty) {
      return sdkElements;
    }
    List<Element> elements = nonSdkElements.toList();
    elements.addAll(sdkElements);
    return elements;
  }

  @override
  String get displayName => _name;

  @override
  String get documentationComment => null;

  @override
  Element get enclosingElement => null;

  @override
  bool get isDeprecated => false;

  @override
  bool get isFactory => false;

  @override
  bool get isJS => false;

  @override
  bool get isOverride => false;

  @override
  bool get isPrivate {
    String name = displayName;
    if (name == null) {
      return false;
    }
    return Identifier.isPrivateName(name);
  }

  @override
  bool get isProtected => false;

  @override
  bool get isPublic => !isPrivate;

  @override
  bool get isRequired => false;

  @override
  bool get isSynthetic => true;

  @override
  ElementKind get kind => ElementKind.ERROR;

  @override
  LibraryElement get library => null;

  @override
  Source get librarySource => null;

  @override
  ElementLocation get location => null;

  @override
  List<ElementAnnotation> get metadata => const <ElementAnnotation>[];

  @override
  String get name => _name;

  @override
  int get nameLength => displayName != null ? displayName.length : 0;

  @override
  int get nameOffset => -1;

  @override
  Source get source => null;

  @override
  DartType get type => DynamicTypeImpl.instance;

  @override
  CompilationUnit get unit => null;

  @override
  accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this);

  @override
  String computeDocumentationComment() => null;

  @override
  AstNode computeNode() => null;

  @override
  Element/*=E*/ getAncestor/*<E extends Element >*/(
          Predicate<Element> predicate) =>
      null;

  @override
  String getExtendedDisplayName(String shortName) {
    if (shortName != null) {
      return shortName;
    }
    return displayName;
  }

  @override
  bool isAccessibleIn(LibraryElement library) {
    for (Element element in conflictingElements) {
      if (element.isAccessibleIn(library)) {
        return true;
      }
    }
    return false;
  }

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    bool needsSeparator = false;
    void writeList(List<Element> elements) {
      for (Element element in elements) {
        if (needsSeparator) {
          buffer.write(", ");
        } else {
          needsSeparator = true;
        }
        if (element is ElementImpl) {
          element.appendTo(buffer);
        } else {
          buffer.write(element);
        }
      }
    }

    buffer.write("[");
    writeList(nonSdkElements);
    writeList(sdkElements);
    buffer.write("]");
    return buffer.toString();
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    // There are no children to visit
  }

  /**
   * Return an element in the given [context] that represents the fact that the
   * [firstElement] and [secondElement] conflict. (If the elements are the same,
   * then one of the two will be returned directly.)
   */
  static Element fromElements(
      AnalysisContext context, Element firstElement, Element secondElement) {
    Set<Element> sdkElements = new HashSet<Element>.identity();
    Set<Element> nonSdkElements = new HashSet<Element>.identity();
    void add(Element element) {
      if (element != null) {
        if (element is MultiplyDefinedElementImpl) {
          sdkElements.addAll(element.sdkElements);
          nonSdkElements.addAll(element.nonSdkElements);
        } else if (element.library.isInSdk) {
          sdkElements.add(element);
        } else {
          nonSdkElements.add(element);
        }
      }
    }

    add(firstElement);
    add(secondElement);
    int nonSdkCount = nonSdkElements.length;
    if (nonSdkCount == 0) {
      int sdkCount = sdkElements.length;
      if (sdkCount == 0) {
        return null;
      } else if (sdkCount == 1) {
        return sdkElements.first;
      }
    } else if (nonSdkCount == 1) {
      return nonSdkElements.first;
    }
    return new MultiplyDefinedElementImpl(
        context,
        sdkElements.toList(growable: false),
        nonSdkElements.toList(growable: false));
  }
}

/**
 * A [MethodElementImpl], with the additional information of a list of
 * [ExecutableElement]s from which this element was composed.
 */
class MultiplyInheritedMethodElementImpl extends MethodElementImpl
    implements MultiplyInheritedExecutableElement {
  /**
   * A list the array of executable elements that were used to compose this
   * element.
   */
  List<ExecutableElement> _elements = MethodElement.EMPTY_LIST;

  MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
    synthetic = true;
  }

  @override
  List<ExecutableElement> get inheritedElements => _elements;

  void set inheritedElements(List<ExecutableElement> elements) {
    this._elements = elements;
  }
}

/**
 * A [PropertyAccessorElementImpl], with the additional information of a list of
 * [ExecutableElement]s from which this element was composed.
 */
class MultiplyInheritedPropertyAccessorElementImpl
    extends PropertyAccessorElementImpl
    implements MultiplyInheritedExecutableElement {
  /**
   * A list the array of executable elements that were used to compose this
   * element.
   */
  List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST;

  MultiplyInheritedPropertyAccessorElementImpl(Identifier name)
      : super.forNode(name) {
    synthetic = true;
  }

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;

  @override
  List<ExecutableElement> get inheritedElements => _elements;

  void set inheritedElements(List<ExecutableElement> elements) {
    this._elements = elements;
  }
}

/**
 * A [VariableElementImpl], which is not a parameter.
 */
abstract class NonParameterVariableElementImpl extends VariableElementImpl {
  /**
   * The unlinked representation of the variable in the summary.
   */
  final UnlinkedVariable _unlinkedVariable;

  /**
   * Initialize a newly created variable element to have the given [name] and
   * [offset].
   */
  NonParameterVariableElementImpl(String name, int offset)
      : _unlinkedVariable = null,
        super(name, offset);

  /**
   * Initialize a newly created variable element to have the given [name].
   */
  NonParameterVariableElementImpl.forNode(Identifier name)
      : _unlinkedVariable = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  NonParameterVariableElementImpl.forSerialized(
      this._unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(enclosingElement);

  @override
  int get codeLength {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  void set const3(bool isConst) {
    _assertNotResynthesized(_unlinkedVariable);
    super.const3 = isConst;
  }

  @override
  String get documentationComment {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable?.documentationComment?.text;
    }
    return super.documentationComment;
  }

  @override
  void set final2(bool isFinal) {
    _assertNotResynthesized(_unlinkedVariable);
    super.final2 = isFinal;
  }

  @override
  bool get hasImplicitType {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.type == null;
    }
    return super.hasImplicitType;
  }

  @override
  void set hasImplicitType(bool hasImplicitType) {
    _assertNotResynthesized(_unlinkedVariable);
    super.hasImplicitType = hasImplicitType;
  }

  @override
  FunctionElement get initializer {
    if (_unlinkedVariable != null && _initializer == null) {
      UnlinkedExecutable unlinkedInitializer = _unlinkedVariable.initializer;
      if (unlinkedInitializer != null) {
        _initializer = new FunctionElementImpl.forSerialized(
            unlinkedInitializer, this)..synthetic = true;
      } else {
        return null;
      }
    }
    return super.initializer;
  }

  /**
   * Set the function representing this variable's initializer to the given
   * [function].
   */
  void set initializer(FunctionElement function) {
    _assertNotResynthesized(_unlinkedVariable);
    super.initializer = function;
  }

  @override
  bool get isConst {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.isConst;
    }
    return super.isConst;
  }

  @override
  bool get isFinal {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.isFinal;
    }
    return super.isFinal;
  }

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedVariable != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedVariable.annotations);
    }
    return super.metadata;
  }

  @override
  String get name {
    if (_unlinkedVariable != null) {
      return _unlinkedVariable.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedVariable != null) {
      return _unlinkedVariable.nameOffset;
    }
    return offset;
  }

  @override
  DartType get type {
    if (_unlinkedVariable != null && _type == null) {
      _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
              _unlinkedVariable.inferredTypeSlot, typeParameterContext) ??
          enclosingUnit.resynthesizerContext
              .resolveTypeRef(_unlinkedVariable.type, typeParameterContext);
    }
    return super.type;
  }

  void set type(DartType type) {
    _assertNotResynthesized(_unlinkedVariable);
    _type = type;
  }

  /**
   * Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
   */
  UnlinkedConst get _unlinkedConst => _unlinkedVariable?.initializer?.bodyExpr;
}

/**
 * A concrete implementation of a [ParameterElement].
 */
class ParameterElementImpl extends VariableElementImpl
    with ParameterElementMixin
    implements ParameterElement {
  /**
   * The unlinked representation of the parameter in the summary.
   */
  final UnlinkedParam _unlinkedParam;

  /**
   * A list containing all of the parameters defined by this parameter element.
   * There will only be parameters if this parameter is a function typed
   * parameter.
   */
  List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST;

  /**
   * A list containing all of the type parameters defined for this parameter
   * element. There will only be parameters if this parameter is a function
   * typed parameter.
   */
  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;

  /**
   * The kind of this parameter.
   */
  ParameterKind _parameterKind;

  /**
   * The Dart code of the default value.
   */
  String _defaultValueCode;

  /**
   * The offset to the beginning of the visible range for this element.
   */
  int _visibleRangeOffset = 0;

  /**
   * The length of the visible range for this element, or `-1` if this element
   * does not have a visible range.
   */
  int _visibleRangeLength = -1;

  bool _inheritsCovariant = false;

  /**
   * Initialize a newly created parameter element to have the given [name] and
   * [nameOffset].
   */
  ParameterElementImpl(String name, int nameOffset)
      : _unlinkedParam = null,
        super(name, nameOffset);

  /**
   * Initialize a newly created parameter element to have the given [name].
   */
  ParameterElementImpl.forNode(Identifier name)
      : _unlinkedParam = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  ParameterElementImpl.forSerialized(
      this._unlinkedParam, ElementImpl enclosingElement)
      : super.forSerialized(enclosingElement);

  /**
   * Initialize using the given serialized information.
   */
  factory ParameterElementImpl.forSerializedFactory(
      UnlinkedParam unlinkedParameter, ElementImpl enclosingElement,
      {bool synthetic: false}) {
    ParameterElementImpl element;
    if (unlinkedParameter.isInitializingFormal) {
      if (unlinkedParameter.kind == UnlinkedParamKind.required) {
        element = new FieldFormalParameterElementImpl.forSerialized(
            unlinkedParameter, enclosingElement);
      } else {
        element = new DefaultFieldFormalParameterElementImpl.forSerialized(
            unlinkedParameter, enclosingElement);
      }
    } else {
      if (unlinkedParameter.kind == UnlinkedParamKind.required) {
        element = new ParameterElementImpl.forSerialized(
            unlinkedParameter, enclosingElement);
      } else {
        element = new DefaultParameterElementImpl.forSerialized(
            unlinkedParameter, enclosingElement);
      }
    }
    element.synthetic = synthetic;
    return element;
  }

  /**
   * Creates a synthetic parameter with [name], [type] and [kind].
   */
  factory ParameterElementImpl.synthetic(
      String name, DartType type, ParameterKind kind) {
    ParameterElementImpl element = new ParameterElementImpl(name, -1);
    element.type = type;
    element.synthetic = true;
    element.parameterKind = kind;
    return element;
  }

  @override
  int get codeLength {
    if (_unlinkedParam != null) {
      return _unlinkedParam.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedParam != null) {
      return _unlinkedParam.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  void set const3(bool isConst) {
    _assertNotResynthesized(_unlinkedParam);
    super.const3 = isConst;
  }

  @override
  String get defaultValueCode {
    if (_unlinkedParam != null) {
      if (_unlinkedParam.initializer?.bodyExpr == null) {
        return null;
      }
      return _unlinkedParam.defaultValueCode;
    }
    return _defaultValueCode;
  }

  /**
   * Set Dart code of the default value.
   */
  void set defaultValueCode(String defaultValueCode) {
    _assertNotResynthesized(_unlinkedParam);
    this._defaultValueCode = StringUtilities.intern(defaultValueCode);
  }

  @override
  void set final2(bool isFinal) {
    _assertNotResynthesized(_unlinkedParam);
    super.final2 = isFinal;
  }

  @override
  bool get hasImplicitType {
    if (_unlinkedParam != null) {
      return _unlinkedParam.type == null;
    }
    return super.hasImplicitType;
  }

  @override
  void set hasImplicitType(bool hasImplicitType) {
    _assertNotResynthesized(_unlinkedParam);
    super.hasImplicitType = hasImplicitType;
  }

  /**
   * True if this parameter inherits from a covariant parameter. This happens
   * when it overrides a method in a supertype that has a corresponding
   * covariant parameter.
   */
  bool get inheritsCovariant {
    if (_unlinkedParam != null) {
      return enclosingUnit.resynthesizerContext
          .inheritsCovariant(_unlinkedParam.inheritsCovariantSlot);
    } else {
      return _inheritsCovariant;
    }
  }

  /**
   * Record whether or not this parameter inherits from a covariant parameter.
   */
  void set inheritsCovariant(bool value) {
    _assertNotResynthesized(_unlinkedParam);
    _inheritsCovariant = value;
  }

  @override
  FunctionElement get initializer {
    if (_unlinkedParam != null && _initializer == null) {
      UnlinkedExecutable unlinkedInitializer = _unlinkedParam.initializer;
      if (unlinkedInitializer != null) {
        _initializer = new FunctionElementImpl.forSerialized(
            unlinkedInitializer, this)..synthetic = true;
      } else {
        return null;
      }
    }
    return super.initializer;
  }

  /**
   * Set the function representing this variable's initializer to the given
   * [function].
   */
  void set initializer(FunctionElement function) {
    _assertNotResynthesized(_unlinkedParam);
    super.initializer = function;
  }

  @override
  bool get isConst {
    if (_unlinkedParam != null) {
      return false;
    }
    return super.isConst;
  }

  @override
  bool get isCovariant {
    if (inheritsCovariant) {
      return true;
    }
    for (ElementAnnotationImpl annotation in metadata) {
      if (annotation.isCovariant) {
        return true;
      }
    }
    return false;
  }

  @override
  bool get isFinal {
    if (_unlinkedParam != null) {
      return false;
    }
    return super.isFinal;
  }

  @override
  bool get isInitializingFormal => false;

  @override
  bool get isPotentiallyMutatedInClosure => true;

  @override
  bool get isPotentiallyMutatedInScope => true;

  @override
  ElementKind get kind => ElementKind.PARAMETER;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedParam != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedParam.annotations);
    }
    return super.metadata;
  }

  @override
  String get name {
    if (_unlinkedParam != null) {
      return _unlinkedParam.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedParam != null) {
      if (isSynthetic) {
        return -1;
      }
      return _unlinkedParam.nameOffset;
    }
    return offset;
  }

  @override
  ParameterKind get parameterKind {
    if (_unlinkedParam != null && _parameterKind == null) {
      switch (_unlinkedParam.kind) {
        case UnlinkedParamKind.named:
          _parameterKind = ParameterKind.NAMED;
          break;
        case UnlinkedParamKind.positional:
          _parameterKind = ParameterKind.POSITIONAL;
          break;
        case UnlinkedParamKind.required:
          _parameterKind = ParameterKind.REQUIRED;
          break;
      }
    }
    return _parameterKind;
  }

  void set parameterKind(ParameterKind parameterKind) {
    _assertNotResynthesized(_unlinkedParam);
    _parameterKind = parameterKind;
  }

  @override
  List<ParameterElement> get parameters {
    _resynthesizeTypeAndParameters();
    return _parameters;
  }

  /**
   * Set the parameters defined by this executable element to the given
   * [parameters].
   */
  void set parameters(List<ParameterElement> parameters) {
    for (ParameterElement parameter in parameters) {
      (parameter as ParameterElementImpl).enclosingElement = this;
    }
    this._parameters = parameters;
  }

  @override
  DartType get type {
    _resynthesizeTypeAndParameters();
    return super.type;
  }

  @override
  List<TypeParameterElement> get typeParameters => _typeParameters;

  /**
   * Set the type parameters defined by this parameter element to the given
   * [typeParameters].
   */
  void set typeParameters(List<TypeParameterElement> typeParameters) {
    for (TypeParameterElement parameter in typeParameters) {
      (parameter as TypeParameterElementImpl).enclosingElement = this;
    }
    this._typeParameters = typeParameters;
  }

  @override
  SourceRange get visibleRange {
    if (_unlinkedParam != null) {
      if (_unlinkedParam.visibleLength == 0) {
        return null;
      }
      return new SourceRange(
          _unlinkedParam.visibleOffset, _unlinkedParam.visibleLength);
    }
    if (_visibleRangeLength < 0) {
      return null;
    }
    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
  }

  /**
   * Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
   */
  UnlinkedConst get _unlinkedConst => _unlinkedParam?.initializer?.bodyExpr;

  @override
  accept(ElementVisitor visitor) => visitor.visitParameterElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    String left = "";
    String right = "";
    while (true) {
      if (parameterKind == ParameterKind.NAMED) {
        left = "{";
        right = "}";
      } else if (parameterKind == ParameterKind.POSITIONAL) {
        left = "[";
        right = "]";
      } else if (parameterKind == ParameterKind.REQUIRED) {}
      break;
    }
    buffer.write(left);
    appendToWithoutDelimiters(buffer);
    buffer.write(right);
  }

  @override
  FormalParameter computeNode() =>
      getNodeMatching((node) => node is FormalParameter);

  @override
  ElementImpl getChild(String identifier) {
    for (ParameterElement parameter in _parameters) {
      ParameterElementImpl parameterImpl = parameter;
      if (parameterImpl.identifier == identifier) {
        return parameterImpl;
      }
    }
    return null;
  }

  /**
   * Set the visible range for this element to the range starting at the given
   * [offset] with the given [length].
   */
  void setVisibleRange(int offset, int length) {
    _assertNotResynthesized(_unlinkedParam);
    _visibleRangeOffset = offset;
    _visibleRangeLength = length;
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    safelyVisitChildren(parameters, visitor);
  }

  /**
   * If this element is resynthesized, and its type and parameters have not
   * been build yet, build them and remember in the corresponding fields.
   */
  void _resynthesizeTypeAndParameters() {
    if (_unlinkedParam != null && _type == null) {
      if (_unlinkedParam.isFunctionTyped) {
        CompilationUnitElementImpl enclosingUnit = this.enclosingUnit;
        FunctionElementImpl parameterTypeElement =
            new FunctionElementImpl_forFunctionTypedParameter(
                enclosingUnit, this);
        if (!isSynthetic) {
          parameterTypeElement.enclosingElement = this;
        }
        List<ParameterElement> subParameters = ParameterElementImpl
            .resynthesizeList(_unlinkedParam.parameters, this,
                synthetic: isSynthetic);
        if (isSynthetic) {
          parameterTypeElement.parameters = subParameters;
        } else {
          _parameters = subParameters;
          parameterTypeElement.shareParameters(subParameters);
        }
        parameterTypeElement.returnType = enclosingUnit.resynthesizerContext
            .resolveTypeRef(_unlinkedParam.type, typeParameterContext);
        FunctionTypeImpl parameterType =
            new FunctionTypeImpl.elementWithNameAndArgs(parameterTypeElement,
                null, typeParameterContext.allTypeParameterTypes, false);
        parameterTypeElement.type = parameterType;
        _type = parameterType;
      } else {
        _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
                _unlinkedParam.inferredTypeSlot, typeParameterContext) ??
            enclosingUnit.resynthesizerContext
                .resolveTypeRef(_unlinkedParam.type, typeParameterContext);
      }
    }
  }

  /**
   * Create and return [ParameterElement]s for the given [unlinkedParameters].
   */
  static List<ParameterElement> resynthesizeList(
      List<UnlinkedParam> unlinkedParameters, ElementImpl enclosingElement,
      {bool synthetic: false}) {
    int length = unlinkedParameters.length;
    if (length != 0) {
      List<ParameterElement> parameters = new List<ParameterElement>(length);
      for (int i = 0; i < length; i++) {
        parameters[i] = new ParameterElementImpl.forSerializedFactory(
            unlinkedParameters[i], enclosingElement,
            synthetic: synthetic);
      }
      return parameters;
    } else {
      return const <ParameterElement>[];
    }
  }
}

/**
 * The parameter of an implicit setter.
 */
class ParameterElementImpl_ofImplicitSetter extends ParameterElementImpl {
  final PropertyAccessorElementImpl_ImplicitSetter setter;

  ParameterElementImpl_ofImplicitSetter(
      PropertyAccessorElementImpl_ImplicitSetter setter)
      : setter = setter,
        super('_${setter.variable.name}', setter.variable.nameOffset) {
    enclosingElement = setter;
    synthetic = true;
    parameterKind = ParameterKind.REQUIRED;
  }

  @override
  bool get isCovariant {
    if (inheritsCovariant) {
      return true;
    }
    for (ElementAnnotationImpl annotation in setter.variable.metadata) {
      if (annotation.isCovariant) {
        return true;
      }
    }
    return false;
  }

  @override
  DartType get type => setter.variable.type;

  @override
  void set type(DartType type) {
    assert(false); // Should never be called.
  }
}

/**
 * A mixin that provides a common implementation for methods defined in
 * [ParameterElement].
 */
abstract class ParameterElementMixin implements ParameterElement {
  @override
  void appendToWithoutDelimiters(StringBuffer buffer) {
    buffer.write(type);
    buffer.write(" ");
    buffer.write(displayName);
    if (defaultValueCode != null) {
      if (parameterKind == ParameterKind.NAMED) {
        buffer.write(": ");
      }
      if (parameterKind == ParameterKind.POSITIONAL) {
        buffer.write(" = ");
      }
      buffer.write(defaultValueCode);
    }
  }
}

/**
 * A concrete implementation of a [PrefixElement].
 */
class PrefixElementImpl extends ElementImpl implements PrefixElement {
  /**
   * The unlinked representation of the import in the summary.
   */
  final UnlinkedImport _unlinkedImport;

  /**
   * Initialize a newly created method element to have the given [name] and
   * [nameOffset].
   */
  PrefixElementImpl(String name, int nameOffset)
      : _unlinkedImport = null,
        super(name, nameOffset);

  /**
   * Initialize a newly created prefix element to have the given [name].
   */
  PrefixElementImpl.forNode(Identifier name)
      : _unlinkedImport = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  PrefixElementImpl.forSerialized(
      this._unlinkedImport, LibraryElementImpl enclosingLibrary)
      : super.forSerialized(enclosingLibrary);

  @override
  String get displayName => name;

  @override
  LibraryElement get enclosingElement =>
      super.enclosingElement as LibraryElement;

  @override
  String get identifier => "_${super.identifier}";

  @override
  List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;

  @override
  ElementKind get kind => ElementKind.PREFIX;

  @override
  String get name {
    if (_unlinkedImport != null) {
      if (_name == null) {
        LibraryElementImpl library = enclosingElement as LibraryElementImpl;
        int prefixId = _unlinkedImport.prefixReference;
        return _name = library._unlinkedDefiningUnit.references[prefixId].name;
      }
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedImport != null) {
      return _unlinkedImport.prefixOffset;
    }
    return offset;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitPrefixElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write("as ");
    super.appendTo(buffer);
  }
}

/**
 * A concrete implementation of a [PropertyAccessorElement].
 */
class PropertyAccessorElementImpl extends ExecutableElementImpl
    implements PropertyAccessorElement {
  /**
   * The variable associated with this accessor.
   */
  PropertyInducingElement variable;

  /**
   * Initialize a newly created property accessor element to have the given
   * [name] and [offset].
   */
  PropertyAccessorElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created property accessor element to have the given
   * [name].
   */
  PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  PropertyAccessorElementImpl.forSerialized(
      UnlinkedExecutable serializedExecutable, ElementImpl enclosingElement)
      : super.forSerialized(serializedExecutable, enclosingElement);

  /**
   * Initialize a newly created synthetic property accessor element to be
   * associated with the given [variable].
   */
  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
      : super(variable.name, variable.nameOffset) {
    this.variable = variable;
    static = variable.isStatic;
    synthetic = true;
  }

  /**
   * Set whether this accessor is abstract.
   */
  void set abstract(bool isAbstract) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.ABSTRACT, isAbstract);
  }

  @override
  List<TypeParameterType> get allEnclosingTypeParameterTypes {
    if (isStatic) {
      return const <TypeParameterType>[];
    }
    return super.allEnclosingTypeParameterTypes;
  }

  @override
  PropertyAccessorElement get correspondingGetter {
    if (isGetter || variable == null) {
      return null;
    }
    return variable.getter;
  }

  @override
  PropertyAccessorElement get correspondingSetter {
    if (isSetter || variable == null) {
      return null;
    }
    return variable.setter;
  }

  @override
  String get displayName {
    if (serializedExecutable != null && isSetter) {
      String name = serializedExecutable.name;
      assert(name.endsWith('='));
      return name.substring(0, name.length - 1);
    }
    return super.displayName;
  }

  @override
  TypeParameterizedElementMixin get enclosingTypeParameterContext {
    return (enclosingElement as ElementImpl).typeParameterContext;
  }

  /**
   * Set whether this accessor is a getter.
   */
  void set getter(bool isGetter) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.GETTER, isGetter);
  }

  @override
  String get identifier {
    String name = displayName;
    String suffix = isGetter ? "?" : "=";
    return "$name$suffix";
  }

  @override
  bool get isGetter {
    if (serializedExecutable != null) {
      return serializedExecutable.kind == UnlinkedExecutableKind.getter;
    }
    return hasModifier(Modifier.GETTER);
  }

  @override
  bool get isSetter {
    if (serializedExecutable != null) {
      return serializedExecutable.kind == UnlinkedExecutableKind.setter;
    }
    return hasModifier(Modifier.SETTER);
  }

  @override
  bool get isStatic {
    if (serializedExecutable != null) {
      return serializedExecutable.isStatic ||
          variable is TopLevelVariableElement;
    }
    return hasModifier(Modifier.STATIC);
  }

  @override
  ElementKind get kind {
    if (isGetter) {
      return ElementKind.GETTER;
    }
    return ElementKind.SETTER;
  }

  @override
  String get name {
    if (serializedExecutable != null) {
      return serializedExecutable.name;
    }
    if (isSetter) {
      return "${super.name}=";
    }
    return super.name;
  }

  /**
   * Set whether this accessor is a setter.
   */
  void set setter(bool isSetter) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.SETTER, isSetter);
  }

  /**
   * Set whether this accessor is static.
   */
  void set static(bool isStatic) {
    _assertNotResynthesized(serializedExecutable);
    setModifier(Modifier.STATIC, isStatic);
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write(isGetter ? "get " : "set ");
    buffer.write(variable.displayName);
    super.appendTo(buffer);
  }

  @override
  AstNode computeNode() {
    if (isSynthetic) {
      return null;
    }
    if (enclosingElement is ClassElement) {
      return getNodeMatching((node) => node is MethodDeclaration);
    } else if (enclosingElement is CompilationUnitElement) {
      return getNodeMatching((node) => node is FunctionDeclaration);
    }
    return null;
  }
}

/**
 * Implicit getter for a [PropertyInducingElementImpl].
 */
class PropertyAccessorElementImpl_ImplicitGetter
    extends PropertyAccessorElementImpl {
  /**
   * Create the implicit getter and bind it to the [property].
   */
  PropertyAccessorElementImpl_ImplicitGetter(
      PropertyInducingElementImpl property)
      : super.forVariable(property) {
    property.getter = this;
    enclosingElement = property.enclosingElement;
  }

  @override
  bool get hasImplicitReturnType => variable.hasImplicitType;

  @override
  bool get isGetter => true;

  @override
  DartType get returnType => variable.type;

  @override
  void set returnType(DartType returnType) {
    assert(false); // Should never be called.
  }

  @override
  FunctionType get type {
    return _type ??= new FunctionTypeImpl(this);
  }

  @override
  void set type(FunctionType type) {
    assert(false); // Should never be called.
  }
}

/**
 * Implicit setter for a [PropertyInducingElementImpl].
 */
class PropertyAccessorElementImpl_ImplicitSetter
    extends PropertyAccessorElementImpl {
  /**
   * Create the implicit setter and bind it to the [property].
   */
  PropertyAccessorElementImpl_ImplicitSetter(
      PropertyInducingElementImpl property)
      : super.forVariable(property) {
    property.setter = this;
  }

  @override
  bool get isSetter => true;

  @override
  List<ParameterElement> get parameters {
    return _parameters ??= <ParameterElement>[
      new ParameterElementImpl_ofImplicitSetter(this)
    ];
  }

  @override
  DartType get returnType => VoidTypeImpl.instance;

  @override
  void set returnType(DartType returnType) {
    assert(false); // Should never be called.
  }

  @override
  FunctionType get type {
    return _type ??= new FunctionTypeImpl(this);
  }

  @override
  void set type(FunctionType type) {
    assert(false); // Should never be called.
  }
}

/**
 * A concrete implementation of a [PropertyInducingElement].
 */
abstract class PropertyInducingElementImpl
    extends NonParameterVariableElementImpl implements PropertyInducingElement {
  /**
   * The getter associated with this element.
   */
  PropertyAccessorElement getter;

  /**
   * The setter associated with this element, or `null` if the element is
   * effectively `final` and therefore does not have a setter associated with
   * it.
   */
  PropertyAccessorElement setter;

  /**
   * The propagated type of this variable, or `null` if type propagation has not
   * been performed.
   */
  DartType _propagatedType;

  /**
   * Initialize a newly created synthetic element to have the given [name] and
   * [offset].
   */
  PropertyInducingElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created element to have the given [name].
   */
  PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  PropertyInducingElementImpl.forSerialized(
      UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedVariable, enclosingElement);

  @override
  DartType get propagatedType {
    if (_unlinkedVariable != null && _propagatedType == null) {
      _propagatedType = enclosingUnit.resynthesizerContext.resolveLinkedType(
          _unlinkedVariable.propagatedTypeSlot, typeParameterContext);
    }
    return _propagatedType;
  }

  void set propagatedType(DartType propagatedType) {
    _assertNotResynthesized(_unlinkedVariable);
    _propagatedType = propagatedType;
  }
}

/**
 * The context in which elements are resynthesized.
 */
abstract class ResynthesizerContext {
  /**
   * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
   */
  ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc);

  /**
   * Build [Expression] for the given [UnlinkedConst].
   */
  Expression buildExpression(ElementImpl context, UnlinkedConst uc);

  /**
   * Build explicit top-level property accessors.
   */
  UnitExplicitTopLevelAccessors buildTopLevelAccessors();

  /**
   * Build explicit top-level variables.
   */
  UnitExplicitTopLevelVariables buildTopLevelVariables();

  /**
   * Return `true` if the given parameter [slot] inherits `@covariant` behavior.
   */
  bool inheritsCovariant(int slot);

  /**
   * Return `true` if the given const constructor [slot] is a part of a cycle.
   */
  bool isInConstCycle(int slot);

  /**
   * Resolve an [EntityRef] into a constructor.  If the reference is
   * unresolved, return `null`.
   */
  ConstructorElement resolveConstructorRef(
      TypeParameterizedElementMixin typeParameterContext, EntityRef entry);

  /**
   * Build the appropriate [DartType] object corresponding to a slot id in the
   * [LinkedUnit.types] table.
   */
  DartType resolveLinkedType(
      int slot, TypeParameterizedElementMixin typeParameterContext);

  /**
   * Resolve an [EntityRef] into a type.  If the reference is
   * unresolved, return [DynamicTypeImpl.instance].
   *
   * TODO(paulberry): or should we have a class representing an
   * unresolved type, for consistency with the full element model?
   */
  DartType resolveTypeRef(
      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
      {bool defaultVoid: false, bool instantiateToBoundsAllowed: true});
}

/**
 * A concrete implementation of a [ShowElementCombinator].
 */
class ShowElementCombinatorImpl implements ShowElementCombinator {
  /**
   * The unlinked representation of the combinator in the summary.
   */
  final UnlinkedCombinator _unlinkedCombinator;

  /**
   * The names that are to be made visible in the importing library if they are
   * defined in the imported library.
   */
  List<String> _shownNames;

  /**
   * The offset of the character immediately following the last character of
   * this node.
   */
  int _end = -1;

  /**
   * The offset of the 'show' keyword of this element.
   */
  int _offset = 0;

  ShowElementCombinatorImpl() : _unlinkedCombinator = null;

  /**
   * Initialize using the given serialized information.
   */
  ShowElementCombinatorImpl.forSerialized(this._unlinkedCombinator);

  @override
  int get end {
    if (_unlinkedCombinator != null) {
      return _unlinkedCombinator.end;
    }
    return _end;
  }

  void set end(int end) {
    _assertNotResynthesized(_unlinkedCombinator);
    _end = end;
  }

  @override
  int get offset {
    if (_unlinkedCombinator != null) {
      return _unlinkedCombinator.offset;
    }
    return _offset;
  }

  void set offset(int offset) {
    _assertNotResynthesized(_unlinkedCombinator);
    _offset = offset;
  }

  @override
  List<String> get shownNames {
    if (_unlinkedCombinator != null) {
      _shownNames ??= _unlinkedCombinator.shows.toList(growable: false);
    }
    return _shownNames ?? const <String>[];
  }

  void set shownNames(List<String> shownNames) {
    _assertNotResynthesized(_unlinkedCombinator);
    _shownNames = shownNames;
  }

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    buffer.write("show ");
    int count = shownNames.length;
    for (int i = 0; i < count; i++) {
      if (i > 0) {
        buffer.write(", ");
      }
      buffer.write(shownNames[i]);
    }
    return buffer.toString();
  }
}

/**
 * A concrete implementation of a [TopLevelVariableElement].
 */
class TopLevelVariableElementImpl extends PropertyInducingElementImpl
    implements TopLevelVariableElement {
  /**
   * Initialize a newly created synthetic top-level variable element to have the
   * given [name] and [offset].
   */
  TopLevelVariableElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created top-level variable element to have the given
   * [name].
   */
  TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  TopLevelVariableElementImpl.forSerialized(
      UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
      : super.forSerialized(unlinkedVariable, enclosingElement);

  @override
  bool get isStatic => true;

  @override
  ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;

  @override
  accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);

  @override
  VariableDeclaration computeNode() =>
      getNodeMatching((node) => node is VariableDeclaration);
}

/**
 * A concrete implementation of a [TypeParameterElement].
 */
class TypeParameterElementImpl extends ElementImpl
    implements TypeParameterElement {
  /**
   * The unlinked representation of the type parameter in the summary.
   */
  final UnlinkedTypeParam _unlinkedTypeParam;

  /**
   * The number of type parameters whose scope overlaps this one, and which are
   * declared earlier in the file.
   *
   * TODO(scheglov) make private?
   */
  final int nestingLevel;

  /**
   * The type defined by this type parameter.
   */
  TypeParameterType _type;

  /**
   * The type representing the bound associated with this parameter, or `null`
   * if this parameter does not have an explicit bound.
   */
  DartType _bound;

  /**
   * Initialize a newly created method element to have the given [name] and
   * [offset].
   */
  TypeParameterElementImpl(String name, int offset)
      : _unlinkedTypeParam = null,
        nestingLevel = null,
        super(name, offset);

  /**
   * Initialize a newly created type parameter element to have the given [name].
   */
  TypeParameterElementImpl.forNode(Identifier name)
      : _unlinkedTypeParam = null,
        nestingLevel = null,
        super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  TypeParameterElementImpl.forSerialized(this._unlinkedTypeParam,
      TypeParameterizedElementMixin enclosingElement, this.nestingLevel)
      : super.forSerialized(enclosingElement);

  /**
   * Initialize a newly created synthetic type parameter element to have the
   * given [name], and with [synthetic] set to true.
   */
  TypeParameterElementImpl.synthetic(String name)
      : _unlinkedTypeParam = null,
        nestingLevel = null,
        super(name, -1) {
    synthetic = true;
  }

  DartType get bound {
    if (_unlinkedTypeParam != null) {
      if (_unlinkedTypeParam.bound == null) {
        return null;
      }
      return _bound ??= enclosingUnit.resynthesizerContext.resolveTypeRef(
          _unlinkedTypeParam.bound, enclosingElement,
          instantiateToBoundsAllowed: false);
    }
    return _bound;
  }

  void set bound(DartType bound) {
    _assertNotResynthesized(_unlinkedTypeParam);
    _bound = bound;
  }

  @override
  int get codeLength {
    if (_unlinkedTypeParam != null) {
      return _unlinkedTypeParam.codeRange?.length;
    }
    return super.codeLength;
  }

  @override
  int get codeOffset {
    if (_unlinkedTypeParam != null) {
      return _unlinkedTypeParam.codeRange?.offset;
    }
    return super.codeOffset;
  }

  @override
  String get displayName => name;

  @override
  ElementKind get kind => ElementKind.TYPE_PARAMETER;

  @override
  List<ElementAnnotation> get metadata {
    if (_unlinkedTypeParam != null) {
      return _metadata ??=
          _buildAnnotations(enclosingUnit, _unlinkedTypeParam.annotations);
    }
    return super.metadata;
  }

  @override
  String get name {
    if (_unlinkedTypeParam != null) {
      return _unlinkedTypeParam.name;
    }
    return super.name;
  }

  @override
  int get nameOffset {
    int offset = super.nameOffset;
    if (offset == 0 && _unlinkedTypeParam != null) {
      return _unlinkedTypeParam.nameOffset;
    }
    return offset;
  }

  TypeParameterType get type {
    if (_unlinkedTypeParam != null) {
      _type ??= new TypeParameterTypeImpl(this);
    }
    return _type;
  }

  void set type(TypeParameterType type) {
    _type = type;
  }

  @override
  accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write(displayName);
    if (bound != null) {
      buffer.write(" extends ");
      buffer.write(bound);
    }
  }
}

/**
 * Mixin representing an element which can have type parameters.
 */
abstract class TypeParameterizedElementMixin
    implements TypeParameterizedElement, ElementImpl {
  int _nestingLevel;
  List<TypeParameterElement> _typeParameterElements;
  List<TypeParameterType> _typeParameterTypes;
  List<TypeParameterType> _allTypeParameterTypes;

  /**
   * Return all type parameter types of the element that encloses element.
   * Not `null`, but might be empty for top-level and static class members.
   */
  List<TypeParameterType> get allEnclosingTypeParameterTypes {
    return enclosingTypeParameterContext?.allTypeParameterTypes ??
        const <TypeParameterType>[];
  }

  /**
   * Return all type parameter types of this element.
   */
  List<TypeParameterType> get allTypeParameterTypes {
    if (_allTypeParameterTypes == null) {
      _allTypeParameterTypes = <TypeParameterType>[];
      // The most logical order would be (enclosing, this).
      // But we have to have it like this to be consistent with (inconsistent
      // by itself) element builder for generic functions.
      _allTypeParameterTypes.addAll(typeParameterTypes);
      _allTypeParameterTypes.addAll(allEnclosingTypeParameterTypes);
    }
    return _allTypeParameterTypes;
  }

  /**
   * Get the type parameter context enclosing this one, if any.
   */
  TypeParameterizedElementMixin get enclosingTypeParameterContext;

  /**
   * The unit in which this element is resynthesized.
   */
  CompilationUnitElementImpl get enclosingUnit;

  /**
   * Find out how many type parameters are in scope in this context.
   */
  int get typeParameterNestingLevel =>
      _nestingLevel ??= unlinkedTypeParams.length +
          (enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0);

  List<TypeParameterElement> get typeParameters {
    if (_typeParameterElements == null) {
      int enclosingNestingLevel =
          enclosingTypeParameterContext?.typeParameterNestingLevel ?? 0;
      int numTypeParameters = unlinkedTypeParams.length;
      _typeParameterElements =
          new List<TypeParameterElement>(numTypeParameters);
      for (int i = 0; i < numTypeParameters; i++) {
        _typeParameterElements[i] = new TypeParameterElementImpl.forSerialized(
            unlinkedTypeParams[i], this, enclosingNestingLevel + i);
      }
    }
    return _typeParameterElements;
  }

  /**
   * Get a list of [TypeParameterType] objects corresponding to the
   * element's type parameters.
   */
  List<TypeParameterType> get typeParameterTypes {
    return _typeParameterTypes ??= typeParameters
        .map((TypeParameterElement e) => e.type)
        .toList(growable: false);
  }

  /**
   * Get the [UnlinkedTypeParam]s representing the type parameters declared by
   * this element.
   *
   * TODO(scheglov) make private after switching linker to Impl
   */
  List<UnlinkedTypeParam> get unlinkedTypeParams;

  /**
   * Convert the given [index] into a type parameter type.
   */
  TypeParameterType getTypeParameterType(int index) {
    List<TypeParameterType> types = typeParameterTypes;
    if (index <= types.length) {
      return types[types.length - index];
    } else if (enclosingTypeParameterContext != null) {
      return enclosingTypeParameterContext
          .getTypeParameterType(index - types.length);
    } else {
      // If we get here, it means that a summary contained a type parameter index
      // that was out of range.
      throw new RangeError('Invalid type parameter index');
    }
  }

  /**
   * Find out if the given [typeParameter] is in scope in this context.
   */
  bool isTypeParameterInScope(TypeParameterElement typeParameter) {
    if (typeParameter.enclosingElement == this) {
      return true;
    } else if (enclosingTypeParameterContext != null) {
      return enclosingTypeParameterContext
          .isTypeParameterInScope(typeParameter);
    } else {
      return false;
    }
  }
}

/**
 * Container with information about explicit top-level property accessors and
 * corresponding implicit top-level variables.
 */
class UnitExplicitTopLevelAccessors {
  final List<PropertyAccessorElementImpl> accessors =
      <PropertyAccessorElementImpl>[];
  final List<TopLevelVariableElementImpl> implicitVariables =
      <TopLevelVariableElementImpl>[];
}

/**
 * Container with information about explicit top-level variables and
 * corresponding implicit top-level property accessors.
 */
class UnitExplicitTopLevelVariables {
  final List<TopLevelVariableElementImpl> variables;
  final List<PropertyAccessorElementImpl> implicitAccessors =
      <PropertyAccessorElementImpl>[];

  UnitExplicitTopLevelVariables(int numberOfVariables)
      : variables = numberOfVariables != 0
            ? new List<TopLevelVariableElementImpl>(numberOfVariables)
            : const <TopLevelVariableElementImpl>[];
}

/**
 * A concrete implementation of a [UriReferencedElement].
 */
abstract class UriReferencedElementImpl extends ElementImpl
    implements UriReferencedElement {
  /**
   * The offset of the URI in the file, or `-1` if this node is synthetic.
   */
  int _uriOffset = -1;

  /**
   * The offset of the character immediately following the last character of
   * this node's URI, or `-1` if this node is synthetic.
   */
  int _uriEnd = -1;

  /**
   * The URI that is specified by this directive.
   */
  String _uri;

  /**
   * Initialize a newly created import element to have the given [name] and
   * [offset]. The offset may be `-1` if the element is synthetic.
   */
  UriReferencedElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize using the given serialized information.
   */
  UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
      : super.forSerialized(enclosingElement);

  /**
   * Return the URI that is specified by this directive.
   */
  String get uri => _uri;

  /**
   * Set the URI that is specified by this directive to be the given [uri].
   */
  void set uri(String uri) {
    _uri = uri;
  }

  /**
   * Return the offset of the character immediately following the last character
   * of this node's URI, or `-1` if this node is synthetic.
   */
  int get uriEnd => _uriEnd;

  /**
   * Set the offset of the character immediately following the last character of
   * this node's URI to the given [offset].
   */
  void set uriEnd(int offset) {
    _uriEnd = offset;
  }

  /**
   * Return the offset of the URI in the file, or `-1` if this node is synthetic.
   */
  int get uriOffset => _uriOffset;

  /**
   * Set the offset of the URI in the file to the given [offset].
   */
  void set uriOffset(int offset) {
    _uriOffset = offset;
  }

  String _selectUri(
      String defaultUri, List<UnlinkedConfiguration> configurations) {
    for (UnlinkedConfiguration configuration in configurations) {
      if (context.declaredVariables.get(configuration.name) ==
          configuration.value) {
        return configuration.uri;
      }
    }
    return defaultUri;
  }
}

/**
 * A concrete implementation of a [VariableElement].
 */
abstract class VariableElementImpl extends ElementImpl
    implements VariableElement {
  /**
   * The declared type of this variable.
   */
  DartType _type;

  /**
   * A synthetic function representing this variable's initializer, or `null` if
   * this variable does not have an initializer.
   */
  FunctionElement _initializer;

  /**
   * Initialize a newly created variable element to have the given [name] and
   * [offset].
   */
  VariableElementImpl(String name, int offset) : super(name, offset);

  /**
   * Initialize a newly created variable element to have the given [name].
   */
  VariableElementImpl.forNode(Identifier name) : super.forNode(name);

  /**
   * Initialize using the given serialized information.
   */
  VariableElementImpl.forSerialized(ElementImpl enclosingElement)
      : super.forSerialized(enclosingElement);

  /**
   * Set whether this variable is const.
   */
  void set const3(bool isConst) {
    setModifier(Modifier.CONST, isConst);
  }

  /**
   * If this element represents a constant variable, and it has an initializer,
   * a copy of the initializer for the constant.  Otherwise `null`.
   *
   * Note that in correct Dart code, all constant variables must have
   * initializers.  However, analyzer also needs to handle incorrect Dart code,
   * in which case there might be some constant variables that lack
   * initializers.
   */
  Expression get constantInitializer => null;

  @override
  DartObject get constantValue => evaluationResult?.value;

  @override
  String get displayName => name;

  /**
   * Return the result of evaluating this variable's initializer as a
   * compile-time constant expression, or `null` if this variable is not a
   * 'const' variable, if it does not have an initializer, or if the compilation
   * unit containing the variable has not been resolved.
   */
  EvaluationResultImpl get evaluationResult => null;

  /**
   * Set the result of evaluating this variable's initializer as a compile-time
   * constant expression to the given [result].
   */
  void set evaluationResult(EvaluationResultImpl result) {
    throw new StateError(
        "Invalid attempt to set a compile-time constant result");
  }

  /**
   * Set whether this variable is final.
   */
  void set final2(bool isFinal) {
    setModifier(Modifier.FINAL, isFinal);
  }

  @override
  bool get hasImplicitType {
    return hasModifier(Modifier.IMPLICIT_TYPE);
  }

  /**
   * Set whether this variable element has an implicit type.
   */
  void set hasImplicitType(bool hasImplicitType) {
    setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType);
  }

  @override
  FunctionElement get initializer => _initializer;

  /**
   * Set the function representing this variable's initializer to the given
   * [function].
   */
  void set initializer(FunctionElement function) {
    if (function != null) {
      (function as FunctionElementImpl).enclosingElement = this;
    }
    this._initializer = function;
  }

  @override
  bool get isConst {
    return hasModifier(Modifier.CONST);
  }

  @override
  bool get isFinal {
    return hasModifier(Modifier.FINAL);
  }

  @override
  bool get isPotentiallyMutatedInClosure => false;

  @override
  bool get isPotentiallyMutatedInScope => false;

  @override
  bool get isStatic => hasModifier(Modifier.STATIC);

  @override
  DartType get type => _type;

  void set type(DartType type) {
    _type = type;
  }

  @override
  void appendTo(StringBuffer buffer) {
    buffer.write(type);
    buffer.write(" ");
    buffer.write(displayName);
  }

  @override
  DartObject computeConstantValue() => null;

  @override
  void visitChildren(ElementVisitor visitor) {
    super.visitChildren(visitor);
    _initializer?.accept(visitor);
  }
}

/**
 * A visitor that visit all the elements recursively and fill the given [map].
 */
class _BuildOffsetToElementMap extends GeneralizingElementVisitor {
  final Map<int, Element> map;

  _BuildOffsetToElementMap(this.map);

  @override
  void visitElement(Element element) {
    int offset = element.nameOffset;
    if (offset != -1) {
      map[offset] = element;
    }
    super.visitElement(element);
  }
}
