// Copyright (c) 2012, 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 elements;

import '../common.dart';
import '../common/resolution.dart' show Resolution;
import '../compiler.dart' show Compiler;
import '../constants/constructors.dart';
import '../constants/expressions.dart';
import '../core_types.dart' show CoreClasses;
import '../dart_types.dart';
import '../ordered_typeset.dart' show OrderedTypeSet;
import '../resolution/scope.dart' show Scope;
import '../resolution/tree_elements.dart' show TreeElements;
import '../script.dart';
import '../tokens/token.dart'
    show Token, isUserDefinableOperator, isMinusOperator;
import '../tree/tree.dart';
import '../util/characters.dart' show $_;
import '../util/util.dart';
import 'entities.dart';
import 'visitor.dart' show ElementVisitor;

part 'names.dart';

const int STATE_NOT_STARTED = 0;
const int STATE_STARTED = 1;
const int STATE_DONE = 2;

class ElementCategory {
  /**
   * Represents things that we don't expect to find when looking in a
   * scope.
   */
  static const int NONE = 0;

  /** Field, parameter, or variable. */
  static const int VARIABLE = 1;

  /** Function, method, or foreign function. */
  static const int FUNCTION = 2;

  static const int CLASS = 4;

  static const int PREFIX = 8;

  /** Constructor or factory. */
  static const int FACTORY = 16;

  static const int ALIAS = 32;

  static const int SUPER = 64;

  /** Type variable */
  static const int TYPE_VARIABLE = 128;

  static const int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE;
}

class ElementKind {
  final String id;
  final int category;

  const ElementKind(String this.id, this.category);

  static const ElementKind VARIABLE =
      const ElementKind('variable', ElementCategory.VARIABLE);
  static const ElementKind PARAMETER =
      const ElementKind('parameter', ElementCategory.VARIABLE);
  // Parameters in constructors that directly initialize fields. For example:
  // [:A(this.field):].
  static const ElementKind INITIALIZING_FORMAL =
      const ElementKind('initializing_formal', ElementCategory.VARIABLE);
  static const ElementKind FUNCTION =
      const ElementKind('function', ElementCategory.FUNCTION);
  static const ElementKind CLASS =
      const ElementKind('class', ElementCategory.CLASS);
  static const ElementKind GENERATIVE_CONSTRUCTOR =
      const ElementKind('generative_constructor', ElementCategory.FACTORY);
  static const ElementKind FACTORY_CONSTRUCTOR =
      const ElementKind('factory_constructor', ElementCategory.FACTORY);
  static const ElementKind FIELD =
      const ElementKind('field', ElementCategory.VARIABLE);
  static const ElementKind GENERATIVE_CONSTRUCTOR_BODY =
      const ElementKind('generative_constructor_body', ElementCategory.NONE);
  static const ElementKind COMPILATION_UNIT =
      const ElementKind('compilation_unit', ElementCategory.NONE);
  static const ElementKind GETTER =
      const ElementKind('getter', ElementCategory.NONE);
  static const ElementKind SETTER =
      const ElementKind('setter', ElementCategory.NONE);
  static const ElementKind TYPE_VARIABLE =
      const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE);
  static const ElementKind ABSTRACT_FIELD =
      const ElementKind('abstract_field', ElementCategory.VARIABLE);
  static const ElementKind LIBRARY =
      const ElementKind('library', ElementCategory.NONE);
  static const ElementKind IMPORT =
      const ElementKind('import', ElementCategory.NONE);
  static const ElementKind EXPORT =
      const ElementKind('export', ElementCategory.NONE);
  static const ElementKind PREFIX =
      const ElementKind('prefix', ElementCategory.PREFIX);
  static const ElementKind TYPEDEF =
      const ElementKind('typedef', ElementCategory.ALIAS);

  static const ElementKind AMBIGUOUS =
      const ElementKind('ambiguous', ElementCategory.NONE);
  static const ElementKind WARN_ON_USE =
      const ElementKind('warn_on_use', ElementCategory.NONE);
  static const ElementKind ERROR =
      const ElementKind('error', ElementCategory.NONE);

  toString() => id;
}

/// Abstract interface for entities.
///
/// Implement this directly if the entity is not a Dart language entity.
/// Entities defined within the Dart language should implement [Element].
///
/// For instance, the JavaScript backend need to create synthetic variables for
/// calling intercepted classes and such variables do not correspond to an
/// entity in the Dart source code nor in the terminology of the Dart language
/// and should therefore implement [Entity] directly.
abstract class Entity implements Spannable {
  String get name;
}

/**
 * A declared element of a program.
 *
 * The declared elements of a program include classes, methods,
 * fields, variables, parameters, etc.
 *
 * Sometimes it makes sense to construct "synthetic" elements that
 * have not been declared anywhere in a program, for example, there
 * are elements corresponding to "dynamic", "null", and unresolved
 * references.
 *
 * Elements are distinct from types ([DartType]). For example, there
 * is one declaration of the class List, but several related types,
 * for example, List, List<int>, List<String>, etc.
 *
 * Elements are distinct from AST nodes ([Node]), and there normally is a
 * one-to-one correspondence between an AST node and an element
 * (except that not all kinds of AST nodes have an associated
 * element).
 *
 * AST nodes represent precisely what is written in source code, for
 * example, when a user writes "class MyClass {}", the corresponding
 * AST node does not have a superclass. On the other hand, the
 * corresponding element (once fully resolved) will record the
 * information about the implicit superclass as defined by the
 * language semantics.
 *
 * Generally, the contents of a method are represented as AST nodes
 * without additional elements, but things like local functions, local
 * variables, and labels have a corresponding element.
 *
 * We generally say that scanning, parsing, resolution, and type
 * checking comprise the "front-end" of the compiler. The "back-end"
 * includes things like SSA graph construction, optimizations, and
 * code generation.
 *
 * The front-end data structures are designed to be reusable by
 * several back-ends.  For example, we may want to support emitting
 * minified Dart and JavaScript code in one go.  Also, we're planning
 * on adding an incremental compilation server that should be able to
 * reuse elements between compilations.  So to keep things simple, it
 * is best if the backends avoid setting state directly in elements.
 * It is better to keep such state in a table on the side.
 */
abstract class Element implements Entity {
  String get name;
  ElementKind get kind;
  Element get enclosingElement;
  Iterable<MetadataAnnotation> get metadata;

  /// `true` if this element is a library.
  bool get isLibrary;

  /// `true` if this element is an import declaration.
  bool get isImport => kind == ElementKind.IMPORT;

  /// `true` if this element is an export declaration.
  bool get isExport => kind == ElementKind.EXPORT;

  /// `true` if this element is a compilation unit.
  bool get isCompilationUnit;

  /// `true` if this element is defines the scope of prefix used by one or
  /// more import declarations.
  bool get isPrefix;

  /// `true` if this element is a class declaration or a mixin application.
  bool get isClass;

  /// `true` if this element is a type variable declaration.
  bool get isTypeVariable;

  /// `true` if this element is a typedef declaration.
  bool get isTypedef;

  /// `true` if this element is a top level function, static or instance
  /// method, local function or closure defined by a function expression.
  ///
  /// This property is `true` for operator methods but `false` for getter and
  /// setter methods, and generative and factory constructors.
  ///
  /// See also [isConstructor], [isGenerativeConstructor], and
  /// [isFactoryConstructor] for constructor properties, and [isAccessor],
  /// [isGetter] and [isSetter] for getter/setter properties.
  bool get isFunction;

  /// `true` if this element is an operator method.
  bool get isOperator;

  /// `true` if this element is an accessor, that is either an explicit
  /// getter or an explicit setter.
  bool get isAccessor;

