// 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 'dart:uri';

// TODO(ahe): Rename prefix to 'api' when VM bug is fixed.
import '../../compiler.dart' as api_e;
import '../tree/tree.dart';
import '../dart2jslib.dart' show invariant,
                                 InterfaceType,
                                 DartType,
                                 TypeVariableType,
                                 TypedefType,
                                 MessageKind,
                                 DiagnosticListener,
                                 Script,
                                 FunctionType,
                                 SourceString,
                                 Selector,
                                 Constant,
                                 Compiler;
import '../scanner/scannerlib.dart' show Token, EOF_TOKEN;
import '../util/util.dart';
import '../resolution/resolution.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;

  static const int IS_EXTENDABLE = CLASS | ALIAS;
}

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 FIELD_PARAMETER =
    const ElementKind('field_parameter', ElementCategory.VARIABLE);
  static const ElementKind FUNCTION =
    const ElementKind('function', ElementCategory.FUNCTION);
  static const ElementKind CLASS =
    const ElementKind('class', ElementCategory.CLASS);
  static const ElementKind FOREIGN =
    const ElementKind('foreign', ElementCategory.FUNCTION);
  static const ElementKind GENERATIVE_CONSTRUCTOR =
      const ElementKind('generative_constructor', ElementCategory.FACTORY);
  static const ElementKind FIELD =
    const ElementKind('field', ElementCategory.VARIABLE);
  static const ElementKind VARIABLE_LIST =
    const ElementKind('variable_list', ElementCategory.NONE);
  static const ElementKind FIELD_LIST =
    const ElementKind('field_list', ElementCategory.NONE);
  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 PREFIX =
    const ElementKind('prefix', ElementCategory.PREFIX);
  static const ElementKind TYPEDEF =
    const ElementKind('typedef', ElementCategory.ALIAS);

  static const ElementKind STATEMENT =
    const ElementKind('statement', ElementCategory.NONE);
  static const ElementKind LABEL =
    const ElementKind('label', ElementCategory.NONE);
  static const ElementKind VOID =
    const ElementKind('void', ElementCategory.NONE);

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

  toString() => id;
}

class Element implements Spannable {
  static int elementHashCode = 0;

  final SourceString name;
  final ElementKind kind;
  final Element enclosingElement;
  final int hashCode = ++elementHashCode;
  Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();

  Element(this.name, this.kind, this.enclosingElement) {
    assert(isErroneous() || getImplementationLibrary() != null);
  }

  Modifiers get modifiers => Modifiers.EMPTY;

  Node parseNode(DiagnosticListener listener) {
    listener.internalErrorOnElement(this, 'not implemented');
  }

  DartType computeType(Compiler compiler) {
    compiler.internalError("$this.computeType.", token: position());
  }

  void addMetadata(MetadataAnnotation annotation) {
    assert(annotation.annotatedElement == null);
    annotation.annotatedElement = this;
    metadata = metadata.prepend(annotation);
  }

  bool isFunction() => identical(kind, ElementKind.FUNCTION);
  bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor();
  bool isClosure() => false;
  bool isMember() {
    // Check that this element is defined in the scope of a Class.
    return enclosingElement != null && enclosingElement.isClass();
  }
  bool isInstanceMember() => false;

  /**
   * Returns [:true:] if this element is enclosed in a static member or is
   * itself a static member.
   */
  bool isInStaticMember() {
    Element member = getEnclosingMember();
    return member != null && member.modifiers.isStatic();
  }

  bool isFactoryConstructor() => modifiers.isFactory();
  bool isGenerativeConstructor() =>
      identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR);
  bool isGenerativeConstructorBody() =>
      identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR_BODY);
  bool isCompilationUnit() => identical(kind, ElementKind.COMPILATION_UNIT);
  bool isClass() => identical(kind, ElementKind.CLASS);
  bool isPrefix() => identical(kind, ElementKind.PREFIX);
  bool isVariable() => identical(kind, ElementKind.VARIABLE);
  bool isParameter() => identical(kind, ElementKind.PARAMETER);
  bool isStatement() => identical(kind, ElementKind.STATEMENT);
  bool isTypedef() => identical(kind, ElementKind.TYPEDEF);
  bool isTypeVariable() => identical(kind, ElementKind.TYPE_VARIABLE);
  bool isField() => identical(kind, ElementKind.FIELD);
  bool isAbstractField() => identical(kind, ElementKind.ABSTRACT_FIELD);
  bool isGetter() => identical(kind, ElementKind.GETTER);
  bool isSetter() => identical(kind, ElementKind.SETTER);
  bool isAccessor() => isGetter() || isSetter();
  bool isForeign() => identical(kind, ElementKind.FOREIGN);
  bool isLibrary() => identical(kind, ElementKind.LIBRARY);
  bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
  bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0;

  /** See [ErroneousElement] for documentation. */
  bool isErroneous() => false;

  /** See [AmbiguousElement] for documentation. */
  bool isAmbiguous() => false;

  bool isMalformed() => false;

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

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

  /**
   * 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 => !isPatched;

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

  /**
   * 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 => isPatched ? patch : this;

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

  Element get patch {
    throw new UnsupportedError('patch is not supported on $this');
  }

  Element get origin {
    throw new UnsupportedError('origin is not supported on $this');
  }

  // TODO(johnniwinther): This breaks for libraries (for which enclosing
  // elements are null) and is invalid for top level variable declarations for
  // which the enclosing element is a VariableDeclarations and not a compilation
  // unit.
  bool isTopLevel() {
    return enclosingElement != null && enclosingElement.isCompilationUnit();
  }

  bool isAssignable() {
    if (modifiers.isFinalOrConst()) return false;
    if (isFunction() || isGenerativeConstructor()) return false;
    return true;
  }

  Token position() => null;

  Token findMyName(Token token) {
    for (Token t = token; !identical(t.kind, EOF_TOKEN); t = t.next) {
      if (t.value == name) return t;
    }
    return token;
  }

  CompilationUnitElement getCompilationUnit() {
    Element element = this;
    while (!element.isCompilationUnit()) {
      element = element.enclosingElement;
    }
    return element;
  }

  LibraryElement getLibrary() => enclosingElement.getLibrary();

  LibraryElement getImplementationLibrary() {
    Element element = this;
    while (!identical(element.kind, ElementKind.LIBRARY)) {
      element = element.enclosingElement;
    }
    return element;
  }

  ClassElement getEnclosingClass() {
    for (Element e = this; e != null; e = e.enclosingElement) {
      if (e.isClass()) return e;
    }
    return null;
  }

  Element getEnclosingClassOrCompilationUnit() {
   for (Element e = this; e != null; e = e.enclosingElement) {
      if (e.isClass() || e.isCompilationUnit()) return e;
    }
    return null;
  }

  /**
   * Returns the member enclosing this element or the element itself if it is a
   * member. If no enclosing element is found, [:null:] is returned.
   */
  Element getEnclosingMember() {
    for (Element e = this; e != null; e = e.enclosingElement) {
      if (e.isMember()) return e;
    }
    return null;
  }

  Element getOutermostEnclosingMemberOrTopLevel() {
    // TODO(lrn): Why is this called "Outermost"?
    for (Element e = this; e != null; e = e.enclosingElement) {
      if (e.isMember() || e.isTopLevel()) {
        return e;
      }
    }
    return null;
  }

  /**
   * Creates the scope for this element.
   */
  Scope buildScope() => enclosingElement.buildScope();

  String toString() {
    // TODO(johnniwinther): Test for nullness of name, or make non-nullness an
    // invariant for all element types?
    var nameText = name != null ? name.slowToString() : '?';
    if (enclosingElement != null && !isTopLevel()) {
      String holderName = enclosingElement.name != null
          ? enclosingElement.name.slowToString()
          : '${enclosingElement.kind}?';
      return '$kind($holderName#${nameText})';
    } else {
      return '$kind(${nameText})';
    }
  }

  String _nativeName = null;
  bool isNative() => _nativeName != null;
  String nativeName() => _nativeName;
  /// Marks this element as a native element.
  void setNative(String name) { _nativeName = name; }

  FunctionElement asFunctionElement() => null;

  static bool isInvalid(Element e) => e == null || e.isErroneous();

  bool isAbstract(Compiler compiler) => modifiers.isAbstract();
}

