| Index: pkg/analyzer/lib/index/index.dart
|
| diff --git a/pkg/analyzer/lib/index/index.dart b/pkg/analyzer/lib/index/index.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d8bb20dd8a3960cef02052d3195b1f492b79c3e9
|
| --- /dev/null
|
| +++ b/pkg/analyzer/lib/index/index.dart
|
| @@ -0,0 +1,482 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library engine.index;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| +import 'package:analyzer/src/generated/element.dart';
|
| +import 'package:analyzer/src/generated/engine.dart';
|
| +import 'package:analyzer/src/generated/html.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +
|
| +
|
| +/**
|
| + * The interface [Index] defines the behavior of objects that maintain an index
|
| + * storing relations between [Element]s.
|
| + *
|
| + * Any modification operations are executed before any read operation.
|
| + * There is no guarantee about the order in which the [Future]s for read
|
| + * operations will complete.
|
| + */
|
| +abstract class Index {
|
| + /**
|
| + * Answers index statistics.
|
| + */
|
| + String get statistics;
|
| +
|
| + /**
|
| + * Removes from the index all the information.
|
| + */
|
| + void clear();
|
| +
|
| + /**
|
| + * Asynchronously returns a list containing all of the locations of the
|
| + * elements that have the given [relationship] with the given [element].
|
| + *
|
| + * For example, if the element represents a function and the relationship is
|
| + * the `is-invoked-by` relationship, then the locations will be all of the
|
| + * places where the function is invoked.
|
| + *
|
| + * [element] - the element that has the relationship with the locations to be
|
| + * returned.
|
| + *
|
| + * [relationship] - the relationship between the given element and the
|
| + * locations to be returned.
|
| + */
|
| + Future<List<Location>> getRelationships(Element element,
|
| + Relationship relationship);
|
| +
|
| + /**
|
| + * Processes the given [HtmlUnit] in order to record the relationships.
|
| + *
|
| + * [context] - the [AnalysisContext] in which [HtmlUnit] was resolved.
|
| + * [unit] - the [HtmlUnit] being indexed.
|
| + */
|
| + void indexHtmlUnit(AnalysisContext context, HtmlUnit unit);
|
| +
|
| + /**
|
| + * Processes the given [CompilationUnit] in order to record the relationships.
|
| + *
|
| + * [context] - the [AnalysisContext] in which [CompilationUnit] was resolved.
|
| + * [unit] - the [CompilationUnit] being indexed.
|
| + */
|
| + void indexUnit(AnalysisContext context, CompilationUnit unit);
|
| +
|
| + /**
|
| + * Removes from the index all of the information associated with [context].
|
| + *
|
| + * This method should be invoked when [context] is disposed.
|
| + */
|
| + void removeContext(AnalysisContext context);
|
| +
|
| + /**
|
| + * Removes from the index all of the information associated with elements or
|
| + * locations in [source]. This includes relationships between an element in
|
| + * [source] and any other locations, relationships between any other elements
|
| + * and a location within [source].
|
| + *
|
| + * This method should be invoked when [source] is no longer part of the code
|
| + * base.
|
| + *
|
| + * [context] - the [AnalysisContext] in which [source] being removed
|
| + * [source] - the [Source] being removed
|
| + */
|
| + void removeSource(AnalysisContext context, Source source);
|
| +
|
| + /**
|
| + * Removes 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.
|
| + *
|
| + * [context] - the [AnalysisContext] in which [Source]s being removed.
|
| + * [container] - the [SourceContainer] holding the sources being removed.
|
| + */
|
| + void removeSources(AnalysisContext context, SourceContainer container);
|
| +
|
| + /**
|
| + * Starts the index.
|
| + * Should be called before any other method.
|
| + */
|
| + void run();
|
| +
|
| + /**
|
| + * Stops the index.
|
| + * After calling this method operations may not be executed.
|
| + */
|
| + void stop();
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Constants used when populating and accessing the index.
|
| + */
|
| +class IndexConstants {
|
| + /**
|
| + * Reference to some closing tag of an XML element.
|
| + */
|
| + static final Relationship ANGULAR_CLOSING_TAG_REFERENCE =
|
| + Relationship.getRelationship("angular-closing-tag-reference");
|
| +
|
| + /**
|
| + * Reference to some [AngularElement].
|
| + */
|
| + static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship(
|
| + "angular-reference");
|
| +
|
| + /**
|
| + * 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 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 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 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 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 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 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 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 a [NameElement] (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 [NameElement] (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_UNQUALIFIED =
|
| + Relationship.getRelationship("is-referenced-by-unqualified");
|
| +
|
| + /**
|
| + * 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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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 a [NameElement] (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");
|
| +
|
| + /**
|
| + * An element used to represent the universe.
|
| + */
|
| + static final Element UNIVERSE = UniverseElement.INSTANCE;
|
| +
|
| + IndexConstants._();
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Instances of the class [Location] 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 const List<Location> EMPTY_ARRAY = const <Location>[];
|
| +
|
| + /**
|
| + * 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;
|
| +
|
| + /**
|
| + * Initializes a newly create location to be relative to the given element at
|
| + * the given [offset] with the given [length].
|
| + *
|
| + * [element] - the [Element] containing this location.
|
| + * [offset] - the offset within the resource containing the [element].
|
| + * [length] - the length of this location
|
| + */
|
| + Location(this.element, this.offset, this.length) {
|
| + if (element == null) {
|
| + throw new ArgumentError("element location cannot be null");
|
| + }
|
| + }
|
| +
|
| + @override
|
| + String toString() => "[${offset} - ${(offset + length)}) in ${element}";
|
| +}
|
| +
|
| +
|
| +/**
|
| + * A [Location] with attached data.
|
| + */
|
| +class LocationWithData<D> extends Location {
|
| + final D data;
|
| +
|
| + LocationWithData(Location location, this.data) : super(location.element,
|
| + location.offset, location.length);
|
| +}
|
| +
|
| +
|
| +/**
|
| + * An [Element] which is used to index references to the name without specifying
|
| + * a concrete kind of this name - field, method or something else.
|
| + */
|
| +class NameElement extends ElementImpl {
|
| + NameElement(String name) : super("name:${name}", -1);
|
| +
|
| + @override
|
| + ElementKind get kind => ElementKind.NAME;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => null;
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Relationship between an element and a location. Relationships are identified
|
| + * by a globally unique identifier.
|
| + */
|
| +class Relationship {
|
| + /**
|
| + * A table mapping relationship identifiers to relationships.
|
| + */
|
| + static Map<String, Relationship> _RELATIONSHIP_MAP = {};
|
| +
|
| + /**
|
| + * The unique identifier for this relationship.
|
| + */
|
| + final String identifier;
|
| +
|
| + /**
|
| + * Initialize a newly created relationship with the given unique identifier.
|
| + */
|
| + Relationship(this.identifier);
|
| +
|
| + @override
|
| + String toString() => identifier;
|
| +
|
| + /**
|
| + * Returns the relationship with the given unique [identifier].
|
| + */
|
| + static Relationship getRelationship(String identifier) {
|
| + Relationship relationship = _RELATIONSHIP_MAP[identifier];
|
| + if (relationship == null) {
|
| + relationship = new Relationship(identifier);
|
| + _RELATIONSHIP_MAP[identifier] = relationship;
|
| + }
|
| + return relationship;
|
| + }
|
| +}
|
| +
|
| +
|
| +/**
|
| + * An element to use when we want to request "defines" relations without
|
| + * specifying an exact library.
|
| + */
|
| +class UniverseElement extends ElementImpl {
|
| + static final UniverseElement INSTANCE = new UniverseElement._();
|
| +
|
| + UniverseElement._() : super("--universe--", -1);
|
| +
|
| + @override
|
| + ElementKind get kind => ElementKind.UNIVERSE;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => null;
|
| +}
|
|
|