  /// `true` if this element is an explicit getter method.
  bool get isGetter;

  /// `true` if this element is an explicit setter method.
  bool get isSetter;

  /// `true` if this element is a generative or factory constructor.
  bool get isConstructor;

  /// `true` if this element is a generative constructor, potentially
  /// redirecting.
  bool get isGenerativeConstructor;

  /// `true` if this element is the body of a generative constructor.
  ///
  /// This is a synthetic element kind used only by the JavaScript backend.
  bool get isGenerativeConstructorBody;

  /// `true` if this element is a factory constructor,
  /// potentially redirecting.
  bool get isFactoryConstructor;

  /// `true` if this element is a local variable.
  bool get isVariable;

  /// `true` if this element is a top level variable, static or instance field.
  bool get isField;

  /// `true` if this element is the abstract field implicitly defined by an
  /// explicit getter and/or setter.
  bool get isAbstractField;

  /// `true` if this element is a formal parameter from a constructor,
  /// a method, a typedef declaration, or from an inlined function typed
  /// parameter.
  ///
  /// This property is `false` if this element is an initializing formal.
  /// See [isInitializingFormal].
  bool get isRegularParameter;

  /// `true` if this element is an initializing formal of constructor, that
  /// is a formal of the form `this.foo`.
  bool get isInitializingFormal;

  /// `true` if this element is a formal parameter, either regular or
  /// initializing.
  bool get isParameter => isRegularParameter || isInitializingFormal;

  /// `true` if this element represents a resolution error.
  bool get isError;

  /// `true` if this element represents an ambiguous name.
  ///
  /// Ambiguous names occur when two imports/exports contain different entities
  /// by the same name. If an ambiguous name is resolved an warning or error
  /// is produced.
  bool get isAmbiguous;

  /// True if there has been errors during resolution or parsing of this
  /// element.
  bool get isMalformed;

  /// `true` if this element represents an entity whose access causes one or
  /// more warnings.
  bool get isWarnOnUse;

  bool get isClosure;

  /// `true` if the element is a (static or instance) member of a class.
  ///
  /// Members are constructors, methods and fields.
  bool get isClassMember;

  /// `true` if the element is a nonstatic member of a class.
  ///
  /// Instance members are methods and fields but not constructors.
  bool get isInstanceMember;

  /// Returns true if this [Element] is a top level element.
  /// That is, if it is not defined within the scope of a class.
  ///
  /// This means whether the enclosing element is a compilation unit.
  /// With the exception of [ClosureClassElement] that is considered top level
  /// as all other classes.
  bool get isTopLevel;
  bool get isAssignable;

  bool get isDeferredLoaderGetter;

  /// True if the element is declared in a patch library but has no
  /// corresponding declaration in the origin library.
  bool get isInjected;

  /// `true` if this element is a constructor, top level or local variable,
  /// or static field that is declared `const`.
  bool get isConst;

  /// `true` if this element is a top level or local variable, static or
  /// instance field, or parameter that is declared `final`.
  bool get isFinal;

  /// `true` if this element is a method, getter, setter or field that
  /// is declared `static`.
  bool get isStatic;

  /// `true` if this element is local element, that is, a local variable,
  /// local function or parameter.
  bool get isLocal;

  bool get impliesType;

  /// The character offset of the declaration of this element within its
  /// compilation unit, if available.
  ///
  /// This is used to sort the elements.
  int get sourceOffset;

  // TODO(johnniwinther): Remove this.
  Token get position;

  /// The position of the declaration of this element, if available.
  SourceSpan get sourcePosition;

  CompilationUnitElement get compilationUnit;
  LibraryElement get library;
  LibraryElement get implementationLibrary;
  ClassElement get enclosingClass;
  Element get enclosingClassOrCompilationUnit;
  Element get outermostEnclosingMemberOrTopLevel;

  // TODO(johnniwinther): Replace uses of this with [enclosingClass] when
  // [ClosureClassElement] has been removed.
  /// The enclosing class that defines the type environment for this element.
  ClassElement get contextClass;

  FunctionElement asFunctionElement();

  /// Is [:true:] if this element has a corresponding patch.
  ///
  /// If [:true:] this element has a non-null [patch] field.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  bool get isPatched;

  /// Is [:true:] if this element is a patch.
  ///
  /// If [:true:] this element has a non-null [origin] field.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  bool get isPatch;

  /// Is [:true:] if this element defines the implementation for the entity of
  /// this element.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  bool get isImplementation;

  /// Is [:true:] if this element introduces the entity of this element.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  bool get isDeclaration;

  /// Returns the element which defines the implementation for the entity of
  /// this element.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  Element get implementation;

  /// Returns the element which introduces the entity of this element.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  Element get declaration;

  /// Returns the patch for this element if this element is patched.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  Element get patch;

  /// Returns the origin for this element if this element is a patch.
  ///
  /// See [:patch_parser.dart:] for a description of the terminology.
  Element get origin;

  bool get isSynthesized;
  bool get isMixinApplication;

  bool get isAbstract;

  Scope buildScope();

  // TODO(johnniwinther): Move this to [AstElement].
  /// Returns the [Element] that holds the [TreeElements] for this element.
  AnalyzableElement get analyzableElement;

  accept(ElementVisitor visitor, arg);
}

class Elements {
  static bool isUnresolved(Element e) {
    return e == null || e.isMalformed;
  }

  static bool isError(Element e) {
    return e != null && e.isError;
  }

  static bool isMalformed(Element e) {
    return e != null && e.isMalformed;
  }

  /// Unwraps [element] reporting any warnings attached to it, if any.
  static Element unwrap(
      Element element, DiagnosticReporter listener, Spannable spannable) {
    if (element != null && element.isWarnOnUse) {
      WarnOnUseElement wrappedElement = element;
      element = wrappedElement.unwrap(listener, spannable);
    }
    return element;
  }

  static bool isClass(Element e) => e != null && e.kind == ElementKind.CLASS;
  static bool isTypedef(Element e) {
    return e != null && e.kind == ElementKind.TYPEDEF;
  }

  static bool isLocal(Element element) {
    return !Elements.isUnresolved(element) && element.isLocal;
  }

  static bool isInstanceField(Element element) {
    return !Elements.isUnresolved(element) &&
        element.isInstanceMember &&
        (identical(element.kind, ElementKind.FIELD) ||
            identical(element.kind, ElementKind.GETTER) ||
            identical(element.kind, ElementKind.SETTER));
  }

  static bool isStaticOrTopLevel(Element element) {
    // TODO(johnniwinther): Clean this up. This currently returns true for a
    // PartialConstructorElement, SynthesizedConstructorElementX, and
    // TypeVariableElementX though neither `element.isStatic` nor
    // `element.isTopLevel` is true.
    if (Elements.isUnresolved(element)) return false;
    if (element.isStatic || element.isTopLevel) return true;
    return !element.isAmbiguous &&
        !element.isInstanceMember &&
        !element.isPrefix &&
        element.enclosingElement != null &&
        (element.enclosingElement.kind == ElementKind.CLASS ||
            element.enclosingElement.kind == ElementKind.COMPILATION_UNIT ||
            element.enclosingElement.kind == ElementKind.LIBRARY ||
            element.enclosingElement.kind == ElementKind.PREFIX);
  }

  static bool isInStaticContext(Element element) {
    if (isUnresolved(element)) return true;
    if (element.enclosingElement.isClosure) {
      var closureClass = element.enclosingElement;
      element = closureClass.methodElement;
    }
    Element outer = element.outermostEnclosingMemberOrTopLevel;
    if (isUnresolved(outer)) return true;
    if (outer.isTopLevel) return true;
    if (outer.isGenerativeConstructor) return false;
    if (outer.isInstanceMember) return false;
    return true;
  }