/**
 * Represents an unresolvable or duplicated element.
 *
 * 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 [isErroneous] 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.isInvalid(element) :]
 * to check for unresolvable elements instead of
 *   [: element == null :].
 */
class ErroneousElement extends Element implements FunctionElement {
  final MessageKind messageKind;
  final List messageArguments;

  ErroneousElement(this.messageKind, this.messageArguments,
                   SourceString name, Element enclosing)
      : super(name, ElementKind.ERROR, enclosing);

  isErroneous() => true;

  unsupported() {
    throw 'unsupported operation on erroneous element';
  }

  Link<MetadataAnnotation> get metadata => unsupported();
  get type => unsupported();
  get cachedNode => unsupported();
  get functionSignature => unsupported();
  get patch => unsupported();
  get origin => unsupported();
  get defaultImplementation => unsupported();
  bool get isPatched => unsupported();
  bool get isPatch => unsupported();
  setPatch(patch) => unsupported();
  computeSignature(compiler) => unsupported();
  requiredParameterCount(compiler) => unsupported();
  optionalParameterCount(compiler) => unsupported();
  parameterCount(copmiler) => unsupported();

  get redirectionTarget => this;

  getLibrary() => enclosingElement.getLibrary();

  String toString() {
    String n = name.slowToString();
    return '<$n: ${messageKind.message(messageArguments)}>';
  }
}

/**
 * An ambiguous element represent 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 should be
 * reported.
 */
class AmbiguousElement extends Element {
  /**
   * The message to report on resolving this element.
   */
  final MessageKind messageKind;

  /**
   * The message arguments to report on resolving this element.
   */
  final List messageArguments;

  /**
   * The first element that this ambiguous element might refer to.
   */
  final Element existingElement;

  /**
   * The second element that this ambiguous element might refer to.
   */
  final Element newElement;

  AmbiguousElement(this.messageKind, this.messageArguments,
      Element enclosingElement, Element existingElement, Element newElement)
      : this.existingElement = existingElement,
        this.newElement = newElement,
        super(existingElement.name, ElementKind.AMBIGUOUS, enclosingElement);

  bool isAmbiguous() => true;
}

class ContainerElement extends Element {
  Link<Element> localMembers = const Link<Element>();

  ContainerElement(name, kind, enclosingElement)
    : super(name, kind, enclosingElement);

  void addMember(Element element, DiagnosticListener listener) {
    localMembers = localMembers.prepend(element);
  }
}

class ScopeContainerElement extends ContainerElement {
  final Map<SourceString, Element> localScope;

  ScopeContainerElement(name, kind, enclosingElement)
    : super(name, kind, enclosingElement),
      localScope = new Map<SourceString, Element>();

  void addMember(Element element, DiagnosticListener listener) {
    super.addMember(element, listener);
    addToScope(element, listener);
  }

  void addToScope(Element element, DiagnosticListener listener) {
    if (element.isAccessor()) {
      addAccessorToScope(element, localScope[element.name], listener);
    } else {
      Element existing = localScope.putIfAbsent(element.name, () => element);
      if (!identical(existing, element)) {
        // TODO(ahe): Do something similar to Resolver.reportErrorWithContext.
        listener.cancel('duplicate definition', token: element.position());
        listener.cancel('existing definition', token: existing.position());
      }
    }
  }

  Element localLookup(SourceString elementName) {
    Element result = localScope[elementName];
    if (result == null && isPatch) {
      ScopeContainerElement element = origin;
      result = element.localScope[elementName];
    }
    return result;
  }

  /**
   * Adds a definition for an [accessor] (getter or setter) to a container.
   * The definition binds to an abstract field that can hold both a getter
   * and a setter.
   *
   * The abstract field is added once, for the first getter or setter, and
   * reused if the other one is also added.
   * The abstract field should not be treated as a proper member of the
   * container, it's simply a way to return two results for one lookup.
   * That is, the getter or setter does not have the abstract field as enclosing
   * element, they are enclosed by the class or compilation unit, as is the
   * abstract field.
   */
  void addAccessorToScope(Element accessor,
                          Element existing,
                          DiagnosticListener listener) {
    void reportError(Element other) {
      // TODO(ahe): Do something similar to Resolver.reportErrorWithContext.
      listener.cancel('duplicate definition of ${accessor.name.slowToString()}',
                      element: accessor);
      listener.cancel('existing definition', element: other);
    }

    if (existing != null) {
      if (!identical(existing.kind, ElementKind.ABSTRACT_FIELD)) {
        reportError(existing);
      } else {
        AbstractFieldElement field = existing;
        if (accessor.isGetter()) {
          if (field.getter != null && field.getter != accessor) {
            reportError(field.getter);
          }
          field.getter = accessor;
        } else {
          assert(accessor.isSetter());
          if (field.setter != null && field.setter != accessor) {
            reportError(field.setter);
          }
          field.setter = accessor;
        }
      }
    } else {
      Element container = accessor.getEnclosingClassOrCompilationUnit();
      AbstractFieldElement field =
          new AbstractFieldElement(accessor.name, container);
      if (accessor.isGetter()) {
        field.getter = accessor;
      } else {
        field.setter = accessor;
      }
      addToScope(field, listener);
    }
  }
}

class CompilationUnitElement extends ContainerElement {
  final Script script;
  PartOf partTag;

  CompilationUnitElement(Script script, LibraryElement library)
    : this.script = script,
      super(new SourceString(script.name),
            ElementKind.COMPILATION_UNIT,
            library) {
    library.addCompilationUnit(this);
  }

  void addMember(Element element, DiagnosticListener listener) {
    // Keep a list of top level members.
    super.addMember(element, listener);
    // Provide the member to the library to build scope.
    if (enclosingElement.isPatch) {
      getImplementationLibrary().addMember(element, listener);
    } else {
      getLibrary().addMember(element, listener);
    }
  }

