// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// This code was auto-generated, is not intended to be edited, and is subject to
// significant change. Please see the README file for more information.

library engine.index;

import 'dart:collection' show Queue;
import 'java_core.dart';
import 'java_engine.dart';
import 'source.dart';
import 'scanner.dart' show Token;
import 'ast.dart';
import 'element.dart';
import 'resolver.dart' show Namespace, NamespaceBuilder;
import 'engine.dart';
import 'html.dart' as ht;

/**
 * Visits resolved [CompilationUnit] and adds Angular specific relationships into
 * [IndexStore].
 */
class AngularDartIndexContributor extends GeneralizingAstVisitor<Object> {
  final IndexStore _store;

  AngularDartIndexContributor(this._store);

  @override
  Object visitClassDeclaration(ClassDeclaration node) {
    ClassElement classElement = node.element;
    if (classElement != null) {
      List<ToolkitObjectElement> toolkitObjects = classElement.toolkitObjects;
      for (ToolkitObjectElement object in toolkitObjects) {
        if (object is AngularComponentElement) {
          _indexComponent(object);
        }
        if (object is AngularDecoratorElement) {
          AngularDecoratorElement directive = object;
          _indexDirective(directive);
        }
      }
    }
    // stop visiting
    return null;
  }

  @override
  Object visitCompilationUnitMember(CompilationUnitMember node) => null;

  void _indexComponent(AngularComponentElement component) {
    _indexProperties(component.properties);
  }

  void _indexDirective(AngularDecoratorElement directive) {
    _indexProperties(directive.properties);
  }

  /**
   * Index [FieldElement] references from [AngularPropertyElement]s.
   */
  void _indexProperties(List<AngularPropertyElement> properties) {
    for (AngularPropertyElement property in properties) {
      FieldElement field = property.field;
      if (field != null) {
        int offset = property.fieldNameOffset;
        if (offset == -1) {
          continue;
        }
        int length = field.name.length;
        Location location = new Location(property, offset, length);
        // getter reference
        if (property.propertyKind.callsGetter()) {
          PropertyAccessorElement getter = field.getter;
          if (getter != null) {
            _store.recordRelationship(getter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location);
          }
        }
        // setter reference
        if (property.propertyKind.callsSetter()) {
          PropertyAccessorElement setter = field.setter;
          if (setter != null) {
            _store.recordRelationship(setter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location);
          }
        }
      }
    }
  }
}

/**
 * Visits resolved [HtmlUnit] and adds relationships into [IndexStore].
 */
class AngularHtmlIndexContributor extends ExpressionVisitor {
  /**
   * The [IndexStore] to record relations into.
   */
  final IndexStore _store;

  /**
   * The index contributor used to index Dart [Expression]s.
   */
  IndexContributor _indexContributor;

  HtmlElement _htmlUnitElement;

  /**
   * Initialize a newly created Angular HTML index contributor.
   *
   * @param store the [IndexStore] to record relations into.
   */
  AngularHtmlIndexContributor(this._store) {
    _indexContributor = new IndexContributor_AngularHtmlIndexContributor(_store, this);
  }

  @override
  void visitExpression(Expression expression) {
    // Formatter
    if (expression is SimpleIdentifier) {
      SimpleIdentifier identifier = expression;
      Element element = identifier.bestElement;
      if (element is AngularElement) {
        _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, _createLocationForIdentifier(identifier));
        return;
      }
    }
    // index as a normal Dart expression
    expression.accept(_indexContributor);
  }

  @override
  Object visitHtmlUnit(ht.HtmlUnit node) {
    _htmlUnitElement = node.element;
    CompilationUnitElement dartUnitElement = _htmlUnitElement.angularCompilationUnit;
    _indexContributor.enterScope(dartUnitElement);
    return super.visitHtmlUnit(node);
  }

  @override
  Object visitXmlAttributeNode(ht.XmlAttributeNode node) {
    Element element = node.element;
    if (element != null) {
      ht.Token nameToken = node.nameToken;
      Location location = _createLocationForToken(nameToken);
      _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, location);
    }
    return super.visitXmlAttributeNode(node);
  }

  @override
  Object visitXmlTagNode(ht.XmlTagNode node) {
    Element element = node.element;
    if (element != null) {
      // tag
      {
        ht.Token tagToken = node.tagToken;
        Location location = _createLocationForToken(tagToken);
        _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, location);
      }
      // maybe add closing tag range
      ht.Token closingTag = node.closingTag;
      if (closingTag != null) {
        Location location = _createLocationForToken(closingTag);
        _store.recordRelationship(element, IndexConstants.ANGULAR_CLOSING_TAG_REFERENCE, location);
      }
    }
    return super.visitXmlTagNode(node);
  }

  Location _createLocationForIdentifier(SimpleIdentifier identifier) => new Location(_htmlUnitElement, identifier.offset, identifier.length);

  Location _createLocationForToken(ht.Token token) => new Location(_htmlUnitElement, token.offset, token.length);
}

/**
 * Instances of the [ClearOperation] implement an operation that removes all of the
 * information from the index.
 */
class ClearOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  ClearOperation(this._indexStore);

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    _indexStore.clear();
  }

  @override
  bool removeWhenSourceRemoved(Source source) => false;

  @override
  String toString() => "ClearOperation()";
}

/**
 * Recursively visits [HtmlUnit] and every embedded [Expression].
 */
abstract class ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> {
  /**
   * Visits the given [Expression]s embedded into tag or attribute.
   *
   * @param expression the [Expression] to visit, not `null`
   */
  void visitExpression(Expression expression);

  @override
  Object visitXmlAttributeNode(ht.XmlAttributeNode node) {
    _visitExpressions(node.expressions);
    return super.visitXmlAttributeNode(node);
  }

  @override
  Object visitXmlTagNode(ht.XmlTagNode node) {
    _visitExpressions(node.expressions);
    return super.visitXmlTagNode(node);
  }

  /**
   * Visits [Expression]s of the given [XmlExpression]s.
   */
  void _visitExpressions(List<ht.XmlExpression> expressions) {
    for (ht.XmlExpression xmlExpression in expressions) {
      if (xmlExpression is AngularXmlExpression) {
        AngularXmlExpression angularXmlExpression = xmlExpression;
        List<Expression> dartExpressions = angularXmlExpression.expression.expressions;
        for (Expression dartExpression in dartExpressions) {
          visitExpression(dartExpression);
        }
      }
      if (xmlExpression is ht.RawXmlExpression) {
        ht.RawXmlExpression rawXmlExpression = xmlExpression;
        visitExpression(rawXmlExpression.expression);
      }
    }
  }
}

/**
 * Instances of the [GetRelationshipsOperation] implement an operation used to access the
 * locations that have a specified relationship with a specified element.
 */
class GetRelationshipsOperation implements IndexOperation {
  final IndexStore _indexStore;

  final Element element;

  final Relationship relationship;

  final RelationshipCallback callback;

  /**
   * Initialize a newly created operation that will access the locations that have a specified
   * relationship with a specified element.
   */
  GetRelationshipsOperation(this._indexStore, this.element, this.relationship, this.callback);

  @override
  bool get isQuery => true;

  @override
  void performOperation() {
    List<Location> locations;
    locations = _indexStore.getRelationships(element, relationship);
    callback.hasRelationships(element, relationship, locations);
  }

  @override
  bool removeWhenSourceRemoved(Source source) => false;

  @override
  String toString() => "GetRelationships(${element}, ${relationship})";
}

/**
 * The interface [Index] defines the behavior of objects that maintain an index storing
 * [Relationship] between [Element]. All of the operations
 * defined on the index are asynchronous, and results, when there are any, are provided through a
 * callback.
 *
 * Despite being asynchronous, the results of the operations are guaranteed to be consistent with
 * the expectation that operations are performed in the order in which they are requested.
 * Modification operations are executed before any read operation. There is no guarantee about the
 * order in which the callbacks for read operations will be invoked.
 */
abstract class Index {
  /**
   * Asynchronously remove from the index all of the information.
   */
  void clear();

  /**
   * Asynchronously invoke the given callback with an array containing all of the locations of the
   * elements that have the given relationship with the given element. For example, if the element
   * represents a method and the relationship is the is-referenced-by relationship, then the
   * locations that will be passed into the callback will be all of the places where the method is
   * invoked.
   *
   * @param element the element that has the relationship with the locations to be returned
   * @param relationship the relationship between the given element and the locations to be returned
   * @param callback the callback that will be invoked when the locations are found
   */
  void getRelationships(Element element, Relationship relationship, RelationshipCallback callback);

  /**
   * Answer index statistics.
   */
  String get statistics;

  /**
   * Asynchronously process the given [HtmlUnit] in order to record the relationships.
   *
   * @param context the [AnalysisContext] in which [HtmlUnit] was resolved
   * @param unit the [HtmlUnit] being indexed
   */
  void indexHtmlUnit(AnalysisContext context, ht.HtmlUnit unit);

  /**
   * Asynchronously process the given [CompilationUnit] in order to record the relationships.
   *
   * @param context the [AnalysisContext] in which [CompilationUnit] was resolved
   * @param unit the [CompilationUnit] being indexed
   */
  void indexUnit(AnalysisContext context, CompilationUnit unit);