  static bool hasAccessToTypeVariable(
      Element element, TypeVariableElement typeVariable) {
    GenericElement declaration = typeVariable.typeDeclaration;
    if (declaration is FunctionElement || declaration is ParameterElement) {
      return true;
    }
    Element outer = element.outermostEnclosingMemberOrTopLevel;
    return (outer != null && outer.isFactoryConstructor) ||
        !isInStaticContext(element);
  }

  static bool isStaticOrTopLevelField(Element element) {
    return isStaticOrTopLevel(element) &&
        (identical(element.kind, ElementKind.FIELD) ||
            identical(element.kind, ElementKind.GETTER) ||
            identical(element.kind, ElementKind.SETTER));
  }

  static bool isStaticOrTopLevelFunction(Element element) {
    return isStaticOrTopLevel(element) && element.isFunction;
  }

  static bool isInstanceMethod(Element element) {
    return !Elements.isUnresolved(element) &&
        element.isInstanceMember &&
        (identical(element.kind, ElementKind.FUNCTION));
  }

  /// Also returns true for [ConstructorBodyElement]s and getters/setters.
  static bool isNonAbstractInstanceMember(Element element) {
    // The generative constructor body is not a function. We therefore treat
    // it specially.
    if (element.isGenerativeConstructorBody) return true;
    return !Elements.isUnresolved(element) &&
        !element.isAbstract &&
        element.isInstanceMember &&
        (element.isFunction || element.isAccessor);
  }

  static bool isInstanceSend(Send send, TreeElements elements) {
    Element element = elements[send];
    if (element == null) return !isClosureSend(send, element);
    return isInstanceMethod(element) ||
        isInstanceField(element) ||
        (send.isConditional && !element.isStatic);
  }

  static bool isClosureSend(Send send, Element element) {
    if (send.isPropertyAccess) return false;
    if (send.receiver != null) return false;
    Node selector = send.selector;
    // this().
    if (selector.isThis()) return true;
    // (o)() or foo()().
    if (element == null && selector.asIdentifier() == null) return true;
    if (element == null) return false;
    // foo() with foo a local or a parameter.
    return isLocal(element);
  }

  static String reconstructConstructorNameSourceString(Element element) {
    if (element.name == '') {
      return element.enclosingClass.name;
    } else {
      return reconstructConstructorName(element);
    }
  }

  // TODO(johnniwinther): Remove this method.
  static String reconstructConstructorName(Element element) {
    String className = element.enclosingClass.name;
    if (element.name == '') {
      return className;
    } else {
      return '$className\$${element.name}';
    }
  }

  static String constructorNameForDiagnostics(
      String className, String constructorName) {
    String classNameString = className;
    String constructorNameString = constructorName;
    return (constructorName == '')
        ? classNameString
        : "$classNameString.$constructorNameString";
  }

  /// Returns `true` if [name] is the name of an operator method.
  static bool isOperatorName(String name) {
    return name == 'unary-' || isUserDefinableOperator(name);
  }

  /**
   * Map an operator-name to a valid JavaScript identifier.
   *
   * For non-operator names, this method just returns its input.
   *
   * The results returned from this method are guaranteed to be valid
   * JavaScript identifers, except it may include reserved words for
   * non-operator names.
   */
  static String operatorNameToIdentifier(String name) {
    if (name == null) {
      return name;
    } else if (name == '==') {
      return r'operator$eq';
    } else if (name == '~') {
      return r'operator$not';
    } else if (name == '[]') {
      return r'operator$index';
    } else if (name == '[]=') {
      return r'operator$indexSet';
    } else if (name == '*') {
      return r'operator$mul';
    } else if (name == '/') {
      return r'operator$div';
    } else if (name == '%') {
      return r'operator$mod';
    } else if (name == '~/') {
      return r'operator$tdiv';
    } else if (name == '+') {
      return r'operator$add';
    } else if (name == '<<') {
      return r'operator$shl';
    } else if (name == '>>') {
      return r'operator$shr';
    } else if (name == '>=') {
      return r'operator$ge';
    } else if (name == '>') {
      return r'operator$gt';
    } else if (name == '<=') {
      return r'operator$le';
    } else if (name == '<') {
      return r'operator$lt';
    } else if (name == '&') {
      return r'operator$and';
    } else if (name == '^') {
      return r'operator$xor';
    } else if (name == '|') {
      return r'operator$or';
    } else if (name == '-') {
      return r'operator$sub';
    } else if (name == 'unary-') {
      return r'operator$negate';
    } else {
      return name;
    }
  }

  static String constructOperatorNameOrNull(String op, bool isUnary) {
    if (isMinusOperator(op)) {
      return isUnary ? 'unary-' : op;
    } else if (isUserDefinableOperator(op) || op == '??') {
      return op;
    } else {
      return null;
    }
  }

  static String constructOperatorName(String op, bool isUnary) {
    String operatorName = constructOperatorNameOrNull(op, isUnary);
    if (operatorName == null)
      throw 'Unhandled operator: $op';
    else
      return operatorName;
  }

  static String mapToUserOperatorOrNull(String op) {
    if (identical(op, '!=')) return '==';
    if (identical(op, '*=')) return '*';
    if (identical(op, '/=')) return '/';
    if (identical(op, '%=')) return '%';
    if (identical(op, '~/=')) return '~/';
    if (identical(op, '+=')) return '+';
    if (identical(op, '-=')) return '-';
    if (identical(op, '<<=')) return '<<';
    if (identical(op, '>>=')) return '>>';
    if (identical(op, '&=')) return '&';
    if (identical(op, '^=')) return '^';
    if (identical(op, '|=')) return '|';
    if (identical(op, '??=')) return '??';

    return null;
  }

  static bool isNumberOrStringSupertype(Element element, Compiler compiler) {
    LibraryElement coreLibrary = compiler.commonElements.coreLibrary;
    return (element == coreLibrary.find('Comparable'));
  }

  static bool isStringOnlySupertype(Element element, Compiler compiler) {
    LibraryElement coreLibrary = compiler.commonElements.coreLibrary;
    return element == coreLibrary.find('Pattern');
  }

  static bool isListSupertype(Element element, Compiler compiler) {
    LibraryElement coreLibrary = compiler.commonElements.coreLibrary;
    return element == coreLibrary.find('Iterable');
  }

  /// A `compareTo` function that places [Element]s in a consistent order based
  /// on the source code order.
  static int compareByPosition(Element a, Element b) {
    if (identical(a, b)) return 0;
    int r = _compareLibraries(a.library, b.library);
    if (r != 0) return r;
    r = _compareCompilationUnits(a.compilationUnit, b.compilationUnit);
    if (r != 0) return r;
    int offsetA = a.sourceOffset ?? -1;
    int offsetB = b.sourceOffset ?? -1;
    r = offsetA.compareTo(offsetB);
    if (r != 0) return r;
    r = a.name.compareTo(b.name);
    if (r != 0) return r;
    // Same file, position and name.  If this happens, we should find out why
    // and make the order total and independent of hashCode.
    return a.hashCode.compareTo(b.hashCode);
  }

  // Somewhat stable ordering for [LibraryElement]s
  static int _compareLibraries(LibraryElement a, LibraryElement b) {
    if (a == b) return 0;

    int byCanonicalUriPath() {
      return a.canonicalUri.path.compareTo(b.canonicalUri.path);
    }

    // Order: platform < package < other.
    if (a.isPlatformLibrary) {
      if (b.isPlatformLibrary) return byCanonicalUriPath();
      return -1;
    }
    if (b.isPlatformLibrary) return 1;

    if (a.isPackageLibrary) {
      if (b.isPackageLibrary) return byCanonicalUriPath();
      return -1;
    }
    if (b.isPackageLibrary) return 1;

    return _compareCanonicalUri(a.canonicalUri, b.canonicalUri);
  }