  void setPartOf(PartOf tag, DiagnosticListener listener) {
    LibraryElement library = enclosingElement;
    if (library.entryCompilationUnit == this) {
      listener.reportMessage(
          listener.spanFromNode(tag),
          MessageKind.ILLEGAL_DIRECTIVE.error(),
          api_e.Diagnostic.WARNING);
      return;
    }
    if (!localMembers.isEmpty) {
      listener.reportMessage(
          listener.spanFromNode(tag),
          MessageKind.BEFORE_TOP_LEVEL.error(),
          api_e.Diagnostic.ERROR);
      return;
    }
    if (partTag != null) {
      listener.reportMessage(
          listener.spanFromNode(tag),
          MessageKind.DUPLICATED_PART_OF.error(),
          api_e.Diagnostic.WARNING);
      return;
    }
    partTag = tag;
    LibraryName libraryTag = getLibrary().libraryTag;
    if (libraryTag != null) {
      String expectedName = tag.name.toString();
      String actualName = libraryTag.name.toString();
      if (expectedName != actualName) {
        listener.reportMessage(
            listener.spanFromNode(tag.name),
            MessageKind.LIBRARY_NAME_MISMATCH.error([expectedName]),
            api_e.Diagnostic.WARNING);
      }
    }
  }
}

class LibraryElement extends ScopeContainerElement {
  final Uri uri;
  CompilationUnitElement entryCompilationUnit;
  Link<CompilationUnitElement> compilationUnits =
      const Link<CompilationUnitElement>();
  Link<LibraryTag> tags = const Link<LibraryTag>();
  LibraryName libraryTag;
  bool canUseNative = false;

  /**
   * If this library is patched, [patch] points to the patch library.
   *
   * See [:patch_parser.dart:] for a description of the terminology.
   */
  LibraryElement patch = null;

  /**
   * If this is a patch library, [origin] points to the origin library.
   *
   * See [:patch_parser.dart:] for a description of the terminology.
   */
  final LibraryElement origin;

  /**
   * Map for elements imported through import declarations.
   *
   * Addition to the map is performed by [addImport]. Lookup is done trough
   * [find].
   */
  final Map<SourceString, Element> importScope;

  /**
   * Link for elements exported either through export declarations or through
   * declaration. This field should not be accessed directly but instead through
   * the [exports] getter.
   *
   * [LibraryDependencyHandler] sets this field through [setExports] when the
   * library is loaded.
   */
  Link<Element> slotForExports;

  LibraryElement(Script script, [Uri uri, LibraryElement this.origin])
    : this.uri = ((uri == null) ? script.uri : uri),
      importScope = new Map<SourceString, Element>(),
      super(new SourceString(script.name), ElementKind.LIBRARY, null) {
    entryCompilationUnit = new CompilationUnitElement(script, this);
    if (isPatch) {
      origin.patch = this;
    }
  }

  bool get isPatched => patch != null;
  bool get isPatch => origin != null;

  LibraryElement get declaration => super.declaration;
  LibraryElement get implementation => super.implementation;

  CompilationUnitElement getCompilationUnit() => entryCompilationUnit;

  void addCompilationUnit(CompilationUnitElement element) {
    compilationUnits = compilationUnits.prepend(element);
  }

  void addTag(LibraryTag tag, DiagnosticListener listener) {
    tags = tags.prepend(tag);
  }

  /**
   * Adds [element] to the import scope of this library.
   *
   * If an element by the same name is already in the imported scope, an
   * [ErroneousElement] will be put in the imported scope, allowing for the
   * detection of ambiguous uses of imported names.
   */
  void addImport(Element element, DiagnosticListener listener) {
    Element existing = importScope[element.name];
    if (existing != null) {
      // TODO(johnniwinther): Provide access to the import tags from which
      // the elements came.
      importScope[element.name] = new AmbiguousElement(
          MessageKind.DUPLICATE_IMPORT, [element.name],
          this, existing, element);
    } else {
      importScope[element.name] = element;
    }
  }

  /**
   * Returns [:true:] if the export scope has already been computed for this
   * library.
   */
  bool get exportsHandled => slotForExports != null;

  Link<Element> get exports {
    assert(invariant(this, exportsHandled,
                     message: 'Exports not handled on $this'));
    return slotForExports;
  }

  /**
   * Sets the export scope of this library. This method can only be called once.
   */
  void setExports(Iterable<Element> exportedElements) {
    assert(invariant(this, !exportsHandled,
        message: 'Exports already set to $slotForExports on $this'));
    assert(invariant(this, exportedElements != null));
    var builder = new LinkBuilder<Element>();
    for (Element export in exportedElements) {
      builder.addLast(export);
    }
    slotForExports = builder.toLink();
  }

  LibraryElement getLibrary() => isPatch ? origin : this;

  /**
   * Look up a top-level element in this library. The element could
   * potentially have been imported from another library. Returns
   * null if no such element exist and an [ErroneousElement] if multiple
   * elements have been imported.
   */
  Element find(SourceString elementName) {
    Element result = localScope[elementName];
    if (result != null) return result;
    if (origin != null) {
      result = origin.localScope[elementName];
      if (result != null) return result;
    }
    result = importScope[elementName];
    if (result != null) return result;
    if (origin != null) {
      result = origin.importScope[elementName];
      if (result != null) return result;
    }
    return null;
  }

  /** Look up a top-level element in this library, but only look for
    * non-imported elements. Returns null if no such element exist. */
  Element findLocal(SourceString elementName) {
    // TODO(johnniwinther): How to handle injected elements in the patch
    // library?
    Element result = localScope[elementName];
    if (result == null || result.getLibrary() != this) return null;
    return result;
  }

  void forEachExport(f(Element element)) {
    exports.forEach((Element e) => f(e));
  }

  void forEachLocalMember(f(Element element)) {
    if (isPatch) {
      // Patch libraries traverse both origin and injected members.
      origin.localMembers.forEach(f);

      void filterPatch(Element element) {
        if (!element.isPatch) {
          // Do not traverse the patch members.
          f(element);
        }
      }
      localMembers.forEach(filterPatch);
    } else {
      localMembers.forEach(f);
    }
  }

  bool hasLibraryName() => libraryTag != null;

  /**
   * 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 private 'library name' for scripts to use for instance in dartdoc.
   */
  String getLibraryOrScriptName() {
    if (libraryTag != null) {
      return libraryTag.name.toString();
    } else {
      // Use the file name as script name.
      String path = uri.path;
      return path.substring(path.lastIndexOf('/') + 1);
    }
  }

  Scope buildScope() => new LibraryScope(this);

  bool get isPlatformLibrary => uri.scheme == "dart";

  String toString() {
    if (origin != null) {
      return 'patch library(${getLibraryOrScriptName()})';
    } else if (patch != null) {
      return 'origin library(${getLibraryOrScriptName()})';
    } else {
      return 'library(${getLibraryOrScriptName()})';
    }
  }
}

class PrefixElement extends Element {
  Map<SourceString, Element> imported;
  Token firstPosition;

  PrefixElement(SourceString prefix, Element enclosing, this.firstPosition)
      : imported = new Map<SourceString, Element>(),
        super(prefix, ElementKind.PREFIX, enclosing);

  lookupLocalMember(SourceString memberName) => imported[memberName];

  DartType computeType(Compiler compiler) => compiler.types.dynamicType;

  Token position() => firstPosition;
}

class TypedefElement extends Element implements TypeDeclarationElement {
  Typedef cachedNode;
  TypedefType cachedType;

  /**
   * Canonicalize raw version of [cachedType].
   *
   * See [ClassElement.rawType] for motivation.
   *
   * The [rawType] is computed together with [cachedType] in [computeType].
   */
  TypedefType rawType;

  /**
   * The type annotation which defines this typedef.
   */
  DartType alias;

  bool isResolved = false;
  bool isBeingResolved = false;