  /**
   * Asynchronously remove from the index all of the information associated with the given context.
   *
   * This method should be invoked when a context is disposed.
   *
   * @param context the [AnalysisContext] to remove
   */
  void removeContext(AnalysisContext context);

  /**
   * Asynchronously remove from the index all of the information associated with elements or
   * locations in the given source. This includes relationships between an element in the given
   * source and any other locations, relationships between any other elements and a location within
   * the given source.
   *
   * This method should be invoked when a source is no longer part of the code base.
   *
   * @param context the [AnalysisContext] in which [Source] being removed
   * @param source the [Source] being removed
   */
  void removeSource(AnalysisContext context, Source source);

  /**
   * Asynchronously remove from the index all of the information associated with elements or
   * locations in the given sources. This includes relationships between an element in the given
   * sources and any other locations, relationships between any other elements and a location within
   * the given sources.
   *
   * This method should be invoked when multiple sources are no longer part of the code base.
   *
   * @param the [AnalysisContext] in which [Source]s being removed
   * @param container the [SourceContainer] holding the sources being removed
   */
  void removeSources(AnalysisContext context, SourceContainer container);

  /**
   * Should be called in separate [Thread] to process request in this [Index]. Does not
   * return until the [stop] method is called.
   */
  void run();

  /**
   * Should be called to stop process running [run], so stop processing requests.
   */
  void stop();
}

/**
 * Constants used when populating and accessing the index.
 */
abstract class IndexConstants {
  /**
   * An element used to represent the universe.
   */
  static final Element UNIVERSE = UniverseElement.INSTANCE;

  /**
   * The relationship used to indicate that a container (the left-operand) contains the definition
   * of a class at a specific location (the right operand).
   */
  static final Relationship DEFINES_CLASS = Relationship.getRelationship("defines-class");

  /**
   * The relationship used to indicate that a container (the left-operand) contains the definition
   * of a function at a specific location (the right operand).
   */
  static final Relationship DEFINES_FUNCTION = Relationship.getRelationship("defines-function");

  /**
   * The relationship used to indicate that a container (the left-operand) contains the definition
   * of a class type alias at a specific location (the right operand).
   */
  static final Relationship DEFINES_CLASS_ALIAS = Relationship.getRelationship("defines-class-alias");

  /**
   * The relationship used to indicate that a container (the left-operand) contains the definition
   * of a function type at a specific location (the right operand).
   */
  static final Relationship DEFINES_FUNCTION_TYPE = Relationship.getRelationship("defines-function-type");

  /**
   * The relationship used to indicate that a container (the left-operand) contains the definition
   * of a method at a specific location (the right operand).
   */
  static final Relationship DEFINES_VARIABLE = Relationship.getRelationship("defines-variable");

  /**
   * The relationship used to indicate that a name (the left-operand) is defined at a specific
   * location (the right operand).
   */
  static final Relationship IS_DEFINED_BY = Relationship.getRelationship("is-defined-by");

  /**
   * The relationship used to indicate that a type (the left-operand) is extended by a type at a
   * specific location (the right operand).
   */
  static final Relationship IS_EXTENDED_BY = Relationship.getRelationship("is-extended-by");

  /**
   * The relationship used to indicate that a type (the left-operand) is implemented by a type at a
   * specific location (the right operand).
   */
  static final Relationship IS_IMPLEMENTED_BY = Relationship.getRelationship("is-implemented-by");

  /**
   * The relationship used to indicate that a type (the left-operand) is mixed into a type at a
   * specific location (the right operand).
   */
  static final Relationship IS_MIXED_IN_BY = Relationship.getRelationship("is-mixed-in-by");

  /**
   * The relationship used to indicate that a parameter or variable (the left-operand) is read at a
   * specific location (the right operand).
   */
  static final Relationship IS_READ_BY = Relationship.getRelationship("is-read-by");

  /**
   * The relationship used to indicate that a parameter or variable (the left-operand) is both read
   * and modified at a specific location (the right operand).
   */
  static final Relationship IS_READ_WRITTEN_BY = Relationship.getRelationship("is-read-written-by");

  /**
   * The relationship used to indicate that a parameter or variable (the left-operand) is modified
   * (assigned to) at a specific location (the right operand).
   */
  static final Relationship IS_WRITTEN_BY = Relationship.getRelationship("is-written-by");