  static int _compareCanonicalUri(Uri a, Uri b) {
    int r = a.scheme.compareTo(b.scheme);
    if (r != 0) return r;

    // We would like the order of 'file:' Uris to be stable across different
    // users or different builds from temporary directories.  We sort by
    // pathSegments elements from the last to the first since that tends to find
    // a stable distinction regardless of directory root.
    List<String> aSegments = a.pathSegments;
    List<String> bSegments = b.pathSegments;
    int aI = aSegments.length;
    int bI = bSegments.length;
    while (aI > 0 && bI > 0) {
      String aSegment = aSegments[--aI];
      String bSegment = bSegments[--bI];
      r = aSegment.compareTo(bSegment);
      if (r != 0) return r;
    }
    return aI.compareTo(bI); // Shortest first.
  }

  static int _compareCompilationUnits(
      CompilationUnitElement a, CompilationUnitElement b) {
    if (a == b) return 0;
    // Compilation units are compared only within the same library so we expect
    // the Uris to usually be clustered together with a common scheme and path
    // prefix.
    Uri aUri = a.script.readableUri;
    Uri bUri = b.script.readableUri;
    return '${aUri}'.compareTo('${bUri}');
  }

  static List<Element> sortedByPosition(Iterable<Element> elements) {
    return elements.toList()..sort(compareByPosition);
  }

  static bool isFixedListConstructorCall(
      Element element, Send node, Compiler compiler) {
    return element == compiler.unnamedListConstructor &&
        node.isCall &&
        !node.arguments.isEmpty &&
        node.arguments.tail.isEmpty;
  }

  static bool isGrowableListConstructorCall(
      Element element, Send node, Compiler compiler) {
    return element == compiler.unnamedListConstructor &&
        node.isCall &&
        node.arguments.isEmpty;
  }

  static bool isFilledListConstructorCall(
      Element element, Send node, Compiler compiler) {
    return element == compiler.filledListConstructor &&
        node.isCall &&
        !node.arguments.isEmpty &&
        !node.arguments.tail.isEmpty &&
        node.arguments.tail.tail.isEmpty;
  }

  static bool isConstructorOfTypedArraySubclass(
      Element element, Compiler compiler) {
    if (compiler.commonElements.typedDataLibrary == null) return false;
    if (!element.isConstructor) return false;
    ConstructorElement constructor = element.implementation;
    constructor = constructor.effectiveTarget;
    ClassElement cls = constructor.enclosingClass;
    return cls.library == compiler.commonElements.typedDataLibrary &&
        compiler.backend.isNative(cls) &&
        compiler.closedWorld
            .isSubtypeOf(cls, compiler.commonElements.typedDataClass) &&
        compiler.closedWorld.isSubtypeOf(cls, compiler.coreClasses.listClass) &&
        constructor.name == '';
  }

  static bool switchStatementHasContinue(
      SwitchStatement node, TreeElements elements) {
    for (SwitchCase switchCase in node.cases) {
      for (Node labelOrCase in switchCase.labelsAndCases) {
        Node label = labelOrCase.asLabel();
        if (label != null) {
          LabelDefinition labelElement = elements.getLabelDefinition(label);
          if (labelElement != null && labelElement.isContinueTarget) {
            return true;
          }
        }
      }
    }
    return false;
  }

  static bool isUnusedLabel(LabeledStatement node, TreeElements elements) {
    Node body = node.statement;
    JumpTarget element = elements.getTargetDefinition(body);
    // Labeled statements with no element on the body have no breaks.
    // A different target statement only happens if the body is itself
    // a break or continue for a different target. In that case, this
    // label is also always unused.
    return element == null || element.statement != body;
  }
}

/// An element representing an erroneous resolution.
///
/// An [ErroneousElement] is used instead of `null` to provide additional
/// information about the error that caused the element to be unresolvable
/// or otherwise invalid.
///
/// Accessing any field or calling any method defined on [ErroneousElement]
/// except [isError] will currently throw an exception. (This might
/// change when we actually want more information on the erroneous element,
/// e.g., the name of the element we were trying to resolve.)
///
/// Code that cannot not handle an [ErroneousElement] should use
/// `Element.isUnresolved(element)` to check for unresolvable elements instead
/// of `element == null`.
abstract class ErroneousElement extends Element implements ConstructorElement {
  MessageKind get messageKind;
  Map get messageArguments;
  String get message;
}

/// An [Element] whose usage should cause one or more warnings.
abstract class WarnOnUseElement extends Element {
  /// The element whose usage cause a warning.
  Element get wrappedElement;

  /// Reports the attached warning and returns the wrapped element.
  /// [usageSpannable] is used to report messages on the reference of
  /// [wrappedElement].
  Element unwrap(DiagnosticReporter listener, Spannable usageSpannable);
}

/// An ambiguous element represents multiple elements accessible by the same
/// name.
///
/// Ambiguous elements are created during handling of import/export scopes. If
/// an ambiguous element is encountered during resolution a warning/error is
/// reported.
abstract class AmbiguousElement extends Element {
  MessageKind get messageKind;
  Map get messageArguments;
  Element get existingElement;
  Element get newElement;

  /// Compute the info messages associated with an error/warning on [context].
  List<DiagnosticMessage> computeInfos(
      Element context, DiagnosticReporter listener);
}

// TODO(kasperl): This probably shouldn't be called an element. It's
// just an interface shared by classes and libraries.
abstract class ScopeContainerElement implements Element {
  Element localLookup(String elementName);

  void forEachLocalMember(f(Element element));
}

abstract class CompilationUnitElement extends Element {
  /// Use [library] instead.
  @deprecated
  get enclosingElement;

  Script get script;

  void forEachLocalMember(f(Element element));
}

abstract class ImportElement extends Element {
  Uri get uri;
  LibraryElement get importedLibrary;
  bool get isDeferred;
  PrefixElement get prefix;
  // TODO(johnniwinther): Remove this when no longer needed in source mirrors.
  Import get node;
}

abstract class ExportElement extends Element {
  Uri get uri;
  LibraryElement get exportedLibrary;
  // TODO(johnniwinther): Remove this when no longer needed in source mirrors.
  Export get node;
}

abstract class LibraryElement extends Element
    implements ScopeContainerElement, AnalyzableElement {
  /**
   * The canonical uri for this library.
   *
   * For user libraries the canonical uri is the script uri. For platform
   * libraries the canonical uri is of the form [:dart:x:].
   */
  Uri get canonicalUri;

  /// Returns `true` if this library is 'dart:core'.
  bool get isDartCore;

  CompilationUnitElement get entryCompilationUnit;
  Link<CompilationUnitElement> get compilationUnits;

  /// The import declarations in this library, including the implicit import of
  /// 'dart:core', if present.
  Iterable<ImportElement> get imports;

  /// The export declarations in this library.
  Iterable<ExportElement> get exports;

  /**
   * [:true:] if this library is part of the platform, that is, its canonical
   * uri has the scheme 'dart'.
   */
  bool get isPlatformLibrary;

  /**
   * [:true:] if this library is from a package, that is, its canonical uri has
   * the scheme 'package'.
   */
  bool get isPackageLibrary;

  /**
   * [:true:] if this library is a platform library whose path starts with
   * an underscore.
   */
  bool get isInternalLibrary;

  bool get exportsHandled;

  LibraryElement get implementation;

  Element find(String elementName);
  Element findLocal(String elementName);
  Element findExported(String elementName);
  void forEachExport(f(Element element));

  /// Calls [f] for each [Element] imported into this library.
  void forEachImport(f(Element element));

  /// Returns the imports that import element into this library.
  Iterable<ImportElement> getImportsFor(Element element);

  /// `true` if this library has name as given through a library tag.
  bool get hasLibraryName;

  /// The library name, which is either the name given in the library tag
  /// or the empty string if there is no library tag.
  String get libraryName;

  /// Returns the library name (as defined by the library tag) or for script
  /// (which have no library tag) the script file name. The latter case is used
  /// to provide a 'library name' for scripts to use for instance in dartdoc.
  ///
  /// Note: the returned filename is still escaped ("a%20b.dart" instead of
  /// "a b.dart").
  String get libraryOrScriptName;
}