  TypedefElement(SourceString name, Element enclosing)
      : super(name, ElementKind.TYPEDEF, enclosing);

  /**
   * Function signature for a typedef of a function type. The signature is
   * kept to provide full information about parameter names through the mirror
   * system.
   *
   * The [functionSignature] is not available until the typedef element has been
   * resolved.
   */
  FunctionSignature functionSignature;

  TypedefType computeType(Compiler compiler) {
    if (cachedType != null) return cachedType;
    Typedef node = parseNode(compiler);
    Link<DartType> parameters =
        TypeDeclarationElement.createTypeVariables(this, node.typeParameters);
    cachedType = new TypedefType(this, parameters);
    if (parameters.isEmpty) {
      rawType = cachedType;
    } else {
      var dynamicParameters = const Link<DartType>();
      parameters.forEach((_) {
        dynamicParameters =
            dynamicParameters.prepend(compiler.types.dynamicType);
      });
      rawType = new TypedefType(this, dynamicParameters);
    }
    compiler.resolveTypedef(this);
    return cachedType;
  }

  Link<DartType> get typeVariables => cachedType.typeArguments;

  Scope buildScope() {
    return new TypeDeclarationScope(enclosingElement.buildScope(), this);
  }
}

class VariableElement extends Element {
  final VariableListElement variables;
  Expression cachedNode; // The send or the identifier in the variables list.

  Modifiers get modifiers => variables.modifiers;

  VariableElement(SourceString name,
                  VariableListElement variables,
                  ElementKind kind,
                  this.cachedNode)
    : this.variables = variables,
      super(name, kind, variables.enclosingElement);

  Node parseNode(DiagnosticListener listener) {
    if (cachedNode != null) return cachedNode;
    VariableDefinitions definitions = variables.parseNode(listener);
    for (Link<Node> link = definitions.definitions.nodes;
         !link.isEmpty; link = link.tail) {
      Expression initializedIdentifier = link.head;
      Identifier identifier = initializedIdentifier.asIdentifier();
      if (identifier == null) {
        identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
      }
      if (identical(name, identifier.source)) {
        cachedNode = initializedIdentifier;
        return cachedNode;
      }
    }
    listener.cancel('internal error: could not find $name', node: variables);
  }

  DartType computeType(Compiler compiler) {
    return variables.computeType(compiler);
  }

  DartType get type => variables.type;

  bool isInstanceMember() => variables.isInstanceMember();

  // Note: cachedNode.getBeginToken() will not be correct in all
  // cases, for example, for function typed parameters.
  Token position() => findMyName(variables.position());
}

/**
 * Parameters in constructors that directly initialize fields. For example:
 * [:A(this.field):].
 */
class FieldParameterElement extends VariableElement {
  VariableElement fieldElement;

  FieldParameterElement(SourceString name,
                        this.fieldElement,
                        VariableListElement variables,
                        Node node)
      : super(name, variables, ElementKind.FIELD_PARAMETER, node);
}

// This element represents a list of variable or field declaration.
// It contains the node, and the type. A [VariableElement] always
// references its [VariableListElement]. It forwards its
// [computeType] and [parseNode] methods to this element.
class VariableListElement extends Element {
  VariableDefinitions cachedNode;
  DartType type;
  final Modifiers modifiers;

  /**
   * Function signature for a variable with a function type. The signature is
   * kept to provide full information about parameter names through the mirror
   * system.
   */
  FunctionSignature functionSignature;

  VariableListElement(ElementKind kind,
                      Modifiers this.modifiers,
                      Element enclosing)
    : super(null, kind, enclosing);

  VariableListElement.node(VariableDefinitions node,
                           ElementKind kind,
                           Element enclosing)
      : super(null, kind, enclosing),
        this.cachedNode = node,
        this.modifiers = node.modifiers {
    assert(modifiers != null);
  }

  VariableDefinitions parseNode(DiagnosticListener listener) {
    return cachedNode;
  }

  DartType computeType(Compiler compiler) {
    if (type != null) return type;
    compiler.withCurrentElement(this, () {
      VariableDefinitions node = parseNode(compiler);
      if (node.type != null) {
        type = compiler.resolveTypeAnnotation(this, node.type);
      } else {
        // Is node.definitions exactly one FunctionExpression?
        Link<Node> link = node.definitions.nodes;
        if (!link.isEmpty &&
            link.head.asFunctionExpression() != null &&
            link.tail.isEmpty) {
          FunctionExpression functionExpression = link.head;
          // We found exactly one FunctionExpression
          functionSignature =
              compiler.resolveFunctionExpression(this, functionExpression);
          type = compiler.computeFunctionType(compiler.functionClass,
                                              functionSignature);
        } else {
          type = compiler.types.dynamicType;
        }
      }
    });
    assert(type != null);
    return type;
  }

  Token position() => cachedNode.getBeginToken();

  bool isInstanceMember() {
    return isMember() && !modifiers.isStatic();
  }
}

class ForeignElement extends Element {
  ForeignElement(SourceString name, ContainerElement enclosingElement)
    : super(name, ElementKind.FOREIGN, enclosingElement);

  DartType computeType(Compiler compiler) {
    return compiler.types.dynamicType;
  }

  parseNode(DiagnosticListener listener) {
    throw "internal error: ForeignElement has no node";
  }
}

class AbstractFieldElement extends Element {
  FunctionElement getter;
  FunctionElement setter;

  AbstractFieldElement(SourceString name, Element enclosing)
      : super(name, ElementKind.ABSTRACT_FIELD, enclosing);

  DartType computeType(Compiler compiler) {
    throw "internal error: AbstractFieldElement has no type";
  }

  Node parseNode(DiagnosticListener listener) {
    throw "internal error: AbstractFieldElement has no node";
  }

  position() {
    // The getter and setter may be defined in two different
    // compilation units.  However, we know that one of them is
    // non-null and defined in the same compilation unit as the
    // abstract element.
    // TODO(lrn): No we don't know that if the element from the same
    // compilation unit is patched.
    //
    // We need to make sure that the position returned is relative to
    // the compilation unit of the abstract element.
    if (getter != null
        && identical(getter.getCompilationUnit(), getCompilationUnit())) {
      return getter.position();
    } else {
      return setter.position();
    }
  }

  Modifiers get modifiers {
    // The resolver ensures that the flags match (ignoring abstract).
    if (getter != null) {
      return new Modifiers.withFlags(
          getter.modifiers.nodes,
          getter.modifiers.flags | Modifiers.FLAG_ABSTRACT);
    } else {
      return new Modifiers.withFlags(
          setter.modifiers.nodes,
          setter.modifiers.flags | Modifiers.FLAG_ABSTRACT);
    }
  }
}

// TODO(johnniwinther): [FunctionSignature] should be merged with
// [FunctionType].
class FunctionSignature {
  final Link<Element> requiredParameters;
  final Link<Element> optionalParameters;
  final DartType returnType;
  final int requiredParameterCount;
  final int optionalParameterCount;
  final bool optionalParametersAreNamed;

  List<Element> _orderedOptionalParameters;

  FunctionSignature(this.requiredParameters,
                    this.optionalParameters,
                    this.requiredParameterCount,
                    this.optionalParameterCount,
                    this.optionalParametersAreNamed,
                    this.returnType);