  /**
   * The relationship used to indicate that an element (the left-operand) is referenced at a
   * specific location (the right operand). This is used for everything except read/write operations
   * for fields, parameters, and variables. Those use either [IS_REFERENCED_BY_QUALIFIED],
   * [IS_REFERENCED_BY_UNQUALIFIED], [IS_READ_BY], [IS_WRITTEN_BY] or
   * [IS_READ_WRITTEN_BY], as appropriate.
   */
  static final Relationship IS_REFERENCED_BY = Relationship.getRelationship("is-referenced-by");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is
   * referenced at a specific location (the right operand). This is used for qualified resolved
   * references to methods and fields.
   */
  static final Relationship IS_REFERENCED_BY_QUALIFIED_RESOLVED = Relationship.getRelationship("is-referenced-by-qualified-resolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is
   * referenced at a specific location (the right operand). This is used for qualified unresolved
   * references to methods and fields.
   */
  static final Relationship IS_REFERENCED_BY_QUALIFIED_UNRESOLVED = Relationship.getRelationship("is-referenced-by-qualified-unresolved");

  /**
   * The relationship used to indicate that an element (the left-operand) is referenced at a
   * specific location (the right operand). This is used for field accessors and methods.
   */
  static final Relationship IS_REFERENCED_BY_QUALIFIED = Relationship.getRelationship("is-referenced-by-qualified");

  /**
   * The relationship used to indicate that an element (the left-operand) is referenced at a
   * specific location (the right operand). This is used for field accessors and methods.
   */
  static final Relationship IS_REFERENCED_BY_UNQUALIFIED = Relationship.getRelationship("is-referenced-by-unqualified");

  /**
   * The relationship used to indicate that an element (the left-operand) is invoked at a specific
   * location (the right operand). This is used for functions.
   */
  static final Relationship IS_INVOKED_BY = Relationship.getRelationship("is-invoked-by");

  /**
   * The relationship used to indicate that an element (the left-operand) is invoked at a specific
   * location (the right operand). This is used for methods.
   */
  static final Relationship IS_INVOKED_BY_QUALIFIED = Relationship.getRelationship("is-invoked-by-qualified");

  /**
   * The relationship used to indicate that an element (the left-operand) is invoked at a specific
   * location (the right operand). This is used for methods.
   */
  static final Relationship IS_INVOKED_BY_UNQUALIFIED = Relationship.getRelationship("is-invoked-by-unqualified");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is invoked
   * at a specific location (the right operand). This is used for resolved invocations.
   */
  static final Relationship NAME_IS_INVOKED_BY_RESOLVED = Relationship.getRelationship("name-is-invoked-by-resolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is read at
   * a specific location (the right operand).
   */
  static final Relationship NAME_IS_READ_BY_RESOLVED = Relationship.getRelationship("name-is-read-by-resolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is both
   * read and written at a specific location (the right operand).
   */
  static final Relationship NAME_IS_READ_WRITTEN_BY_RESOLVED = Relationship.getRelationship("name-is-read-written-by-resolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is written
   * at a specific location (the right operand).
   */
  static final Relationship NAME_IS_WRITTEN_BY_RESOLVED = Relationship.getRelationship("name-is-written-by-resolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is invoked
   * at a specific location (the right operand). This is used for unresolved invocations.
   */
  static final Relationship NAME_IS_INVOKED_BY_UNRESOLVED = Relationship.getRelationship("name-is-invoked-by-unresolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is read at
   * a specific location (the right operand).
   */
  static final Relationship NAME_IS_READ_BY_UNRESOLVED = Relationship.getRelationship("name-is-read-by-unresolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is both
   * read and written at a specific location (the right operand).
   */
  static final Relationship NAME_IS_READ_WRITTEN_BY_UNRESOLVED = Relationship.getRelationship("name-is-read-written-by-unresolved");

  /**
   * The relationship used to indicate that an [NameElementImpl] (the left-operand) is written
   * at a specific location (the right operand).
   */
  static final Relationship NAME_IS_WRITTEN_BY_UNRESOLVED = Relationship.getRelationship("name-is-written-by-unresolved");

  /**
   * Reference to some [AngularElement].
   */
  static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("angular-reference");

  /**
   * Reference to some closing tag of an XML element.
   */
  static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRelationship("angular-closing-tag-reference");
}

/**
 * Visits resolved AST and adds relationships into [IndexStore].
 */
class IndexContributor extends GeneralizingAstVisitor<Object> {
  /**
   * @return the [Location] representing location of the [Element].
   */
  static Location createLocation(Element element) {
    if (element != null) {
      int offset = element.nameOffset;
      int length = element.displayName.length;
      return new Location(element, offset, length);
    }
    return null;
  }

  /**
   * @return the [ImportElement] that is referenced by this node with [PrefixElement],
   *         may be `null`.
   */
  static ImportElement getImportElement(SimpleIdentifier prefixNode) {
    IndexContributor_ImportElementInfo info = getImportElementInfo(prefixNode);
    return info != null ? info._element : null;
  }

  /**
   * @return the [ImportElementInfo] with [ImportElement] that is referenced by this
   *         node with [PrefixElement], may be `null`.
   */
  static IndexContributor_ImportElementInfo getImportElementInfo(SimpleIdentifier prefixNode) {
    IndexContributor_ImportElementInfo info = new IndexContributor_ImportElementInfo();
    // prepare environment
    AstNode parent = prefixNode.parent;
    CompilationUnit unit = prefixNode.getAncestor((node) => node is CompilationUnit);
    LibraryElement libraryElement = unit.element.library;
    // prepare used element
    Element usedElement = null;
    if (parent is PrefixedIdentifier) {
      PrefixedIdentifier prefixed = parent;
      if (identical(prefixed.prefix, prefixNode)) {
        usedElement = prefixed.staticElement;
        info._periodEnd = prefixed.period.end;
      }
    }
    if (parent is MethodInvocation) {
      MethodInvocation invocation = parent;
      if (identical(invocation.target, prefixNode)) {
        usedElement = invocation.methodName.staticElement;
        info._periodEnd = invocation.period.end;
      }
    }
    // we need used Element
    if (usedElement == null) {
      return null;
    }
    // find ImportElement
    String prefix = prefixNode.name;
    Map<ImportElement, Set<Element>> importElementsMap = {};
    info._element = _internalGetImportElement(libraryElement, prefix, usedElement, importElementsMap);
    if (info._element == null) {
      return null;
    }
    return info;
  }

  /**
   * If the given expression has resolved type, returns the new location with this type.
   *
   * @param location the base location
   * @param expression the expression assigned at the given location
   */
  static Location _getLocationWithExpressionType(Location location, Expression expression) {
    if (expression != null) {
      return new LocationWithData<DartType>.con1(location, expression.bestType);
    }
    return location;
  }

  /**
   * If the given node is the part of the [ConstructorFieldInitializer], returns location with
   * type of the initializer expression.
   */
  static Location _getLocationWithInitializerType(SimpleIdentifier node, Location location) {
    if (node.parent is ConstructorFieldInitializer) {
      ConstructorFieldInitializer initializer = node.parent as ConstructorFieldInitializer;
      if (identical(initializer.fieldName, node)) {
        location = _getLocationWithExpressionType(location, initializer.expression);
      }
    }
    return location;
  }

  /**
   * If the given identifier has a synthetic [PropertyAccessorElement], i.e. accessor for
   * normal field, and it is LHS of assignment, then include [Type] of the assigned value into
   * the [Location].
   *
   * @param identifier the identifier to record location
   * @param element the element of the identifier
   * @param location the raw location
   * @return the [Location] with the type of the assigned value
   */
  static Location _getLocationWithTypeAssignedToField(SimpleIdentifier identifier, Element element, Location location) {
    // we need accessor
    if (element is! PropertyAccessorElement) {
      return location;
    }
    PropertyAccessorElement accessor = element as PropertyAccessorElement;
    // should be setter
    if (!accessor.isSetter) {
      return location;
    }
    // accessor should be synthetic, i.e. field normal
    if (!accessor.isSynthetic) {
      return location;
    }
    // should be LHS of assignment
    AstNode parent;
    {
      AstNode node = identifier;
      parent = node.parent;
      // new T().field = x;
      if (parent is PropertyAccess) {
        PropertyAccess propertyAccess = parent as PropertyAccess;
        if (identical(propertyAccess.propertyName, node)) {
          node = propertyAccess;
          parent = propertyAccess.parent;
        }
      }
      // obj.field = x;
      if (parent is PrefixedIdentifier) {
        PrefixedIdentifier prefixedIdentifier = parent as PrefixedIdentifier;
        if (identical(prefixedIdentifier.identifier, node)) {
          node = prefixedIdentifier;
          parent = prefixedIdentifier.parent;
        }
      }
    }
    // OK, remember the type
    if (parent is AssignmentExpression) {
      AssignmentExpression assignment = parent as AssignmentExpression;
      Expression rhs = assignment.rightHandSide;
      location = _getLocationWithExpressionType(location, rhs);
    }
    // done
    return location;
  }

  /**
   * @return the [ImportElement] that declares given [PrefixElement] and imports library
   *         with given "usedElement".
   */
  static ImportElement _internalGetImportElement(LibraryElement libraryElement, String prefix, Element usedElement, Map<ImportElement, Set<Element>> importElementsMap) {
    // validate Element
    if (usedElement == null) {
      return null;
    }
    if (usedElement.enclosingElement is! CompilationUnitElement) {
      return null;
    }
    LibraryElement usedLibrary = usedElement.library;
    // find ImportElement that imports used library with used prefix
    List<ImportElement> candidates = null;
    for (ImportElement importElement in libraryElement.imports) {
      // required library
      if (importElement.importedLibrary != usedLibrary) {
        continue;
      }
      // required prefix
      PrefixElement prefixElement = importElement.prefix;
      if (prefix == null) {
        if (prefixElement != null) {
          continue;
        }
      } else {
        if (prefixElement == null) {
          continue;
        }
        if (prefix != prefixElement.name) {
          continue;
        }
      }
      // no combinators => only possible candidate
      if (importElement.combinators.length == 0) {
        return importElement;
      }
      // OK, we have candidate
      if (candidates == null) {
        candidates = [];
      }
      candidates.add(importElement);
    }
    // no candidates, probably element is defined in this library
    if (candidates == null) {
      return null;
    }
    // one candidate
    if (candidates.length == 1) {
      return candidates[0];
    }
    // ensure that each ImportElement has set of elements
    for (ImportElement importElement in candidates) {
      if (importElementsMap.containsKey(importElement)) {
        continue;
      }
      Namespace namespace = new NamespaceBuilder().createImportNamespaceForDirective(importElement);
      Set<Element> elements = new Set();
      importElementsMap[importElement] = elements;
    }
    // use import namespace to choose correct one
    for (MapEntry<ImportElement, Set<Element>> entry in getMapEntrySet(importElementsMap)) {
      if (entry.getValue().contains(usedElement)) {
        return entry.getKey();
      }
    }
    // not found
    return null;
  }

  /**
   * @return `true` if given "node" is part of an import [Combinator].
   */
  static bool _isIdentifierInImportCombinator(SimpleIdentifier node) {
    AstNode parent = node.parent;
    return parent is Combinator;
  }

  /**
   * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node".
   */
  static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) {
    AstNode parent = node.parent;
    return parent is PrefixedIdentifier && identical(parent.identifier, node);
  }

  /**
   * @return `true` if given [SimpleIdentifier] is "name" part of prefixed identifier or
   *         method invocation.
   */
  static bool _isQualified(SimpleIdentifier node) {
    AstNode parent = node.parent;
    if (parent is PrefixedIdentifier) {
      return identical(parent.identifier, node);
    }
    if (parent is PropertyAccess) {
      return identical(parent.propertyName, node);
    }
    if (parent is MethodInvocation) {
      MethodInvocation invocation = parent;
      return invocation.realTarget != null && identical(invocation.methodName, node);
    }
    return false;
  }

  final IndexStore _store;

  LibraryElement _libraryElement;

  Map<ImportElement, Set<Element>> _importElementsMap = {};

  /**
   * A stack whose top element (the element with the largest index) is an element representing the
   * inner-most enclosing scope.
   */
  Queue<Element> _elementStack = new Queue();

  IndexContributor(this._store);

  /**
   * Enter a new scope represented by the given [Element].
   */
  void enterScope(Element element) {
    _elementStack.addFirst(element);
  }

  /**
   * @return the inner-most enclosing [Element], may be `null`.
   */
  Element peekElement() {
    for (Element element in _elementStack) {
      if (element != null) {
        return element;
      }
    }
    return null;
  }

  @override
  Object visitAssignmentExpression(AssignmentExpression node) {
    _recordOperatorReference(node.operator, node.bestElement);
    return super.visitAssignmentExpression(node);
  }

  @override
  Object visitBinaryExpression(BinaryExpression node) {
    _recordOperatorReference(node.operator, node.bestElement);
    return super.visitBinaryExpression(node);
  }

  @override
  Object visitClassDeclaration(ClassDeclaration node) {
    ClassElement element = node.element;
    enterScope(element);
    try {
      _recordElementDefinition(element, IndexConstants.DEFINES_CLASS);
      {
        ExtendsClause extendsClause = node.extendsClause;
        if (extendsClause != null) {
          TypeName superclassNode = extendsClause.superclass;
          _recordSuperType(superclassNode, IndexConstants.IS_EXTENDED_BY);
        } else {
          InterfaceType superType = element.supertype;
          if (superType != null) {
            ClassElement objectElement = superType.element;
            recordRelationship(objectElement, IndexConstants.IS_EXTENDED_BY, _createLocationFromOffset(node.name.offset, 0));
          }
        }
      }
      {
        WithClause withClause = node.withClause;
        if (withClause != null) {
          for (TypeName mixinNode in withClause.mixinTypes) {
            _recordSuperType(mixinNode, IndexConstants.IS_MIXED_IN_BY);
          }
        }
      }
      {
        ImplementsClause implementsClause = node.implementsClause;
        if (implementsClause != null) {
          for (TypeName interfaceNode in implementsClause.interfaces) {
            _recordSuperType(interfaceNode, IndexConstants.IS_IMPLEMENTED_BY);
          }
        }
      }
      return super.visitClassDeclaration(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitClassTypeAlias(ClassTypeAlias node) {
    ClassElement element = node.element;
    enterScope(element);
    try {
      _recordElementDefinition(element, IndexConstants.DEFINES_CLASS_ALIAS);
      {
        TypeName superclassNode = node.superclass;
        if (superclassNode != null) {
          _recordSuperType(superclassNode, IndexConstants.IS_EXTENDED_BY);
        }
      }
      {
        WithClause withClause = node.withClause;
        if (withClause != null) {
          for (TypeName mixinNode in withClause.mixinTypes) {
            _recordSuperType(mixinNode, IndexConstants.IS_MIXED_IN_BY);
          }
        }
      }
      {
        ImplementsClause implementsClause = node.implementsClause;
        if (implementsClause != null) {
          for (TypeName interfaceNode in implementsClause.interfaces) {
            _recordSuperType(interfaceNode, IndexConstants.IS_IMPLEMENTED_BY);
          }
        }
      }
      return super.visitClassTypeAlias(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitCompilationUnit(CompilationUnit node) {
    CompilationUnitElement unitElement = node.element;
    if (unitElement != null) {
      _elementStack.add(unitElement);
      _libraryElement = unitElement.enclosingElement;
      if (_libraryElement != null) {
        return super.visitCompilationUnit(node);
      }
    }
    return null;
  }

  @override
  Object visitConstructorDeclaration(ConstructorDeclaration node) {
    ConstructorElement element = node.element;
    // define
    {
      Location location;
      if (node.name != null) {
        int start = node.period.offset;
        int end = node.name.end;
        location = _createLocationFromOffset(start, end - start);
      } else {
        int start = node.returnType.end;
        location = _createLocationFromOffset(start, 0);
      }
      recordRelationship(element, IndexConstants.IS_DEFINED_BY, location);
    }
    // visit children
    enterScope(element);
    try {
      return super.visitConstructorDeclaration(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitConstructorName(ConstructorName node) {
    ConstructorElement element = node.staticElement;
    // in 'class B = A;' actually A constructors are invoked
    if (element != null && element.isSynthetic && element.redirectedConstructor != null) {
      element = element.redirectedConstructor;
    }
    // prepare location
    Location location;
    if (node.name != null) {
      int start = node.period.offset;
      int end = node.name.end;
      location = _createLocationFromOffset(start, end - start);
    } else {
      int start = node.type.end;
      location = _createLocationFromOffset(start, 0);
    }
    // record relationship
    recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
    return super.visitConstructorName(node);
  }

  @override
  Object visitExportDirective(ExportDirective node) {
    ExportElement element = node.element;
    if (element != null) {
      LibraryElement expLibrary = element.exportedLibrary;
      _recordLibraryReference(node, expLibrary);
    }
    return super.visitExportDirective(node);
  }

  @override
  Object visitFormalParameter(FormalParameter node) {
    ParameterElement element = node.element;
    enterScope(element);
    try {
      return super.visitFormalParameter(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitFunctionDeclaration(FunctionDeclaration node) {
    Element element = node.element;
    _recordElementDefinition(element, IndexConstants.DEFINES_FUNCTION);
    enterScope(element);
    try {
      return super.visitFunctionDeclaration(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
    Element element = node.element;
    _recordElementDefinition(element, IndexConstants.DEFINES_FUNCTION_TYPE);
    return super.visitFunctionTypeAlias(node);
  }

  @override
  Object visitImportDirective(ImportDirective node) {
    ImportElement element = node.element;
    if (element != null) {
      LibraryElement impLibrary = element.importedLibrary;
      _recordLibraryReference(node, impLibrary);
    }
    return super.visitImportDirective(node);
  }

  @override
  Object visitIndexExpression(IndexExpression node) {
    MethodElement element = node.bestElement;
    if (element is MethodElement) {
      Token operator = node.leftBracket;
      Location location = _createLocationFromToken(operator);
      recordRelationship(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, location);
    }
    return super.visitIndexExpression(node);
  }

  @override
  Object visitMethodDeclaration(MethodDeclaration node) {
    ExecutableElement element = node.element;
    enterScope(element);
    try {
      return super.visitMethodDeclaration(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitMethodInvocation(MethodInvocation node) {
    SimpleIdentifier name = node.methodName;
    Element element = name.bestElement;
    if (element is MethodElement) {
      Location location = _createLocationFromNode(name);
      Relationship relationship;
      if (node.target != null) {
        relationship = IndexConstants.IS_INVOKED_BY_QUALIFIED;
      } else {
        relationship = IndexConstants.IS_INVOKED_BY_UNQUALIFIED;
      }
      recordRelationship(element, relationship, location);
    }
    if (element is FunctionElement || element is VariableElement) {
      Location location = _createLocationFromNode(name);
      recordRelationship(element, IndexConstants.IS_INVOKED_BY, location);
    }
    // name invocation
    {
      Element nameElement = new NameElementImpl(name.name);
      Location location = _createLocationFromNode(name);
      Relationship kind = element != null ? IndexConstants.NAME_IS_INVOKED_BY_RESOLVED : IndexConstants.NAME_IS_INVOKED_BY_UNRESOLVED;
      _store.recordRelationship(nameElement, kind, location);
    }
    _recordImportElementReferenceWithoutPrefix(name);
    return super.visitMethodInvocation(node);
  }

  @override
  Object visitPartDirective(PartDirective node) {
    Element element = node.element;
    Location location = _createLocationFromNode(node.uri);
    recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
    return super.visitPartDirective(node);
  }

  @override
  Object visitPartOfDirective(PartOfDirective node) {
    Location location = _createLocationFromNode(node.libraryName);
    recordRelationship(node.element, IndexConstants.IS_REFERENCED_BY, location);
    return null;
  }

  @override
  Object visitPostfixExpression(PostfixExpression node) {
    _recordOperatorReference(node.operator, node.bestElement);
    return super.visitPostfixExpression(node);
  }

  @override
  Object visitPrefixExpression(PrefixExpression node) {
    _recordOperatorReference(node.operator, node.bestElement);
    return super.visitPrefixExpression(node);
  }

  @override
  Object visitSimpleIdentifier(SimpleIdentifier node) {
    Element nameElement = new NameElementImpl(node.name);
    Location location = _createLocationFromNode(node);
    // name in declaration
    if (node.inDeclarationContext()) {
      recordRelationship(nameElement, IndexConstants.IS_DEFINED_BY, location);
      return null;
    }
    // prepare information
    Element element = node.bestElement;
    // qualified name reference
    _recordQualifiedMemberReference(node, element, nameElement, location);
    // stop if already handled
    if (_isAlreadyHandledName(node)) {
      return null;
    }
    // record name read/write
    {
      bool inGetterContext = node.inGetterContext();
      bool inSetterContext = node.inSetterContext();
      if (inGetterContext && inSetterContext) {
        Relationship kind = element != null ? IndexConstants.NAME_IS_READ_WRITTEN_BY_RESOLVED : IndexConstants.NAME_IS_READ_WRITTEN_BY_UNRESOLVED;
        _store.recordRelationship(nameElement, kind, location);
      } else if (inGetterContext) {
        Relationship kind = element != null ? IndexConstants.NAME_IS_READ_BY_RESOLVED : IndexConstants.NAME_IS_READ_BY_UNRESOLVED;
        _store.recordRelationship(nameElement, kind, location);
      } else if (inSetterContext) {
        Relationship kind = element != null ? IndexConstants.NAME_IS_WRITTEN_BY_RESOLVED : IndexConstants.NAME_IS_WRITTEN_BY_UNRESOLVED;
        _store.recordRelationship(nameElement, kind, location);
      }
    }
    // record specific relations
    if (element is ClassElement || element is FunctionElement || element is FunctionTypeAliasElement || element is LabelElement || element is TypeParameterElement) {
      recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
    } else if (element is FieldElement) {
      location = _getLocationWithInitializerType(node, location);
      recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
    } else if (element is FieldFormalParameterElement) {
      FieldFormalParameterElement fieldParameter = element;
      FieldElement field = fieldParameter.field;
      recordRelationship(field, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location);
    } else if (element is PrefixElement) {
      _recordImportElementReferenceWithPrefix(node);
    } else if (element is PropertyAccessorElement || element is MethodElement) {
      location = _getLocationWithTypeAssignedToField(node, element, location);
      if (_isQualified(node)) {
        recordRelationship(element, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location);
      } else {
        recordRelationship(element, IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, location);
      }
    } else if (element is ParameterElement || element is LocalVariableElement) {
      bool inGetterContext = node.inGetterContext();
      bool inSetterContext = node.inSetterContext();
      if (inGetterContext && inSetterContext) {
        recordRelationship(element, IndexConstants.IS_READ_WRITTEN_BY, location);
      } else if (inGetterContext) {
        recordRelationship(element, IndexConstants.IS_READ_BY, location);
      } else if (inSetterContext) {
        recordRelationship(element, IndexConstants.IS_WRITTEN_BY, location);
      } else {
        recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
      }
    }
    _recordImportElementReferenceWithoutPrefix(node);
    return super.visitSimpleIdentifier(node);
  }

  @override
  Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    ConstructorElement element = node.staticElement;
    Location location;
    if (node.constructorName != null) {
      int start = node.period.offset;
      int end = node.constructorName.end;
      location = _createLocationFromOffset(start, end - start);
    } else {
      int start = node.keyword.end;
      location = _createLocationFromOffset(start, 0);
    }
    recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location);
    return super.visitSuperConstructorInvocation(node);
  }

  @override
  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    VariableDeclarationList variables = node.variables;
    for (VariableDeclaration variableDeclaration in variables.variables) {
      Element element = variableDeclaration.element;
      _recordElementDefinition(element, IndexConstants.DEFINES_VARIABLE);
    }
    return super.visitTopLevelVariableDeclaration(node);
  }

  @override
  Object visitTypeParameter(TypeParameter node) {
    TypeParameterElement element = node.element;
    enterScope(element);
    try {
      return super.visitTypeParameter(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitVariableDeclaration(VariableDeclaration node) {
    VariableElement element = node.element;
    // record declaration
    {
      SimpleIdentifier name = node.name;
      Location location = _createLocationFromNode(name);
      location = _getLocationWithExpressionType(location, node.initializer);
      recordRelationship(element, IndexConstants.IS_DEFINED_BY, location);
    }
    // visit
    enterScope(element);
    try {
      return super.visitVariableDeclaration(node);
    } finally {
      _exitScope();
    }
  }

  @override
  Object visitVariableDeclarationList(VariableDeclarationList node) {
    NodeList<VariableDeclaration> variables = node.variables;
    if (variables != null) {
      // use first VariableDeclaration as Element for Location(s) in type
      {
        TypeName type = node.type;
        if (type != null) {
          for (VariableDeclaration variableDeclaration in variables) {
            enterScope(variableDeclaration.element);
            try {
              type.accept(this);
            } finally {
              _exitScope();
            }
            // only one iteration
            break;
          }
        }
      }
      // visit variables
      variables.accept(this);
    }
    return null;
  }

  /**
   * Record the given relationship between the given [Element] and [Location].
   */
  void recordRelationship(Element element, Relationship relationship, Location location) {
    if (element != null && location != null) {
      _store.recordRelationship(element, relationship, location);
    }
  }

  /**
   * @return the [Location] representing location of the [AstNode].
   */
  Location _createLocationFromNode(AstNode node) => _createLocationFromOffset(node.offset, node.length);

  /**
   * @param offset the offset of the location within [Source]
   * @param length the length of the location
   * @return the [Location] representing the given offset and length within the inner-most
   *         [Element].
   */
  Location _createLocationFromOffset(int offset, int length) {
    Element element = peekElement();
    return new Location(element, offset, length);
  }

  /**
   * @return the [Location] representing location of the [Token].
   */
  Location _createLocationFromToken(Token token) => _createLocationFromOffset(token.offset, token.length);

  /**
   * Exit the current scope.
   */
  void _exitScope() {
    _elementStack.removeFirst();
  }

  /**
   * @return `true` if given node already indexed as more interesting reference, so it should
   *         not be indexed again.
   */
  bool _isAlreadyHandledName(SimpleIdentifier node) {
    AstNode parent = node.parent;
    if (parent is MethodInvocation) {
      return identical(parent.methodName, node);
    }
    return false;
  }

  /**
   * Records the [Element] definition in the library and universe.
   */
  void _recordElementDefinition(Element element, Relationship relationship) {
    Location location = createLocation(element);
    recordRelationship(_libraryElement, relationship, location);
    recordRelationship(IndexConstants.UNIVERSE, relationship, location);
  }

  /**
   * Records [ImportElement] reference if given [SimpleIdentifier] references some
   * top-level element and not qualified with import prefix.
   */
  void _recordImportElementReferenceWithoutPrefix(SimpleIdentifier node) {
    if (_isIdentifierInImportCombinator(node)) {
      return;
    }
    if (_isIdentifierInPrefixedIdentifier(node)) {
      return;
    }
    Element element = node.staticElement;
    ImportElement importElement = _internalGetImportElement(_libraryElement, null, element, _importElementsMap);
    if (importElement != null) {
      Location location = _createLocationFromOffset(node.offset, 0);
      recordRelationship(importElement, IndexConstants.IS_REFERENCED_BY, location);
    }
  }

  /**
   * Records [ImportElement] that declares given prefix and imports library with element used
   * with given prefix node.
   */
  void _recordImportElementReferenceWithPrefix(SimpleIdentifier prefixNode) {
    IndexContributor_ImportElementInfo info = getImportElementInfo(prefixNode);
    if (info != null) {
      int offset = prefixNode.offset;
      int length = info._periodEnd - offset;
      Location location = _createLocationFromOffset(offset, length);
      recordRelationship(info._element, IndexConstants.IS_REFERENCED_BY, location);
    }
  }

  /**
   * Records reference to defining [CompilationUnitElement] of the given
   * [LibraryElement].
   */
  void _recordLibraryReference(UriBasedDirective node, LibraryElement library) {
    if (library != null) {
      Location location = _createLocationFromNode(node.uri);
      recordRelationship(library.definingCompilationUnit, IndexConstants.IS_REFERENCED_BY, location);
    }
  }

  /**
   * Record reference to the given operator [Element] and name.
   */
  void _recordOperatorReference(Token operator, Element element) {
    // prepare location
    Location location = _createLocationFromToken(operator);
    // record name reference
    {
      String name = operator.lexeme;
      if (name == "++") {
        name = "+";
      }
      if (name == "--") {
        name = "-";
      }
      if (StringUtilities.endsWithChar(name, 0x3D) && name != "==") {
        name = name.substring(0, name.length - 1);
      }
      Element nameElement = new NameElementImpl(name);
      Relationship relationship = element != null ? IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED : IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED;
      recordRelationship(nameElement, relationship, location);
    }
    // record element reference
    if (element != null) {
      recordRelationship(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, location);
    }
  }

  /**
   * Records reference if the given [SimpleIdentifier] looks like a qualified property access
   * or method invocation.
   */
  void _recordQualifiedMemberReference(SimpleIdentifier node, Element element, Element nameElement, Location location) {
    if (_isQualified(node)) {
      Relationship relationship = element != null ? IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED : IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED;
      recordRelationship(nameElement, relationship, location);
    }
  }

  /**
   * Records extends/implements relationships between given [ClassElement] and [Type] of
   * "superNode".
   */
  void _recordSuperType(TypeName superNode, Relationship relationship) {
    if (superNode != null) {
      Identifier superName = superNode.name;
      if (superName != null) {
        Element superElement = superName.staticElement;
        recordRelationship(superElement, relationship, _createLocationFromNode(superNode));
      }
    }
  }
}

class IndexContributor_AngularHtmlIndexContributor extends IndexContributor {
  final AngularHtmlIndexContributor AngularHtmlIndexContributor_this;

  IndexContributor_AngularHtmlIndexContributor(IndexStore arg0, this.AngularHtmlIndexContributor_this) : super(arg0);

  @override
  Element peekElement() => AngularHtmlIndexContributor_this._htmlUnitElement;

  @override
  void recordRelationship(Element element, Relationship relationship, Location location) {
    AngularElement angularElement = AngularHtmlUnitResolver.getAngularElement(element);
    if (angularElement != null) {
      element = angularElement;
      relationship = IndexConstants.ANGULAR_REFERENCE;
    }
    super.recordRelationship(element, relationship, location);
  }
}

/**
 * Information about [ImportElement] and place where it is referenced using
 * [PrefixElement].
 */
class IndexContributor_ImportElementInfo {
  ImportElement _element;

  int _periodEnd = 0;
}

/**
 * Instances of the [IndexHtmlUnitOperation] implement an operation that adds data to the
 * index based on the resolved [HtmlUnit].
 */
class IndexHtmlUnitOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  /**
   * The context in which [HtmlUnit] was resolved.
   */
  final AnalysisContext _context;

  /**
   * The [HtmlUnit] being indexed.
   */
  final ht.HtmlUnit unit;

  /**
   * The element of the [HtmlUnit] being indexed.
   */
  HtmlElement _htmlElement;

  /**
   * The source being indexed.
   */
  Source _source;

  /**
   * Initialize a newly created operation that will index the specified [HtmlUnit].
   *
   * @param indexStore the index store against which this operation is being run
   * @param context the context in which [HtmlUnit] was resolved
   * @param unit the fully resolved [HtmlUnit]
   */
  IndexHtmlUnitOperation(this._indexStore, this._context, this.unit) {
    this._htmlElement = unit.element;
    this._source = _htmlElement.source;
  }

  /**
   * @return the [Source] to be indexed.
   */
  Source get source => _source;

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    try {
      bool mayIndex = _indexStore.aboutToIndexHtml(_context, _htmlElement);
      if (!mayIndex) {
        return;
      }
      AngularHtmlIndexContributor contributor = new AngularHtmlIndexContributor(_indexStore);
      unit.accept(contributor);
    } catch (exception) {
      AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.location}", exception);
    }
  }

  @override
  bool removeWhenSourceRemoved(Source source) => this._source == source;

  @override
  String toString() => "IndexHtmlUnitOperation(${_source.fullName})";
}

/**
 * The interface [IndexOperation] defines the behavior of objects used to perform operations
 * on an index.
 */
abstract class IndexOperation {
  /**
   * Return `true` if this operation returns information from the index.
   *
   * @return `true` if this operation returns information from the index
   */
  bool get isQuery;

  /**
   * Perform the operation implemented by this operation.
   */
  void performOperation();

  /**
   * Return `true` if this operation should be removed from the operation queue when the
   * given resource has been removed.
   *
   * @param source the [Source] that has been removed
   * @return `true` if this operation should be removed from the operation queue as a
   *         result of removing the resource
   */
  bool removeWhenSourceRemoved(Source source);
}

/**
 * Container of information computed by the index - relationships between elements.
 */
abstract class IndexStore {
  /**
   * Notifies the index store that we are going to index the unit with the given element.
   *
   * If the unit is a part of a library, then all its locations are removed. If it is a defining
   * compilation unit of a library, then index store also checks if some previously indexed parts of
   * the library are not parts of the library anymore, and clears their information.
   *
   * @param the [AnalysisContext] in which unit being indexed
   * @param unitElement the element of the unit being indexed
   * @return `true` the given [AnalysisContext] is active, or `false` if it was
   *         removed before, so no any unit may be indexed with it
   */
  bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement);

  /**
   * Notifies the index store that we are going to index the given [HtmlElement].
   *
   * @param the [AnalysisContext] in which unit being indexed
   * @param htmlElement the [HtmlElement] being indexed
   * @return `true` the given [AnalysisContext] is active, or `false` if it was
   *         removed before, so no any unit may be indexed with it
   */
  bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement);

  /**
   * Removes all of the information.
   */
  void clear();

  /**
   * Return the locations of the elements that have the given relationship with the given element.
   * For example, if the element represents a method and the relationship is the is-referenced-by
   * relationship, then the returned locations will be all of the places where the method is
   * invoked.
   *
   * @param element the the element that has the relationship with the locations to be returned
   * @param relationship the [Relationship] between the given element and the locations to be
   *          returned
   * @return the locations that have the given relationship with the given element
   */
  List<Location> getRelationships(Element element, Relationship relationship);

  /**
   * Answer index statistics.
   */
  String get statistics;

  /**
   * Record that the given element and location have the given relationship. For example, if the
   * relationship is the is-referenced-by relationship, then the element would be the element being
   * referenced and the location would be the point at which it is referenced. Each element can have
   * the same relationship with multiple locations. In other words, if the following code were
   * executed
   *
   * <pre>
   *   recordRelationship(element, isReferencedBy, location1);
   *   recordRelationship(element, isReferencedBy, location2);
   * </pre>
   *
   * then both relationships would be maintained in the index and the result of executing
   *
   * <pre>
   *   getRelationship(element, isReferencedBy);
   * </pre>
   *
   * would be an array containing both <code>location1</code> and <code>location2</code>.
   *
   * @param element the element that is related to the location
   * @param relationship the [Relationship] between the element and the location
   * @param location the [Location] where relationship happens
   */
  void recordRelationship(Element element, Relationship relationship, Location location);

  /**
   * Remove from the index all of the information associated with [AnalysisContext].
   *
   * This method should be invoked when a context is disposed.
   *
   * @param the [AnalysisContext] being removed
   */
  void removeContext(AnalysisContext context);

  /**
   * Remove from the index all of the information associated with elements or locations in the given
   * source. This includes relationships between an element in the given source and any other
   * locations, relationships between any other elements and a location within the given source.
   *
   * This method should be invoked when a source is no longer part of the code base.
   *
   * @param the [AnalysisContext] in which [Source] being removed
   * @param source the source being removed
   */
  void removeSource(AnalysisContext context, Source source);

  /**
   * Remove from the index all of the information associated with elements or locations in the given
   * sources. This includes relationships between an element in the given sources and any other
   * locations, relationships between any other elements and a location within the given sources.
   *
   * This method should be invoked when multiple sources are no longer part of the code base.
   *
   * @param the [AnalysisContext] in which [Source]s being removed
   * @param container the [SourceContainer] holding the sources being removed
   */
  void removeSources(AnalysisContext context, SourceContainer container);
}

/**
 * Instances of the [IndexUnitOperation] implement an operation that adds data to the index
 * based on the resolved [CompilationUnit].
 */
class IndexUnitOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  /**
   * The context in which compilation unit was resolved.
   */
  final AnalysisContext _context;

  /**
   * The compilation unit being indexed.
   */
  final CompilationUnit unit;

  /**
   * The element of the compilation unit being indexed.
   */
  CompilationUnitElement _unitElement;

  /**
   * The source being indexed.
   */
  Source _source;

  /**
   * Initialize a newly created operation that will index the specified unit.
   *
   * @param indexStore the index store against which this operation is being run
   * @param context the context in which compilation unit was resolved
   * @param unit the fully resolved AST structure
   */
  IndexUnitOperation(this._indexStore, this._context, this.unit) {
    this._unitElement = unit.element;
    this._source = _unitElement.source;
  }

  /**
   * @return the [Source] to be indexed.
   */
  Source get source => _source;

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    try {
      bool mayIndex = _indexStore.aboutToIndexDart(_context, _unitElement);
      if (!mayIndex) {
        return;
      }
      unit.accept(new IndexContributor(_indexStore));
      unit.accept(new AngularDartIndexContributor(_indexStore));
    } catch (exception) {
      AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.location}", exception);
    }
  }

  @override
  bool removeWhenSourceRemoved(Source source) => this._source == source;

  @override
  String toString() => "IndexUnitOperation(${_source.fullName})";
}

/**
 * Instances of the class <code>Location</code> represent a location related to an element. The
 * location is expressed as an offset and length, but the offset is relative to the resource
 * containing the element rather than the start of the element within that resource.
 */
class Location {
  /**
   * An empty array of locations.
   */
  static List<Location> EMPTY_ARRAY = new List<Location>(0);

  /**
   * The element containing this location.
   */
  final Element element;

  /**
   * The offset of this location within the resource containing the element.
   */
  final int offset;

  /**
   * The length of this location.
   */
  final int length;

  /**
   * Internal field used to hold a key that is referenced at this location.
   */
  Object internalKey;

  /**
   * Initialize a newly create location to be relative to the given element at the given offset with
   * the given length.
   *
   * @param element the [Element] containing this location
   * @param offset the offset of this location within the resource containing the element
   * @param length the length of this location
   */
  Location(this.element, this.offset, this.length) {
    if (element == null) {
      throw new IllegalArgumentException("element location cannot be null");
    }
  }

  /**
   * Returns a clone of this [Location].
   */
  Location newClone() => new Location(element, offset, length);

  @override
  String toString() => "[${offset} - ${(offset + length)}) in ${element}";
}

/**
 * [Location] with attached data.
 */
class LocationWithData<D> extends Location {
  final D data;

  LocationWithData.con1(Location location, this.data) : super(location.element, location.offset, location.length);

  LocationWithData.con2(Element element, int offset, int length, this.data) : super(element, offset, length);

  @override
  Location newClone() => new LocationWithData<D>.con2(element, offset, length, data);
}

/**
 * [IndexStore] which keeps all information in memory, but can write it to stream and read
 * later.
 */
abstract class MemoryIndexStore implements IndexStore {
}

/**
 * [IndexStore] which keeps full index in memory.
 */
class MemoryIndexStoreImpl implements MemoryIndexStore {
  /**
   * When logging is on, [AnalysisEngine] actually creates
   * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used to create
   * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisContextImpl]
   * when perform any operation.
   */
  static AnalysisContext unwrapContext(AnalysisContext context) {
    if (context is InstrumentedAnalysisContextImpl) {
      context = (context as InstrumentedAnalysisContextImpl).basis;
    }
    return context;
  }

  /**
   * @return the [Source] of the enclosing [LibraryElement], may be `null`.
   */
  static Source _getLibrarySourceOrNull(Element element) {
    LibraryElement library = element.library;
    if (library == null) {
      return null;
    }
    if (library.isAngularHtml) {
      return null;
    }
    return library.source;
  }

  /**
   * This map is used to canonicalize equal keys.
   */
  Map<MemoryIndexStoreImpl_ElementRelationKey, MemoryIndexStoreImpl_ElementRelationKey> _canonicalKeys = {};

  /**
   * The mapping of [ElementRelationKey] to the [Location]s, one-to-many.
   */
  Map<MemoryIndexStoreImpl_ElementRelationKey, Set<Location>> _keyToLocations = {};

  /**
   * The mapping of [Source] to the [ElementRelationKey]s. It is used in
   * [removeSource] to identify keys to remove from
   * [keyToLocations].
   */
  Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>>> _contextToSourceToKeys = {};

  /**
   * The mapping of [Source] to the [Location]s existing in it. It is used in
   * [clearSource0] to identify locations to remove from
   * [keyToLocations].
   */
  Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, List<Location>>> _contextToSourceToLocations = {};

  /**
   * The mapping of library [Source] to the [Source]s of part units.
   */
  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits = {};

  /**
   * The mapping of unit [Source] to the [Source]s of libraries it is used in.
   */
  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries = {};

  int _sourceCount = 0;

  int _keyCount = 0;

  int _locationCount = 0;

  @override
  bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement) {
    context = unwrapContext(context);
    // may be already disposed in other thread
    if (context.isDisposed) {
      return false;
    }
    // validate unit
    if (unitElement == null) {
      return false;
    }
    LibraryElement libraryElement = unitElement.library;
    if (libraryElement == null) {
      return false;
    }
    CompilationUnitElement definingUnitElement = libraryElement.definingCompilationUnit;
    if (definingUnitElement == null) {
      return false;
    }
    // prepare sources
    Source library = definingUnitElement.source;
    Source unit = unitElement.source;
    // special handling for the defining library unit
    if (unit == library) {
      // prepare new parts
      Set<Source> newParts = new Set();
      for (CompilationUnitElement part in libraryElement.parts) {
        newParts.add(part.source);
      }
      // prepare old parts
      Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
      if (libraryToUnits == null) {
        libraryToUnits = {};
        _contextToLibraryToUnits[context] = libraryToUnits;
      }
      Set<Source> oldParts = libraryToUnits[library];
      // check if some parts are not in the library now
      if (oldParts != null) {
        Set<Source> noParts = oldParts.difference(newParts);
        for (Source noPart in noParts) {
          _removeLocations(context, library, noPart);
        }
      }
      // remember new parts
      libraryToUnits[library] = newParts;
    }
    // remember libraries in which unit is used
    _recordUnitInLibrary(context, library, unit);
    // remove locations
    _removeLocations(context, library, unit);
    // remove keys
    {
      Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context];
      if (sourceToKeys != null) {
        MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit);
        bool hadSource = sourceToKeys.remove(source2) != null;
        if (hadSource) {
          _sourceCount--;
        }
      }
    }
    // OK, we can index
    return true;
  }

  @override
  bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) {
    context = unwrapContext(context);
    // may be already disposed in other thread
    if (context.isDisposed) {
      return false;
    }
    // remove locations
    Source source = htmlElement.source;
    _removeLocations(context, null, source);
    // remove keys
    {
      Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context];
      if (sourceToKeys != null) {
        MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(null, source);
        bool hadSource = sourceToKeys.remove(source2) != null;
        if (hadSource) {
          _sourceCount--;
        }
      }
    }
    // remember libraries in which unit is used
    _recordUnitInLibrary(context, null, source);
    // OK, we can index
    return true;
  }

  @override
  void clear() {
    _canonicalKeys.clear();
    _keyToLocations.clear();
    _contextToSourceToKeys.clear();
    _contextToSourceToLocations.clear();
    _contextToLibraryToUnits.clear();
    _contextToUnitToLibraries.clear();
  }

  @override
  List<Location> getRelationships(Element element, Relationship relationship) {
    MemoryIndexStoreImpl_ElementRelationKey key = new MemoryIndexStoreImpl_ElementRelationKey(element, relationship);
    Set<Location> locations = _keyToLocations[key];
    if (locations != null) {
      return new List.from(locations);
    }
    return Location.EMPTY_ARRAY;
  }

  @override
  String get statistics => "${_locationCount} relationships in ${_keyCount} keys in ${_sourceCount} sources";

  int internalGetKeyCount() => _keyToLocations.length;

  int internalGetLocationCount() {
    int count = 0;
    for (Set<Location> locations in _keyToLocations.values) {
      count += locations.length;
    }
    return count;
  }

  int internalGetLocationCountForContext(AnalysisContext context) {
    context = unwrapContext(context);
    int count = 0;
    for (Set<Location> locations in _keyToLocations.values) {
      for (Location location in locations) {
        if (identical(location.element.context, context)) {
          count++;
        }
      }
    }
    return count;
  }

  int internalGetSourceKeyCount(AnalysisContext context) {
    int count = 0;
    Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context];
    if (sourceToKeys != null) {
      for (Set<MemoryIndexStoreImpl_ElementRelationKey> keys in sourceToKeys.values) {
        count += keys.length;
      }
    }
    return count;
  }

  @override
  void recordRelationship(Element element, Relationship relationship, Location location) {
    if (element == null || location == null) {
      return;
    }
    location = location.newClone();
    // at the index level we don't care about Member(s)
    if (element is Member) {
      element = (element as Member).baseElement;
    }
    //    System.out.println(element + " " + relationship + " " + location);
    // prepare information
    AnalysisContext elementContext = element.context;
    AnalysisContext locationContext = location.element.context;
    Source elementSource = element.source;
    Source locationSource = location.element.source;
    Source elementLibrarySource = _getLibrarySourceOrNull(element);
    Source locationLibrarySource = _getLibrarySourceOrNull(location.element);
    // sanity check
    if (locationContext == null) {
      return;
    }
    if (locationSource == null) {
      return;
    }
    if (elementContext == null && element is! NameElementImpl && element is! UniverseElementImpl) {
      return;
    }
    if (elementSource == null && element is! NameElementImpl && element is! UniverseElementImpl) {
      return;
    }
    // may be already disposed in other thread
    if (elementContext != null && elementContext.isDisposed) {
      return;
    }
    if (locationContext.isDisposed) {
      return;
    }
    // record: key -> location(s)
    MemoryIndexStoreImpl_ElementRelationKey key = _getCanonicalKey(element, relationship);
    {
      Set<Location> locations = _keyToLocations.remove(key);
      if (locations == null) {
        locations = _createLocationIdentitySet();
      } else {
        _keyCount--;
      }
      _keyToLocations[key] = locations;
      _keyCount++;
      locations.add(location);
      _locationCount++;
    }
    // record: location -> key
    location.internalKey = key;
    // prepare source pairs
    MemoryIndexStoreImpl_Source2 elementSource2 = new MemoryIndexStoreImpl_Source2(elementLibrarySource, elementSource);
    MemoryIndexStoreImpl_Source2 locationSource2 = new MemoryIndexStoreImpl_Source2(locationLibrarySource, locationSource);
    // record: element source -> keys
    {
      Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[elementContext];
      if (sourceToKeys == null) {
        sourceToKeys = {};
        _contextToSourceToKeys[elementContext] = sourceToKeys;
      }
      Set<MemoryIndexStoreImpl_ElementRelationKey> keys = sourceToKeys[elementSource2];
      if (keys == null) {
        keys = new Set();
        sourceToKeys[elementSource2] = keys;
        _sourceCount++;
      }
      keys.remove(key);
      keys.add(key);
    }
    // record: location source -> locations
    {
      Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[locationContext];
      if (sourceToLocations == null) {
        sourceToLocations = {};
        _contextToSourceToLocations[locationContext] = sourceToLocations;
      }
      List<Location> locations = sourceToLocations[locationSource2];
      if (locations == null) {
        locations = [];
        sourceToLocations[locationSource2] = locations;
      }
      locations.add(location);
    }
  }

  @override
  void removeContext(AnalysisContext context) {
    context = unwrapContext(context);
    if (context == null) {
      return;
    }
    // remove sources
    removeSources(context, null);
    // remove context
    _contextToSourceToKeys.remove(context);
    _contextToSourceToLocations.remove(context);
    _contextToLibraryToUnits.remove(context);
    _contextToUnitToLibraries.remove(context);
  }

  @override
  void removeSource(AnalysisContext context, Source unit) {
    context = unwrapContext(context);
    if (context == null) {
      return;
    }
    // remove locations defined in source
    Map<Source, Set<Source>> unitToLibraries = _contextToUnitToLibraries[context];
    if (unitToLibraries != null) {
      Set<Source> libraries = unitToLibraries.remove(unit);
      if (libraries != null) {
        for (Source library in libraries) {
          MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit);
          // remove locations defined in source
          _removeLocations(context, library, unit);
          // remove keys for elements defined in source
          Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context];
          if (sourceToKeys != null) {
            Set<MemoryIndexStoreImpl_ElementRelationKey> keys = sourceToKeys.remove(source2);
            if (keys != null) {
              for (MemoryIndexStoreImpl_ElementRelationKey key in keys) {
                _canonicalKeys.remove(key);
                Set<Location> locations = _keyToLocations.remove(key);
                if (locations != null) {
                  _keyCount--;
                  _locationCount -= locations.length;
                }
              }
              _sourceCount--;
            }
          }
        }
      }
    }
  }

  @override
  void removeSources(AnalysisContext context, SourceContainer container) {
    context = unwrapContext(context);
    if (context == null) {
      return;
    }
    // remove sources #1
    Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context];
    if (sourceToKeys != null) {
      List<MemoryIndexStoreImpl_Source2> sources = [];
      for (MemoryIndexStoreImpl_Source2 source2 in sources) {
        Source source = source2._unitSource;
        if (container == null || container.contains(source)) {
          removeSource(context, source);
        }
      }
    }
    // remove sources #2
    Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[context];
    if (sourceToLocations != null) {
      List<MemoryIndexStoreImpl_Source2> sources = [];
      for (MemoryIndexStoreImpl_Source2 source2 in sources) {
        Source source = source2._unitSource;
        if (container == null || container.contains(source)) {
          removeSource(context, source);
        }
      }
    }
  }

  /**
   * Creates new [Set] that uses object identity instead of equals.
   */
  Set<Location> _createLocationIdentitySet() => new Set<Location>.identity();

  /**
   * @return the canonical [ElementRelationKey] for given [Element] and
   *         [Relationship], i.e. unique instance for this combination.
   */
  MemoryIndexStoreImpl_ElementRelationKey _getCanonicalKey(Element element, Relationship relationship) {
    MemoryIndexStoreImpl_ElementRelationKey key = new MemoryIndexStoreImpl_ElementRelationKey(element, relationship);
    MemoryIndexStoreImpl_ElementRelationKey canonicalKey = _canonicalKeys[key];
    if (canonicalKey == null) {
      canonicalKey = key;
      _canonicalKeys[key] = canonicalKey;
    }
    return canonicalKey;
  }

  void _recordUnitInLibrary(AnalysisContext context, Source library, Source unit) {
    Map<Source, Set<Source>> unitToLibraries = _contextToUnitToLibraries[context];
    if (unitToLibraries == null) {
      unitToLibraries = {};
      _contextToUnitToLibraries[context] = unitToLibraries;
    }
    Set<Source> libraries = unitToLibraries[unit];
    if (libraries == null) {
      libraries = new Set();
      unitToLibraries[unit] = libraries;
    }
    libraries.add(library);
  }

  /**
   * Removes locations recorded in the given library/unit pair.
   */
  void _removeLocations(AnalysisContext context, Source library, Source unit) {
    MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit);
    Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[context];
    if (sourceToLocations != null) {
      List<Location> sourceLocations = sourceToLocations.remove(source2);
      if (sourceLocations != null) {
        for (Location location in sourceLocations) {
          MemoryIndexStoreImpl_ElementRelationKey key = location.internalKey as MemoryIndexStoreImpl_ElementRelationKey;
          Set<Location> relLocations = _keyToLocations[key];
          if (relLocations != null) {
            relLocations.remove(location);
            _locationCount--;
            // no locations with this key
            if (relLocations.isEmpty) {
              _canonicalKeys.remove(key);
              _keyToLocations.remove(key);
              _keyCount--;
            }
          }
        }
      }
    }
  }
}

class MemoryIndexStoreImpl_ElementRelationKey {
  final Element _element;

  final Relationship _relationship;

  MemoryIndexStoreImpl_ElementRelationKey(this._element, this._relationship);

  @override
  bool operator ==(Object obj) {
    MemoryIndexStoreImpl_ElementRelationKey other = obj as MemoryIndexStoreImpl_ElementRelationKey;
    Element otherElement = other._element;
    return identical(other._relationship, _relationship) && otherElement.nameOffset == _element.nameOffset && otherElement.kind == _element.kind && otherElement.displayName == _element.displayName && otherElement.source == _element.source;
  }

  @override
  int get hashCode => JavaArrays.makeHashCode([
      _element.source,
      _element.nameOffset,
      _element.kind,
      _element.displayName,
      _relationship]);

  @override
  String toString() => "${_element} ${_relationship}";
}

class MemoryIndexStoreImpl_Source2 {
  final Source _librarySource;

  final Source _unitSource;

  MemoryIndexStoreImpl_Source2(this._librarySource, this._unitSource);

  @override
  bool operator ==(Object obj) {
    if (identical(obj, this)) {
      return true;
    }
    if (obj is! MemoryIndexStoreImpl_Source2) {
      return false;
    }
    MemoryIndexStoreImpl_Source2 other = obj as MemoryIndexStoreImpl_Source2;
    return other._librarySource == _librarySource && other._unitSource == _unitSource;
  }

  @override
  int get hashCode => JavaArrays.makeHashCode([_librarySource, _unitSource]);

  @override
  String toString() => "${_librarySource} ${_unitSource}";
}

/**
 * Special [Element] which is used to index references to the name without specifying concrete
 * kind of this name - field, method or something else.
 */
class NameElementImpl extends ElementImpl {
  NameElementImpl(String name) : super("name:${name}", -1);

  @override
  accept(ElementVisitor visitor) => null;

  @override
  ElementKind get kind => ElementKind.NAME;
}

/**
 * The enumeration <code>ProcessorState</code> represents the possible states of an operation
 * processor.
 */
class ProcessorState extends Enum<ProcessorState> {
  /**
   * The processor is ready to be run (has not been run before).
   */
  static const ProcessorState READY = const ProcessorState('READY', 0);

  /**
   * The processor is currently performing operations.
   */
  static const ProcessorState RUNNING = const ProcessorState('RUNNING', 1);

  /**
   * The processor is currently performing operations but has been asked to stop.
   */
  static const ProcessorState STOP_REQESTED = const ProcessorState('STOP_REQESTED', 2);

  /**
   * The processor has stopped performing operations and cannot be used again.
   */
  static const ProcessorState STOPPED = const ProcessorState('STOPPED', 3);

  static const List<ProcessorState> values = const [READY, RUNNING, STOP_REQESTED, STOPPED];

  const ProcessorState(String name, int ordinal) : super(name, ordinal);
}

/**
 * Relationship between an element and a location. Relationships are identified by a globally unique
 * identifier.
 */
class Relationship {
  /**
   * The unique identifier for this relationship.
   */
  final String _uniqueId;

  /**
   * A table mapping relationship identifiers to relationships.
   */
  static Map<String, Relationship> _RelationshipMap = {};

  /**
   * Return the relationship with the given unique identifier.
   *
   * @param uniqueId the unique identifier for the relationship
   * @return the relationship with the given unique identifier
   */
  static Relationship getRelationship(String uniqueId) {
    Relationship relationship = _RelationshipMap[uniqueId];
    if (relationship == null) {
      relationship = new Relationship(uniqueId);
      _RelationshipMap[uniqueId] = relationship;
    }
    return relationship;
  }

  /**
   * @return all registered [Relationship]s.
   */
  static Iterable<Relationship> values() => _RelationshipMap.values;

  /**
   * Initialize a newly created relationship to have the given unique identifier.
   *
   * @param uniqueId the unique identifier for this relationship
   */
  Relationship(this._uniqueId);

  /**
   * Return the unique identifier for this relationship.
   *
   * @return the unique identifier for this relationship
   */
  String get identifier => _uniqueId;

  @override
  String toString() => _uniqueId;
}

/**
 * The interface <code>RelationshipCallback</code> defines the behavior of objects that are invoked
 * with the results of a query about a given relationship.
 */
abstract class RelationshipCallback {
  /**
   * This method is invoked when the locations that have a specified relationship with a specified
   * element are available. For example, if the element is a field and the relationship is the
   * is-referenced-by relationship, then this method will be invoked with each location at which the
   * field is referenced.
   *
   * @param element the [Element] that has the relationship with the locations
   * @param relationship the relationship between the given element and the locations
   * @param locations the locations that were found
   */
  void hasRelationships(Element element, Relationship relationship, List<Location> locations);
}

/**
 * Instances of the [RemoveContextOperation] implement an operation that removes from the
 * index any data based on the specified [AnalysisContext].
 */
class RemoveContextOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  /**
   * The context being removed.
   */
  final AnalysisContext context;

  /**
   * Initialize a newly created operation that will remove the specified resource.
   *
   * @param indexStore the index store against which this operation is being run
   * @param context the [AnalysisContext] to remove
   */
  RemoveContextOperation(this._indexStore, this.context);

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    _indexStore.removeContext(context);
  }

  @override
  bool removeWhenSourceRemoved(Source source) => false;

  @override
  String toString() => "RemoveContext(${context})";
}

/**
 * Instances of the [RemoveSourceOperation] implement an operation that removes from the index
 * any data based on the content of a specified source.
 */
class RemoveSourceOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  /**
   * The context in which source being removed.
   */
  final AnalysisContext _context;

  /**
   * The source being removed.
   */
  final Source source;

  /**
   * Initialize a newly created operation that will remove the specified resource.
   *
   * @param indexStore the index store against which this operation is being run
   * @param context the [AnalysisContext] to remove source in
   * @param source the [Source] to remove from index
   */
  RemoveSourceOperation(this._indexStore, this._context, this.source);

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    _indexStore.removeSource(_context, source);
  }

  @override
  bool removeWhenSourceRemoved(Source source) => false;

  @override
  String toString() => "RemoveSource(${source.fullName})";
}

/**
 * Instances of the [RemoveSourcesOperation] implement an operation that removes from the
 * index any data based on the content of source belonging to a [SourceContainer].
 */
class RemoveSourcesOperation implements IndexOperation {
  /**
   * The index store against which this operation is being run.
   */
  final IndexStore _indexStore;