/// The implicit scope defined by a import declaration with a prefix clause.
abstract class PrefixElement extends Element {
  Element lookupLocalMember(String memberName);

  void forEachLocalMember(void f(Element member));

  /// Is true if this prefix belongs to a deferred import.
  bool get isDeferred;

  /// Import that declared this deferred prefix.
  ImportElement get deferredImport;

  /// The `loadLibrary` getter implicitly defined on deferred prefixes.
  GetterElement get loadLibrary;
}

/// A type alias definition.
abstract class TypedefElement extends Element
    implements AstElement, TypeDeclarationElement, FunctionTypedElement {
  /// The type defined by this typedef with the type variables as its type
  /// arguments.
  ///
  /// For instance `F<T>` for `typedef void F<T>(T t)`.
  TypedefType get thisType;

  /// The type defined by this typedef with `dynamic` as its type arguments.
  ///
  /// For instance `F<dynamic>` for `typedef void F<T>(T t)`.
  TypedefType get rawType;

  /// The type, function type if well-defined, for which this typedef is an
  /// alias.
  ///
  /// For instance `(int)->void` for `typedef void F(int)`.
  DartType get alias;

  void checkCyclicReference(Resolution resolution);
}

/// An executable element is an element that can hold code.
///
/// These elements variables (fields, parameters and locals), which can hold
/// code in their initializer, and functions (including methods and
/// constructors), which can hold code in their body.
abstract class ExecutableElement extends Element
    implements TypedElement, AstElement {
  /// The outermost member that contains this element.
  ///
  /// For top level, static or instance members, the member context is the
  /// element itself. For parameters, local variables and nested closures, the
  /// member context is the top level, static or instance member in which it is
  /// defined.
  MemberElement get memberContext;
}

/// A top-level, static or instance field or method, or a constructor.
///
/// A [MemberElement] is the outermost executable element for any executable
/// context.
abstract class MemberElement extends Element
    implements ExecutableElement, MemberEntity {
  /// The local functions defined within this member.
  List<FunctionElement> get nestedClosures;

  /// The name of this member, taking privacy into account.
  Name get memberName;
}

/// A function, variable or parameter defined in an executable context.
abstract class LocalElement extends Element
    implements AstElement, TypedElement, Local {}

/// A top level, static or instance field, a formal parameter or local variable.
abstract class VariableElement extends ExecutableElement {
  @override
  VariableDefinitions get node;

  Expression get initializer;

  bool get hasConstant;

  /// The constant expression defining the (initial) value of the variable.
  ///
  /// If the variable is `const` the value is always non-null, possibly an
  /// [ErroneousConstantExpression], otherwise, the value is null when the
  /// initializer isn't a constant expression.
  ConstantExpression get constant;
}

/// An entity that defines a local entity (memory slot) in generated code.
///
/// Parameters, local variables and local functions (can) define local entity
/// and thus implement [Local] through [LocalElement]. For non-element locals,
/// like `this` and boxes, specialized [Local] classes are created.
///
/// Type variables can introduce locals in factories and constructors
/// but since one type variable can introduce different locals in different
/// factories and constructors it is not itself a [Local] but instead
/// a non-element [Local] is created through a specialized class.
// TODO(johnniwinther): Should [Local] have `isAssignable` or `type`?
// TODO(johnniwinther): Move this to 'entities.dart' when it does not refer
// to [ExecutableElement].
abstract class Local extends Entity {
  /// The context in which this local is defined.
  ExecutableElement get executableContext;
}

/// A variable or parameter that is local to an executable context.
///
/// The executable context is the [ExecutableElement] in which this variable
/// is defined.
abstract class LocalVariableElement extends VariableElement
    implements LocalElement {}

/// A top-level, static or instance field.
abstract class FieldElement extends VariableElement
    implements MemberElement, FieldEntity {}

/// A parameter-like element of a function signature.
///
/// If the function signature comes from a typedef or an inline function-typed
/// parameter (e.g. the parameter 'f' in `method(void f())`), then its
/// parameters are not real parameters in that they can take no argument and
/// hold no value. Such parameter-like elements are modeled by [FormalElement].
///
/// If the function signature comes from a function or constructor, its
/// parameters are real parameters and are modeled by [ParameterElement].
abstract class FormalElement extends Element
    implements FunctionTypedElement, TypedElement, AstElement {
  /// Use [functionDeclaration] instead.
  @deprecated
  get enclosingElement;

  /// The function, typedef or inline function-typed parameter on which
  /// this parameter is declared.
  FunctionTypedElement get functionDeclaration;

  VariableDefinitions get node;
}

/// A formal parameter of a function or constructor.
///
/// Normal parameter that introduce a local variable are modeled by
/// [LocalParameterElement] whereas initializing formals, that is parameter of
/// the form `this.x`, are modeled by [InitializingFormalElement].
abstract class ParameterElement extends Element
    implements VariableElement, FormalElement, LocalElement {
  /// Use [functionDeclaration] instead.
  @deprecated
  get enclosingElement;

  /// The function on which this parameter is declared.
  FunctionElement get functionDeclaration;

  /// `true` if this parameter is named.
  bool get isNamed;

  /// `true` if this parameter is optional.
  bool get isOptional;
}

/// A formal parameter on a function or constructor that introduces a local
/// variable in the scope of the function or constructor.
abstract class LocalParameterElement extends ParameterElement
    implements LocalVariableElement {}

/// A formal parameter in a constructor that directly initializes a field.
///
/// For example: `A(this.field)`.
abstract class InitializingFormalElement extends LocalParameterElement {
  /// The field initialized by this initializing formal.
  FieldElement get fieldElement;

  /// The function on which this parameter is declared.
  ConstructorElement get functionDeclaration;
}

/**
 * A synthetic element which holds a getter and/or a setter.
 *
 * This element unifies handling of fields and getters/setters.  When
 * looking at code like "foo.x", we don't have to look for both a
 * field named "x", a getter named "x", and a setter named "x=".
 */
abstract class AbstractFieldElement extends Element {
  GetterElement get getter;
  SetterElement get setter;
}

abstract class FunctionSignature {
  FunctionType get type;
  DartType get returnType;
  List<DartType> get typeVariables;
  List<FormalElement> get requiredParameters;
  List<FormalElement> get optionalParameters;

  int get requiredParameterCount;
  int get optionalParameterCount;
  bool get optionalParametersAreNamed;
  bool get hasOptionalParameters;

  int get parameterCount;
  List<FormalElement> get orderedOptionalParameters;

  void forEachParameter(void function(FormalElement parameter));
  void forEachRequiredParameter(void function(FormalElement parameter));
  void forEachOptionalParameter(void function(FormalElement parameter));