  void forEachRequiredParameter(void function(Element parameter)) {
    for (Link<Element> link = requiredParameters;
         !link.isEmpty;
         link = link.tail) {
      function(link.head);
    }
  }

  void forEachOptionalParameter(void function(Element parameter)) {
    for (Link<Element> link = optionalParameters;
         !link.isEmpty;
         link = link.tail) {
      function(link.head);
    }
  }

  List<Element> get orderedOptionalParameters {
    if (_orderedOptionalParameters != null) return _orderedOptionalParameters;
    List<Element> list = new List<Element>.from(optionalParameters);
    if (optionalParametersAreNamed) {
      list.sort((Element a, Element b) {
        return a.name.slowToString().compareTo(b.name.slowToString());
      });
    }
    _orderedOptionalParameters = list;
    return list;
  }

  void forEachParameter(void function(Element parameter)) {
    forEachRequiredParameter(function);
    forEachOptionalParameter(function);
  }

  void orderedForEachParameter(void function(Element parameter)) {
    forEachRequiredParameter(function);
    orderedOptionalParameters.forEach(function);
  }

  int get parameterCount => requiredParameterCount + optionalParameterCount;
}

class FunctionElement extends Element {
  FunctionExpression cachedNode;
  DartType type;
  final Modifiers modifiers;

  FunctionSignature functionSignature;

  /**
   * A function declaration that should be parsed instead of the current one.
   * The patch should be parsed as if it was in the current scope. Its
   * signature must match this function's signature.
   */
  // TODO(lrn): Consider using [defaultImplementation] to store the patch.
  FunctionElement patch = null;
  FunctionElement origin = null;

  /**
   * If this is a redirecting factory, [defaultImplementation] will be
   * changed by the resolver to point to the redirection target.  If
   * this is an interface constructor, [defaultImplementation] will be
   * changed by the resolver to point to the default implementation.
   * Otherwise, [:identical(defaultImplementation, this):].
   */
  // TODO(ahe): Rename this field to redirectionTarget and remove
  // mention of interface constructors above.
  FunctionElement defaultImplementation;

  FunctionElement(SourceString name,
                  ElementKind kind,
                  Modifiers modifiers,
                  Element enclosing)
      : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null);

  FunctionElement.node(SourceString name,
                       FunctionExpression node,
                       ElementKind kind,
                       Modifiers modifiers,
                       Element enclosing)
      : this.tooMuchOverloading(name, node, kind, modifiers, enclosing, null);

  FunctionElement.from(SourceString name,
                       FunctionElement other,
                       Element enclosing)
      : this.tooMuchOverloading(name, other.cachedNode, other.kind,
                                other.modifiers, enclosing,
                                other.functionSignature);

  FunctionElement.tooMuchOverloading(SourceString name,
                                     FunctionExpression this.cachedNode,
                                     ElementKind kind,
                                     Modifiers this.modifiers,
                                     Element enclosing,
                                     FunctionSignature this.functionSignature)
      : super(name, kind, enclosing) {
    assert(modifiers != null);
    defaultImplementation = this;
  }

  bool get isPatched => patch != null;
  bool get isPatch => origin != null;

  FunctionElement get redirectionTarget {
    if (this == defaultImplementation) return this;
    var target = defaultImplementation;
    Set<Element> seen = new Set<Element>();
    seen.add(target);
    while (!target.isErroneous() && target != target.defaultImplementation) {
      target = target.defaultImplementation;
      if (seen.contains(target)) {
        // TODO(ahe): This is expedient for now, but it should be
        // checked by the resolver.  Keeping http://dartbug.com/3970
        // open to track this.
        throw new SpannableAssertionFailure(
            target, 'redirecting factory leads to cycle');
      }
    }
    return target;
  }

  /**
   * Applies a patch function to this function. The patch function's body
   * is used as replacement when parsing this function's body.
   * This method must not be called after the function has been parsed,
   * and it must be called at most once.
   */
  void setPatch(FunctionElement patchElement) {
    // Sanity checks. The caller must check these things before calling.
    assert(patch == null);
    this.patch = patchElement;
  }

  bool isInstanceMember() {
    return isMember()
           && !isConstructor()
           && !modifiers.isStatic();
  }

  FunctionSignature computeSignature(Compiler compiler) {
    if (functionSignature != null) return functionSignature;
    compiler.withCurrentElement(this, () {
      functionSignature = compiler.resolveSignature(this);
    });
    return functionSignature;
  }

  int requiredParameterCount(Compiler compiler) {
    return computeSignature(compiler).requiredParameterCount;
  }

  int optionalParameterCount(Compiler compiler) {
    return computeSignature(compiler).optionalParameterCount;
  }

  int parameterCount(Compiler compiler) {
    return computeSignature(compiler).parameterCount;
  }

  FunctionType computeType(Compiler compiler) {
    if (type != null) return type;
    type = compiler.computeFunctionType(declaration,
                                        computeSignature(compiler));
    return type;
  }

  FunctionExpression parseNode(DiagnosticListener listener) {
    if (patch == null) {
      if (modifiers.isExternal()) {
        listener.cancel("Compiling external function with no implementation.",
                        element: this);
      }
    }
    return cachedNode;
  }

  Token position() => cachedNode.getBeginToken();

  FunctionElement asFunctionElement() => this;

  String toString() {
    if (isPatch) {
      return 'patch ${super.toString()}';
    } else if (isPatched) {
      return 'origin ${super.toString()}';
    } else {
      return super.toString();
    }
  }

  bool isAbstract(Compiler compiler) {
    if (super.isAbstract(compiler)) return true;
    if (modifiers.isExternal()) return false;
    if (isFunction() || isAccessor()) {
      return !parseNode(compiler).hasBody();
    }
    return false;
  }
}

class ConstructorBodyElement extends FunctionElement {
  FunctionElement constructor;

  ConstructorBodyElement(FunctionElement constructor)
      : this.constructor = constructor,
        super(constructor.name,
              ElementKind.GENERATIVE_CONSTRUCTOR_BODY,
              Modifiers.EMPTY,
              constructor.enclosingElement) {
    functionSignature = constructor.functionSignature;
  }

  bool isInstanceMember() => true;

  FunctionType computeType(Compiler compiler) {
    compiler.reportFatalError('Internal error: $this.computeType', this);
  }

  Node parseNode(DiagnosticListener listener) {
    if (cachedNode != null) return cachedNode;
    cachedNode = constructor.parseNode(listener);
    assert(cachedNode != null);
    return cachedNode;
  }

  Token position() => constructor.position();
}

class SynthesizedConstructorElement extends FunctionElement {
  SynthesizedConstructorElement(Element enclosing)
    : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
            Modifiers.EMPTY, enclosing);

  Token position() => enclosingElement.position();
}

class VoidElement extends Element {
  VoidElement(Element enclosing)
      : super(const SourceString('void'), ElementKind.VOID, enclosing);
  DartType computeType(compiler) => compiler.types.voidType;
  Node parseNode(_) {
    throw 'internal error: parseNode on void';
  }
  bool impliesType() => true;
}

class MalformedTypeElement extends Element {
  final TypeAnnotation typeNode;

  MalformedTypeElement(this.typeNode, Element enclosing)
      : super(const SourceString('malformed'),
              ElementKind.MALFORMED_TYPE,
              enclosing);

  DartType computeType(compiler) => compiler.types.malformedType;

  Node parseNode(_) => typeNode;

  bool impliesType() => true;