  /**
   * The context to remove container.
   */
  final AnalysisContext _context;

  /**
   * The source container to remove.
   */
  final SourceContainer container;

  /**
   * Initialize a newly created operation that will remove the specified resource.
   *
   * @param indexStore the index store against which this operation is being run
   * @param context the [AnalysisContext] to remove container in
   * @param container the [SourceContainer] to remove from index
   */
  RemoveSourcesOperation(this._indexStore, this._context, this.container);

  @override
  bool get isQuery => false;

  @override
  void performOperation() {
    _indexStore.removeSources(_context, container);
  }

  @override
  bool removeWhenSourceRemoved(Source source) => false;

  @override
  String toString() => "RemoveSources(${container})";
}

/**
 * The interface `UniverseElement` defines element to use when we want to request "defines"
 * relations without specifying exact library.
 */
abstract class UniverseElement implements Element {
  static final UniverseElement INSTANCE = UniverseElementImpl.INSTANCE;
}

/**
 * Implementation of [UniverseElement].
 */
class UniverseElementImpl extends ElementImpl implements UniverseElement {
  static UniverseElementImpl INSTANCE = new UniverseElementImpl();

  UniverseElementImpl() : super("--universe--", -1);

  @override
  accept(ElementVisitor visitor) => null;

  @override
  ElementKind get kind => ElementKind.UNIVERSE;
}