  void orderedForEachParameter(void function(FormalElement parameter));

  bool isCompatibleWith(FunctionSignature constructorSignature);
}

/// A top level, static or instance method, constructor, local function, or
/// closure (anonymous local function).
abstract class FunctionElement extends Element
    implements
        AstElement,
        TypedElement,
        FunctionTypedElement,
        ExecutableElement,
        GenericElement {
  FunctionExpression get node;

  FunctionElement get patch;
  FunctionElement get origin;

  bool get hasFunctionSignature;

  /// The parameters of this function.
  List<ParameterElement> get parameters;

  /// The type of this function.
  FunctionType get type;

  /// The synchronous/asynchronous marker on this function.
  AsyncMarker get asyncMarker;

  /// `true` if this function is external.
  bool get isExternal;
}

/// A getter or setter.
abstract class AccessorElement extends MethodElement {
  /// Used to retrieve a link to the abstract field element representing this
  /// element.
  AbstractFieldElement get abstractField;
}

/// A getter.
abstract class GetterElement extends AccessorElement {
  /// The setter corresponding to this getter, if any.
  SetterElement get setter;
}

/// A setter.
abstract class SetterElement extends AccessorElement {
  /// The getter corresponding to this setter, if any.
  GetterElement get getter;
}

/// Enum for the synchronous/asynchronous function body modifiers.
class AsyncMarker {
  /// The default function body marker.
  static const AsyncMarker SYNC = const AsyncMarker._();

  /// The `sync*` function body marker.
  static const AsyncMarker SYNC_STAR = const AsyncMarker._(isYielding: true);

  /// The `async` function body marker.
  static const AsyncMarker ASYNC = const AsyncMarker._(isAsync: true);

  /// The `async*` function body marker.
  static const AsyncMarker ASYNC_STAR =
      const AsyncMarker._(isAsync: true, isYielding: true);

  /// Is `true` if this marker defines the function body to have an
  /// asynchronous result, that is, either a [Future] or a [Stream].
  final bool isAsync;

  /// Is `true` if this marker defines the function body to have a plural
  /// result, that is, either an [Iterable] or a [Stream].
  final bool isYielding;

  const AsyncMarker._({this.isAsync: false, this.isYielding: false});

  String toString() {
    return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
  }

  /// Canonical list of marker values.
  ///
  /// Added to make [AsyncMarker] enum-like.
  static const List<AsyncMarker> values = const <AsyncMarker>[
    SYNC,
    SYNC_STAR,
    ASYNC,
    ASYNC_STAR
  ];

  /// Index to this marker within [values].
  ///
  /// Added to make [AsyncMarker] enum-like.
  int get index => values.indexOf(this);
}

/// A top level, static or instance function.
abstract class MethodElement extends FunctionElement
    implements MemberElement, FunctionEntity {}

/// A local function or closure (anonymous local function).
abstract class LocalFunctionElement extends FunctionElement
    implements LocalElement {}

/// A constructor.
abstract class ConstructorElement extends MethodElement {
  /// Returns `true` if [effectiveTarget] has been computed for this
  /// constructor.
  bool get hasEffectiveTarget;

  /// The effective target of this constructor, that is the non-redirecting
  /// constructor that is called on invocation of this constructor.
  ///
  /// Consider for instance this hierarchy:
  ///
  ///     class C { factory C.c() = D.d; }
  ///     class D { factory D.d() = E.e2; }
  ///     class E { E.e1();
  ///               E.e2() : this.e1(); }
  ///
  /// The effective target of both `C.c`, `D.d`, and `E.e2` is `E.e2`, and the
  /// effective target of `E.e1` is `E.e1` itself.
  ConstructorElement get effectiveTarget;

  /// The immediate redirection target of a redirecting factory constructor.
  ///
  /// Consider for instance this hierarchy:
  ///
  ///     class C { factory C() = D; }
  ///     class D { factory D() = E; }
  ///     class E { E(); }
  ///
  /// The immediate redirection target of `C` is `D` and the immediate
  /// redirection target of `D` is `E`. `E` is not a redirecting factory
  /// constructor so its immediate redirection target is `null`.
  ConstructorElement get immediateRedirectionTarget;

  /// The prefix of the immediateRedirectionTarget, if it is deferred.
  /// [null] if it is not deferred.
  PrefixElement get redirectionDeferredPrefix;

  /// Is `true` if this constructor is a redirecting generative constructor.
  bool get isRedirectingGenerative;

  /// Is `true` if this constructor is a redirecting factory constructor.
  bool get isRedirectingFactory;

  /// Is `true` if this constructor is a redirecting factory constructor that is
  /// part of a redirection cycle.
  bool get isCyclicRedirection;

  /// Is `true` if the effective target of this constructor is malformed.
  ///
  /// A constructor is considered malformed if any of the following applies:
  ///
  ///     * the constructor is undefined,
  ///     * the type of the constructor is undefined,
  ///     * the constructor is a redirecting factory and either
  ///       - it is part of a redirection cycle,
  ///       - the effective target is a generative constructor on an abstract
  ///         class, or
  ///       - this constructor is constant but the effective target is not,
  ///       - the arguments to this constructor are incompatible with the
  ///         parameters of the effective target.
  bool get isEffectiveTargetMalformed;

  /// Compute the type of the effective target of this constructor for an
  /// instantiation site with type [:newType:].
  InterfaceType computeEffectiveTargetType(InterfaceType newType);

  /// If this is a synthesized constructor [definingConstructor] points to
  /// the generative constructor from which this constructor was created.
  /// Otherwise [definingConstructor] is `null`.
  ///
  /// Consider for instance this hierarchy:
  ///
  ///     class C { C.c(a, {b});
  ///     class D {}
  ///     class E = C with D;
  ///
  /// Class `E` has a synthesized constructor, `E.c`, whose defining constructor
  /// is `C.c`.
  ConstructorElement get definingConstructor;

  /// Returns `true` if this constructor is an implicit default constructor.
  bool get isDefaultConstructor;

  /// The constant constructor defining the binding of fields if `const`,
  /// `null` otherwise.
  ConstantConstructor get constantConstructor;

  /// `true` if this constructor is one of `bool.fromEnvironment`,
  /// `int.fromEnvironment`, or `String.fromEnvironment`.
  bool get isFromEnvironmentConstructor;

  /// `true` if this constructor is `int.fromEnvironment`.
  bool get isIntFromEnvironmentConstructor;

  /// `true` if this constructor is `bool.fromEnvironment`.
  bool get isBoolFromEnvironmentConstructor;

  /// `true` if this constructor is `String.fromEnvironment`.
  bool get isStringFromEnvironmentConstructor;

  /// Use [enclosingClass] instead.
  @deprecated
  get enclosingElement;
}

/// JavaScript backend specific element for the body of constructor.
// TODO(johnniwinther): Remove this class from the element model.
abstract class ConstructorBodyElement extends MethodElement {
  FunctionElement get constructor;
}

/// [GenericElement] defines the common interface for generic functions and
/// [TypeDeclarationElement].
abstract class GenericElement extends Element implements AstElement {
  /**
   * The type variables declared on this declaration. The type variables are not
   * available until the type of the element has been computed through
   * [computeType].
   */
  List<DartType> get typeVariables;
}

/// [TypeDeclarationElement] defines the common interface for class/interface
/// declarations and typedefs.
abstract class TypeDeclarationElement extends GenericElement {
  /// The name of this type declaration, taking privacy into account.
  Name get memberName;

  /// Do not use [computeType] outside of the resolver; instead retrieve the
  /// type from the [thisType] or [rawType], depending on the use case.
  ///
  /// Trying to access a type that has not been computed in resolution is an
  /// error and calling [computeType] covers that error.
  /// This method will go away!
  @deprecated
  GenericType computeType(Resolution resolution);