  bool isMalformed() => true;
}

/**
 * [TypeDeclarationElement] defines the common interface for class/interface
 * declarations and typedefs.
 */
abstract class TypeDeclarationElement implements Element {
  // TODO(johnniwinther): This class should eventually be a mixin.

  /**
   * The type variables declared on this declaration. The type variables are not
   * available until the type of the element has been computed through
   * [computeType].
   */
  // TODO(johnniwinther): Find a (better) way to decouple [typeVariables] from
  // [Compiler].
  Link<DartType> get typeVariables;

  /**
   * Creates the type variables, their type and corresponding element, for the
   * type variables declared in [parameter] on [element]. The bounds of the type
   * variables are not set until [element] has been resolved.
   */
  static Link<DartType> createTypeVariables(TypeDeclarationElement element,
                                            NodeList parameters) {
    if (parameters == null) return const Link<DartType>();

    // Create types and elements for type variable.
    var arguments = new LinkBuilder<DartType>();
    for (Link link = parameters.nodes; !link.isEmpty; link = link.tail) {
      TypeVariable node = link.head;
      SourceString variableName = node.name.source;
      TypeVariableElement variableElement =
          new TypeVariableElement(variableName, element, node);
      TypeVariableType variableType = new TypeVariableType(variableElement);
      variableElement.type = variableType;
      arguments.addLast(variableType);
    }
    return arguments.toLink();
  }
}