  /**
   * The `this type` for this type declaration.
   *
   * The type of [:this:] is the generic type based on this element in which
   * the type arguments are the declared type variables. For instance,
   * [:List<E>:] for [:List:] and [:Map<K,V>:] for [:Map:].
   *
   * For a class declaration this is the type of [:this:].
   */
  GenericType get thisType;

  /**
   * The raw type for this type declaration.
   *
   * The raw type is the generic type base on this element in which the type
   * arguments are all [dynamic]. For instance [:List<dynamic>:] for [:List:]
   * and [:Map<dynamic,dynamic>:] for [:Map:]. For non-generic classes [rawType]
   * is the same as [thisType].
   *
   * The [rawType] field is a canonicalization of the raw type and should be
   * used to distinguish explicit and implicit uses of the [dynamic]
   * type arguments. For instance should [:List:] be the [rawType] of the
   * [:List:] class element whereas [:List<dynamic>:] should be its own
   * instantiation of [InterfaceType] with [:dynamic:] as type argument. Using
   * this distinction, we can print the raw type with type arguments only when
   * the input source has used explicit type arguments.
   */
  GenericType get rawType;

  bool get isResolved;

  void ensureResolved(Resolution resolution);
}

abstract class ClassElement extends TypeDeclarationElement
    implements ScopeContainerElement, ClassEntity {
  /// The length of the longest inheritance path from [:Object:].
  int get hierarchyDepth;

  InterfaceType get rawType;
  InterfaceType get thisType;
  ClassElement get superclass;

  /// The direct supertype of this class.
  DartType get supertype;

  /// Ordered set of all supertypes of this class including the class itself.
  OrderedTypeSet get allSupertypesAndSelf;

  /// A list of all supertypes of this class excluding the class itself.
  Link<DartType> get allSupertypes;

  /// Returns the this type of this class as an instance of [cls].
  InterfaceType asInstanceOf(ClassElement cls);

  /// A list of all direct superinterfaces of this class.
  Link<DartType> get interfaces;

  bool get hasConstructor;
  Link<Element> get constructors;

  ClassElement get patch;
  ClassElement get origin;
  ClassElement get declaration;
  ClassElement get implementation;

  /// `true` if this class is an enum declaration.
  bool get isEnumClass;

  /// `true` if this class is a mixin application, either named or unnamed.
  bool get isMixinApplication;

  /// `true` if this class is a named mixin application, e.g.
  ///
  ///     class NamedMixinApplication = SuperClass with MixinClass;
  ///
  bool get isNamedMixinApplication;

  /// `true` if this class is an unnamed mixin application, e.g. the synthesized
  /// `SuperClass+MixinClass` mixin application class in:
  ///
  ///     class Class extends SuperClass with MixinClass {}
  ///
  bool get isUnnamedMixinApplication;

  bool get hasBackendMembers;
  bool get hasLocalScopeMembers;

  /// Returns `true` if this class is `Object` from dart:core.
  bool get isObject;

  /// Returns `true` if this class implements [Function] either by directly
  /// implementing the interface or by providing a [call] method.
  bool implementsFunction(CoreClasses coreClasses);

  /// Returns `true` if this class extends [cls] directly or indirectly.
  ///
  /// This method is not to be used for checking type hierarchy and assignments,
  /// because it does not take parameterized types into account.
  bool isSubclassOf(ClassElement cls);

  /// Returns `true` if this class explicitly implements [intrface].
  ///
  /// Note that, if [intrface] is the `Function` class, this method returns
  /// false for a class that has a `call` method but does not explicitly
  /// implement `Function`.
  bool implementsInterface(ClassElement intrface);

  bool hasFieldShadowedBy(Element fieldMember);

  /// Returns `true` if this class has a @proxy annotation.
  bool get isProxy;

  /// Returns `true` if the class hierarchy for this class contains errors.
  bool get hasIncompleteHierarchy;

  void addBackendMember(Element element);
  void reverseBackendMembers();

  Element lookupMember(String memberName);

  /// Looks up a class instance member declared or inherited in this class
  /// using [memberName] to match the (private) name and getter/setter property.
  ///
  /// This method recursively visits superclasses until the member is found or
  /// [stopAt] is reached.
  Element lookupByName(Name memberName, {ClassElement stopAt});
  Element lookupSuperByName(Name memberName);

  Element lookupLocalMember(String memberName);
  Element lookupBackendMember(String memberName);
  Element lookupSuperMember(String memberName);

  Element lookupSuperMemberInLibrary(String memberName, LibraryElement library);

  // TODO(johnniwinther): Clean up semantics. Can the default constructor take
  // optional arguments? Must it be resolved?
  ConstructorElement lookupDefaultConstructor();
  ConstructorElement lookupConstructor(String name);

  void forEachMember(void f(ClassElement enclosingClass, Element member),
      {bool includeBackendMembers: false,
      bool includeSuperAndInjectedMembers: false});

  void forEachInstanceField(
      void f(ClassElement enclosingClass, FieldElement field),
      {bool includeSuperAndInjectedMembers: false});

  /// Similar to [forEachInstanceField] but visits static fields.
  void forEachStaticField(void f(ClassElement enclosingClass, Element field));

  void forEachBackendMember(void f(Element member));

  /// Looks up the member [name] in this class.
  Member lookupClassMember(Name name);

  /// Calls [f] with each member of this class.
  void forEachClassMember(f(Member member));

  /// Looks up the member [name] in the interface of this class.
  MemberSignature lookupInterfaceMember(Name name);

  /// Calls [f] with each member of the interface of this class.
  void forEachInterfaceMember(f(MemberSignature member));

  /// Returns the type of the 'call' method in the interface of this class, or
  /// `null` if the interface has no 'call' method.
  FunctionType get callType;
}

abstract class MixinApplicationElement extends ClassElement {
  ClassElement get mixin;
  InterfaceType get mixinType;

  /// If this is an unnamed mixin application [subclass] is the subclass for
  /// which this mixin application is created.
  ClassElement get subclass;
}

/// Enum declaration.
abstract class EnumClassElement extends ClassElement {
  /// The static fields implied by the enum values.
  List<EnumConstantElement> get enumValues;
}

/// An enum constant value.
abstract class EnumConstantElement extends FieldElement {
  /// The enum that declared this constant.
  EnumClassElement get enclosingClass;

  /// The index of this constant within the values of the enum.
  int get index;
}

/// The label entity defined by a labeled statement.
abstract class LabelDefinition extends Entity {
  Label get label;
  String get labelName;
  JumpTarget get target;

  bool get isTarget;
  bool get isBreakTarget;
  bool get isContinueTarget;

  void setBreakTarget();
  void setContinueTarget();
}

/// A jump target is the reference point of a statement or switch-case,
/// either by label or as the default target of a break or continue.
abstract class JumpTarget extends Local {
  Node get statement;
  int get nestingLevel;
  Link<LabelDefinition> get labels;

  bool get isTarget;
  bool get isBreakTarget;
  bool get isContinueTarget;
  bool get isSwitch;

  // TODO(kasperl): Try to get rid of these.
  void set isBreakTarget(bool value);
  void set isContinueTarget(bool value);

  LabelDefinition addLabel(Label label, String labelName);
}

/// The [Element] for a type variable declaration on a generic class or typedef.
abstract class TypeVariableElement extends Element
    implements AstElement, TypedElement {
  /// The name of this type variable, taking privacy into account.
  Name get memberName;

  /// Use [typeDeclaration] instead.
  @deprecated
  get enclosingElement;

  /// The class, typedef, function, method, or function typed parameter on
  /// which this type variable is defined.
  GenericElement get typeDeclaration;

  /// The index of this type variable within its type declaration.
  int get index;

  /// The [type] defined by the type variable.
  TypeVariableType get type;

  /// The upper bound on the type variable. If not explicitly declared, this is
  /// `Object`.
  DartType get bound;
}

abstract class MetadataAnnotation implements Spannable {
  /// The front-end constant of this metadata annotation.
  ConstantExpression get constant;
  Element get annotatedElement;
  SourceSpan get sourcePosition;

  bool get hasNode;
  Node get node;

  MetadataAnnotation ensureResolved(Resolution resolution);
}

/// An [Element] that has a type.
abstract class TypedElement extends Element {
  /// Do not use [computeType] outside of the resolver; instead retrieve the
  /// type from  [type] property.
  ///
  /// Trying to access a type that has not been computed in resolution is an
  /// error and calling [computeType] covers that error.
  /// This method will go away!
  @deprecated
  DartType computeType(Resolution resolution);

  DartType get type;
}

/// An [Element] that can define a function type.
abstract class FunctionTypedElement extends Element implements GenericElement {
  /// The function signature for the function type defined by this element,
  /// if any.
  FunctionSignature get functionSignature;
}

/// An [Element] that holds a [TreeElements] mapping.
abstract class AnalyzableElement extends Element {
  /// Return `true` if [treeElements] have been (partially) computed for this
  /// element.
  bool get hasTreeElements;

  /// Returns the [TreeElements] that hold the resolution information for the
  /// AST nodes of this element.
  TreeElements get treeElements;
}

/// An [Element] that (potentially) has a node.
///
/// Synthesized elements may return `null` from [node].
abstract class AstElement extends AnalyzableElement {
  /// `true` if [node] is available and non-null.
  bool get hasNode;

  /// The AST node of this element.
  Node get node;

  /// `true` if [resolvedAst] is available.
  bool get hasResolvedAst;

  /// The defining AST node of this element with is corresponding
  /// [TreeElements]. This is not available if [hasResolvedAst] is `false`.
  ResolvedAst get resolvedAst;
}

/// Enum values for different ways of defining semantics for an element.
enum ResolvedAstKind {
  /// The semantics of the element is defined in terms of an AST with resolved
  /// data mapped in [TreeElements].
  PARSED,

  /// The element is an implicit default constructor. No AST or [TreeElements]
  /// are provided.
  DEFAULT_CONSTRUCTOR,

  /// The element is an implicit forwarding constructor on a mixin application.
  /// No AST or [TreeElements] are provided.
  FORWARDING_CONSTRUCTOR,

  /// The element is the `loadLibrary` getter implicitly defined on a deferred
  /// prefix.
  DEFERRED_LOAD_LIBRARY,
}

/// [ResolvedAst] contains info that define the semantics of an element.
abstract class ResolvedAst {
  /// The element whose semantics is defined.
  Element get element;

  /// The kind of semantics definition used for this object.
  ResolvedAstKind get kind;

  /// The root AST node for the declaration of [element]. This only available if
  /// [kind] is `ResolvedAstKind.PARSED`.
  Node get node;

  /// The AST node for the 'body' of [element].
  ///
  /// For functions and constructors this is the root AST node of the method
  /// body, and for variables this is the root AST node of the initializer, if
  /// available.
  ///
  /// This only available if [kind] is `ResolvedAstKind.PARSED`.
  Node get body;

  /// The [TreeElements] containing the resolution data for [node]. This only
  /// available of [kind] is `ResolvedAstKind.PARSED`.
  TreeElements get elements;

  /// Returns the uri for the source file defining [node] and [body]. This
  /// only available if [kind] is `ResolvedAstKind.PARSED`.
  Uri get sourceUri;
}

/// [ResolvedAst] implementation used for elements whose semantics is defined in
/// terms an AST and a [TreeElements].
class ParsedResolvedAst implements ResolvedAst {
  final Element element;
  final Node node;
  final Node body;
  final TreeElements elements;
  final Uri sourceUri;

  ParsedResolvedAst(
      this.element, this.node, this.body, this.elements, this.sourceUri);

  ResolvedAstKind get kind => ResolvedAstKind.PARSED;

  String toString() => '$kind:$element:$node';
}

/// [ResolvedAst] implementation used for synthesized elements whose semantics
/// is not defined in terms an AST and a [TreeElements].
class SynthesizedResolvedAst implements ResolvedAst {
  final Element element;
  final ResolvedAstKind kind;

  SynthesizedResolvedAst(this.element, this.kind);

  @override
  TreeElements get elements {
    throw new UnsupportedError('$this does not provide a TreeElements');
  }

  @override
  Node get node {
    throw new UnsupportedError('$this does not have a root AST node');
  }

  @override
  Node get body {
    throw new UnsupportedError('$this does not have a body AST node');
  }

  @override
  Uri get sourceUri {
    throw new UnsupportedError('$this does not have a source URI');
  }

  String toString() => '$kind:$element';
}

/// A [MemberSignature] is a member of an interface.
///
/// A signature is either a method or a getter or setter, possibly implicitly
/// defined by a field declarations. Fields themselves are not members of an
/// interface.
///
/// A [MemberSignature] may be defined by a member declaration or may be
/// synthetized from a set of declarations.
abstract class MemberSignature {
  /// The name of this member.
  Name get name;

  /// The type of the member when accessed. For getters and setters this is the
  /// return type and argument type, respectively. For methods the type is the
  /// [functionType] defined by the return type and parameters.
  DartType get type;

  /// The function type of the member. For a getter `Foo get foo` this is
  /// `() -> Foo`, for a setter `void set foo(Foo _)` this is `(Foo) -> void`.
  /// For methods the function type is defined by the return type and
  /// parameters.
  FunctionType get functionType;

  /// Returns `true` if this member is a getter, possibly implictly defined by a
  /// field declaration.
  bool get isGetter;

  /// Returns `true` if this member is a setter, possibly implictly defined by a
  /// field declaration.
  bool get isSetter;

  /// Returns `true` if this member is a method, that is neither a getter nor
  /// setter.
  bool get isMethod;

  /// Returns an iterable of the declarations that define this member.
  Iterable<Member> get declarations;
}

/// A [Member] is a member of a class, that is either a method or a getter or
/// setter, possibly implicitly defined by a field declarations. Fields
/// themselves are not members of a class.
///
/// A [Member] of a class also defines a signature which is a member of the
/// corresponding interface type.
///
/// A [Member] is implicitly concrete. An abstract declaration only declares
/// a signature in the interface of its class.
///
/// A [Member] is always declared by an [Element] which is accessibly through
/// the [element] getter.
abstract class Member extends MemberSignature {
  /// The [Element] that declared this member, possibly implicitly in case of
  /// a getter or setter defined by a field.
  Element get element;

  /// The instance of the class that declared this member.
  ///
  /// For instance:
  ///   class A<T> { T m() {} }
  ///   class B<S> extends A<S> {}
  /// The declarer of `m` in `A` is `A<T>` whereas the declarer of `m` in `B` is
  /// `A<S>`.
  InterfaceType get declarer;

  /// Returns `true` if this member is static.
  bool get isStatic;

  /// Returns `true` if this member is a getter or setter implicitly declared
  /// by a field.
  bool get isDeclaredByField;

  /// Returns `true` if this member is abstract.
  bool get isAbstract;

  /// If abstract, [implementation] points to the overridden concrete member,
  /// if any. Otherwise [implementation] points to the member itself.
  Member get implementation;
}