abstract class ClassElement extends ScopeContainerElement
    implements TypeDeclarationElement {
  final int id;
  /**
   * The type of [:this:] for this class declaration.
   *
   * The type of [:this:] is the interface 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:].
   *
   * This type is computed in [computeType].
   */
  InterfaceType thisType;

  /**
   * The raw type for this class declaration.
   *
   * The raw type is the interface 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.
   *
   * This type is computed together with [thisType] in [computeType].
   */
  InterfaceType rawType;
  DartType supertype;
  DartType defaultClass;
  Link<DartType> interfaces;
  SourceString nativeTagInfo;
  int supertypeLoadState;
  int resolutionState;

  // backendMembers are members that have been added by the backend to simplify
  // compilation. They don't have any user-side counter-part.
  Link<Element> backendMembers = const Link<Element>();

  Link<DartType> allSupertypes;

  // Lazily applied patch of class members.
  ClassElement patch = null;
  ClassElement origin = null;

  ClassElement(SourceString name, Element enclosing, this.id, int initialState)
    : supertypeLoadState = initialState,
      resolutionState = initialState,
      super(name, ElementKind.CLASS, enclosing);

  ClassNode parseNode(Compiler compiler);

  InterfaceType computeType(compiler) {
    if (thisType == null) {
      if (origin == null) {
        ClassNode node = parseNode(compiler);
        Link<DartType> parameters =
            TypeDeclarationElement.createTypeVariables(this,
                                                       node.typeParameters);
        thisType = new InterfaceType(this, parameters);
        if (parameters.isEmpty) {
          rawType = thisType;
        } else {
          var dynamicParameters = const Link<DartType>();
          parameters.forEach((_) {
            dynamicParameters =
                dynamicParameters.prepend(compiler.types.dynamicType);
          });
          rawType = new InterfaceType(this, dynamicParameters);
        }
      } else {
        thisType = origin.computeType(compiler);
        rawType = origin.rawType;
      }
    }
    return thisType;
  }

  bool get isPatched => patch != null;
  bool get isPatch => origin != null;

  ClassElement get declaration => super.declaration;
  ClassElement get implementation => super.implementation;

  /**
   * Return [:true:] if this element is the [:Object:] class for the [compiler].
   */
  bool isObject(Compiler compiler) =>
      identical(declaration, compiler.objectClass);

  Link<DartType> get typeVariables => thisType.typeArguments;

  ClassElement ensureResolved(Compiler compiler) {
    if (resolutionState == STATE_NOT_STARTED) {
      compiler.resolver.resolveClass(this);
    }
    return this;
  }

  /**
   * Lookup local members in the class. This will ignore constructors.
   */
  Element lookupLocalMember(SourceString memberName) {
    var result = localLookup(memberName);
    if (result != null && result.isConstructor()) return null;
    return result;
  }

  /**
   * Lookup super members for the class. This will ignore constructors.
   */
  Element lookupSuperMember(SourceString memberName) {
    return lookupSuperMemberInLibrary(memberName, getLibrary());
  }

  /**
   * Lookup super members for the class that is accessible in [library].
   * This will ignore constructors.
   */
  Element lookupSuperMemberInLibrary(SourceString memberName,
                                     LibraryElement library) {
    bool includeInjectedMembers = isPatch;
    bool isPrivate = memberName.isPrivate();
    for (ClassElement s = superclass; s != null; s = s.superclass) {
      // Private members from a different library are not visible.
      if (isPrivate && !identical(library, s.getLibrary())) continue;
      s = includeInjectedMembers ? s.implementation : s;
      Element e = s.lookupLocalMember(memberName);
      if (e == null) continue;
      // Static members are not inherited.
      if (e.modifiers.isStatic()) continue;
      return e;
    }
    if (isInterface()) {
      return lookupSuperInterfaceMember(memberName, getLibrary());
    }
    return null;
  }

  Element lookupSuperInterfaceMember(SourceString memberName,
                                     LibraryElement fromLibrary) {
    bool includeInjectedMembers = isPatch;
    bool isPrivate = memberName.isPrivate();
    for (InterfaceType t in interfaces) {
      ClassElement cls = t.element;
      cls = includeInjectedMembers ? cls.implementation : cls;
      Element e = cls.lookupLocalMember(memberName);
      if (e == null) continue;
      // Private members from a different library are not visible.
      if (isPrivate && !identical(fromLibrary, e.getLibrary())) continue;
      // Static members are not inherited.
      if (e.modifiers.isStatic()) continue;
      return e;
    }
    return null;
  }

  /**
   * Find the first member in the class chain with the given [selector].
   *
   * This method is NOT to be used for resolving
   * unqualified sends because it does not implement the scoping
   * rules, where library scope comes before superclass scope.
   *
   * When called on the implementation element both members declared in the
   * origin and the patch class are returned.
   */
  Element lookupSelector(Selector selector) {
    SourceString memberName = selector.name;
    LibraryElement library = selector.library;
    Element localMember = lookupLocalMember(memberName);
    if (localMember != null &&
        (!memberName.isPrivate() || getLibrary() == library)) {
      return localMember;
    }
    return lookupSuperMemberInLibrary(memberName, library);
  }

  /**
   * Find the first member in the class chain with the given
   * [memberName]. This method is NOT to be used for resolving
   * unqualified sends because it does not implement the scoping
   * rules, where library scope comes before superclass scope.
   */
  Element lookupMember(SourceString memberName) {
    Element localMember = lookupLocalMember(memberName);
    return localMember == null ? lookupSuperMember(memberName) : localMember;
  }

  /**
   * Returns true if the [fieldMember] is shadowed by another field. The given
   * [fieldMember] must be a member of this class.
   *
   * This method also works if the [fieldMember] is private.
   */
  bool isShadowedByField(Element fieldMember) {
    assert(fieldMember.isField());
    // Note that we cannot use [lookupMember] or [lookupSuperMember] since it
    // will not do the right thing for private elements.
    ClassElement lookupClass = this;
    LibraryElement memberLibrary = fieldMember.getLibrary();
    if (fieldMember.name.isPrivate()) {
      // We find a super class in the same library as the field. This way the
      // lookupMember will work.
      while (lookupClass.getLibrary() != memberLibrary) {
        lookupClass = lookupClass.superclass;
      }
    }
    SourceString fieldName = fieldMember.name;
    while (true) {
      Element foundMember = lookupClass.lookupMember(fieldName);
      if (foundMember == fieldMember) return false;
      if (foundMember.isField()) return true;
      lookupClass = foundMember.getEnclosingClass().superclass;
    }
  }

  Element validateConstructorLookupResults(Selector selector,
                                           Element result,
                                           Element noMatch(Element)) {
    if (result == null
        || !result.isConstructor()
        || (selector.name.isPrivate()
            && result.getLibrary() != selector.library)) {
      result = noMatch != null ? noMatch(result) : null;
    }
    return result;
  }

  // TODO(aprelev@gmail.com): Peter believes that it would be great to
  // make noMatch a required argument. Peter's suspicion is that most
  // callers of this method would benefit from using the noMatch method.
  Element lookupConstructor(Selector selector, [Element noMatch(Element)]) {
    SourceString normalizedName;
    SourceString className = this.name;
    SourceString constructorName = selector.name;
    if (constructorName != const SourceString('')) {
      normalizedName = Elements.constructConstructorName(className,
                                                         constructorName);
    } else {
      normalizedName = className;
    }
    Element result = localLookup(normalizedName);
    return validateConstructorLookupResults(selector, result, noMatch);
  }

  Element lookupFactoryConstructor(Selector selector,
                                   [Element noMatch(Element)]) {
    SourceString constructorName = selector.name;
    Element result = localLookup(constructorName);
    return validateConstructorLookupResults(selector, result, noMatch);
  }

  bool get hasConstructor {
    // Search in scope to be sure we search patched constructors.
    for (var element in localScope.values) {
      if (element.isConstructor()) return true;
    }
    return false;
  }

  Link<Element> get constructors {
    // TODO(ajohnsen): See if we can avoid this method at some point.
    Link<Element> result = const Link<Element>();
    // TODO(johnniwinther): Should we include injected constructors?
    forEachMember((_, Element member) {
      if (member.isConstructor()) result = result.prepend(member);
    });
    return result;
  }

  /**
   * Returns the super class, if any.
   *
   * The returned element may not be resolved yet.
   */
  ClassElement get superclass {
    assert(supertypeLoadState == STATE_DONE);
    return supertype == null ? null : supertype.element;
  }

  /**
   * Runs through all members of this class.
   *
   * The enclosing class is passed to the callback. This is useful when
   * [includeSuperMembers] is [:true:].
   *
   * When called on an implementation element both the members in the origin
   * and patch class are included.
   */
  // TODO(johnniwinther): Clean up lookup to get rid of the include predicates.
  void forEachMember(void f(ClassElement enclosingClass, Element member),
                     {includeBackendMembers: false,
                      includeSuperMembers: false}) {
    bool includeInjectedMembers = isPatch;
    Set<ClassElement> seen = new Set<ClassElement>();
    ClassElement classElement = declaration;
    do {
      if (seen.contains(classElement)) return;
      seen.add(classElement);

      // Iterate through the members in textual order, which requires
      // to reverse the data structure [localMembers] we created.
      // Textual order may be important for certain operations, for
      // example when emitting the initializers of fields.
      for (Element element in classElement.localMembers.reverse()) {
        f(classElement, element);
      }
      if (includeBackendMembers) {
        for (Element element in classElement.backendMembers) {
          f(classElement, element);
        }
      }
      if (includeInjectedMembers) {
        if (classElement.patch != null) {
          for (Element element in classElement.patch.localMembers.reverse()) {
            if (!element.isPatch) {
              f(classElement, element);
            }
          }
        }
      }
      classElement = includeSuperMembers ? classElement.superclass : null;
    } while(classElement != null);
  }

  /**
   * Runs through all instance-field members of this class.
   *
   * The enclosing class is passed to the callback. This is useful when
   * [includeSuperMembers] is [:true:].
   *
   * When [includeBackendMembers] and [includeSuperMembers] are both [:true:]
   * then the fields are visited in the same order as they need to be given
   * to the JavaScript constructor.
   *
   * When called on the implementation element both the fields declared in the
   * origin and in the patch are included.
   */
  void forEachInstanceField(void f(ClassElement enclosingClass, Element field),
                            {includeBackendMembers: false,
                             includeSuperMembers: false}) {
    // Filters so that [f] is only invoked with instance fields.
    void fieldFilter(ClassElement enclosingClass, Element member) {
      if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
        f(enclosingClass, member);
      }
    }

    forEachMember(fieldFilter,
                  includeBackendMembers: includeBackendMembers,
                  includeSuperMembers: includeSuperMembers);
  }

  bool implementsInterface(ClassElement intrface) {
    for (DartType implementedInterfaceType in allSupertypes) {
      ClassElement implementedInterface = implementedInterfaceType.element;
      if (identical(implementedInterface, intrface)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if [this] is a subclass of [cls].
   *
   * 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) {
    for (ClassElement s = this; s != null; s = s.superclass) {
      if (identical(s, cls)) return true;
    }
    return false;
  }

  bool isInterface() => false;
  bool isNative() => nativeTagInfo != null;
  int get hashCode => id;

  Scope buildScope() => new ClassScope(enclosingElement.buildScope(), this);

  String toString() {
    if (origin != null) {
      return 'patch ${super.toString()}';
    } else if (patch != null) {
      return 'origin ${super.toString()}';
    } else {
      return super.toString();
    }
  }
}

class Elements {
  static bool isUnresolved(Element e) {
    return e == null || e.isErroneous() || e.isMalformed();
  }
  static bool isErroneousElement(Element e) => e != null && e.isErroneous();
  static bool isMalformedElement(Element e) => e != null && e.isMalformed();

  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.isInstanceMember()
            && !isStaticOrTopLevelField(element)
            && !isStaticOrTopLevelFunction(element)
            && (identical(element.kind, ElementKind.VARIABLE) ||
                identical(element.kind, ElementKind.PARAMETER) ||
                identical(element.kind, ElementKind.FUNCTION));
  }

  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(ager): This should not be necessary when patch support has
    // been reworked.
    if (!Elements.isUnresolved(element)
        && element.modifiers.isStatic()) {
      return true;
    }
    return !Elements.isUnresolved(element)
           && !element.isInstanceMember()
           && !element.isPrefix()
           && element.enclosingElement != null
           && (element.enclosingElement.kind == ElementKind.CLASS ||
               element.enclosingElement.kind == ElementKind.COMPILATION_UNIT ||
               element.enclosingElement.kind == ElementKind.LIBRARY);
  }

  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)
           && (identical(element.kind, ElementKind.FUNCTION));
  }

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

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

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

  static SourceString constructConstructorName(SourceString receiver,
                                               SourceString selector) {
    String r = receiver.slowToString();
    String s = selector.slowToString();
    return new SourceString('$r\$$s');
  }

  /**
   * Map an operator-name to a valid Dart identifier.
   *
   * For non-operator names, this metod 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 SourceString operatorNameToIdentifier(SourceString name) {
    if (name == null) return null;
    String value = name.stringValue;
    if (value == null) {
      return name;
    } else if (identical(value, '==')) {
      return const SourceString(r'operator$eq');
    } else if (identical(value, '~')) {
      return const SourceString(r'operator$not');
    } else if (identical(value, '[]')) {
      return const SourceString(r'operator$index');
    } else if (identical(value, '[]=')) {
      return const SourceString(r'operator$indexSet');
    } else if (identical(value, '*')) {
      return const SourceString(r'operator$mul');
    } else if (identical(value, '/')) {
      return const SourceString(r'operator$div');
    } else if (identical(value, '%')) {
      return const SourceString(r'operator$mod');
    } else if (identical(value, '~/')) {
      return const SourceString(r'operator$tdiv');
    } else if (identical(value, '+')) {
      return const SourceString(r'operator$add');
    } else if (identical(value, '<<')) {
      return const SourceString(r'operator$shl');
    } else if (identical(value, '>>')) {
      return const SourceString(r'operator$shr');
    } else if (identical(value, '>=')) {
      return const SourceString(r'operator$ge');
    } else if (identical(value, '>')) {
      return const SourceString(r'operator$gt');
    } else if (identical(value, '<=')) {
      return const SourceString(r'operator$le');
    } else if (identical(value, '<')) {
      return const SourceString(r'operator$lt');
    } else if (identical(value, '&')) {
      return const SourceString(r'operator$and');
    } else if (identical(value, '^')) {
      return const SourceString(r'operator$xor');
    } else if (identical(value, '|')) {
      return const SourceString(r'operator$or');
    } else if (identical(value, '-')) {
      return const SourceString(r'operator$sub');
    } else if (identical(value, 'unary-')) {
      return const SourceString(r'operator$negate');
    } else {
      return name;
    }
  }

  static SourceString constructOperatorNameOrNull(SourceString op,
                                                  bool isUnary) {
    String value = op.stringValue;
    if ((identical(value, '==')) ||
        (identical(value, '~')) ||
        (identical(value, '[]')) ||
        (identical(value, '[]=')) ||
        (identical(value, '*')) ||
        (identical(value, '/')) ||
        (identical(value, '%')) ||
        (identical(value, '~/')) ||
        (identical(value, '+')) ||
        (identical(value, '<<')) ||
        (identical(value, '>>>')) ||
        (identical(value, '>>')) ||
        (identical(value, '>=')) ||
        (identical(value, '>')) ||
        (identical(value, '<=')) ||
        (identical(value, '<')) ||
        (identical(value, '&')) ||
        (identical(value, '^')) ||
        (identical(value, '|'))) {
      return op;
    } else if (identical(value, '-')) {
      return isUnary ? const SourceString('unary-') : op;
    } else {
      return null;
    }
  }

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

  static SourceString mapToUserOperatorOrNull(SourceString op) {
    String value = op.stringValue;

    if (identical(value, '!=')) return const SourceString('==');
    if (identical(value, '*=')) return const SourceString('*');
    if (identical(value, '/=')) return const SourceString('/');
    if (identical(value, '%=')) return const SourceString('%');
    if (identical(value, '~/=')) return const SourceString('~/');
    if (identical(value, '+=')) return const SourceString('+');
    if (identical(value, '-=')) return const SourceString('-');
    if (identical(value, '<<=')) return const SourceString('<<');
    if (identical(value, '>>=')) return const SourceString('>>');
    if (identical(value, '&=')) return const SourceString('&');
    if (identical(value, '^=')) return const SourceString('^');
    if (identical(value, '|=')) return const SourceString('|');

    return null;
  }

  static SourceString mapToUserOperator(SourceString op) {
    SourceString userOperator = mapToUserOperatorOrNull(op);
    if (userOperator == null) throw 'Unhandled operator: ${op.slowToString()}';
    else return userOperator;
  }

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

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

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

class LabelElement extends Element {
  // We store the original label here so it can be returned by [parseNode].
  final Label label;
  final String labelName;
  final TargetElement target;
  bool isBreakTarget = false;
  bool isContinueTarget = false;
  LabelElement(Label label, String labelName, this.target,
               Element enclosingElement)
      : this.label = label,
        this.labelName = labelName,
        // In case of a synthetic label, just use [labelName] for
        // identifying the element.
        super(label == null
                  ? new SourceString(labelName)
                  : label.identifier.source,
              ElementKind.LABEL,
              enclosingElement);

  void setBreakTarget() {
    isBreakTarget = true;
    target.isBreakTarget = true;
  }
  void setContinueTarget() {
    isContinueTarget = true;
    target.isContinueTarget = true;
  }

  bool get isTarget => isBreakTarget || isContinueTarget;
  Node parseNode(DiagnosticListener l) => label;

  Token position() => label.getBeginToken();
  String toString() => "${labelName}:";
}

// Represents a reference to a statement or switch-case, either by label or the
// default target of a break or continue.
class TargetElement extends Element {
  final Node statement;
  final int nestingLevel;
  Link<LabelElement> labels = const Link<LabelElement>();
  bool isBreakTarget = false;
  bool isContinueTarget = false;

  TargetElement(this.statement, this.nestingLevel, Element enclosingElement)
      : super(const SourceString(""), ElementKind.STATEMENT, enclosingElement);
  bool get isTarget => isBreakTarget || isContinueTarget;

  LabelElement addLabel(Label label, String labelName) {
    LabelElement result = new LabelElement(label, labelName, this,
                                           enclosingElement);
    labels = labels.prepend(result);
    return result;
  }

  Node parseNode(DiagnosticListener l) => statement;

  bool get isSwitch => statement is SwitchStatement;

  Token position() => statement.getBeginToken();
  String toString() => statement.toString();
}

class TypeVariableElement extends Element {
  final Node cachedNode;
  TypeVariableType type;
  DartType bound;

  TypeVariableElement(name, Element enclosing, this.cachedNode,
                      [this.type, this.bound])
    : super(name, ElementKind.TYPE_VARIABLE, enclosing);

  TypeVariableType computeType(compiler) => type;

  Node parseNode(compiler) => cachedNode;

  String toString() => "${enclosingElement.toString()}.${name.slowToString()}";

  Token position() => cachedNode.getBeginToken();
}

/**
 * A single metadata annotation.
 *
 * For example, consider:
 *
 * [:
 * class Data {
 *   const Data();
 * }
 *
 * const data = const Data();
 *
 * @data
 * class Foo {}
 *
 * @data @data
 * class Bar {}
 * :]
 *
 * In this example, there are three instances of [MetadataAnnotation]
 * and they correspond each to a location in the source code where
 * there is an at-sign, '@'. The [value] of each of these instances
 * are the same compile-time constant, [: const Data() :].
 *
 * The mirror system does not have a concept matching this class.
 */
abstract class MetadataAnnotation {
  /**
   * The compile-time constant which this annotation resolves to.
   * In the mirror system, this would be an object mirror.
   */
  Constant get value;
  Element annotatedElement;
  int resolutionState;

  MetadataAnnotation([this.resolutionState = STATE_NOT_STARTED]);

  MetadataAnnotation ensureResolved(Compiler compiler) {
    if (resolutionState == STATE_NOT_STARTED) {
      compiler.resolver.resolveMetadataAnnotation(this);
    }
    return this;
  }

  String toString() => 'MetadataAnnotation($value, $resolutionState)';
}
