Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: pkg/analyzer/lib/src/generated/index.dart

Issue 257773008: New analyzer snapshot, based on r35422. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update pubspec.yaml Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/index.dart
diff --git a/pkg/analyzer/lib/src/generated/index.dart b/pkg/analyzer/lib/src/generated/index.dart
index c4008b79b3cd842a8cd7044633d908e666a9473f..c19cbae6d6bfc85a0888e8b6bde2048272f72225 100644
--- a/pkg/analyzer/lib/src/generated/index.dart
+++ b/pkg/analyzer/lib/src/generated/index.dart
@@ -19,166 +19,650 @@ import 'engine.dart';
import 'html.dart' as ht;
/**
- * Instances of the [RemoveSourceOperation] implement an operation that removes from the index
- * any data based on the content of a specified source.
+ * Implementation of [UniverseElement].
*/
-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;
+class UniverseElementImpl extends ElementImpl implements UniverseElement {
+ static UniverseElementImpl INSTANCE = new UniverseElementImpl();
- @override
- void performOperation() {
- _indexStore.removeSource(_context, source);
- }
+ UniverseElementImpl() : super("--universe--", -1);
@override
- bool removeWhenSourceRemoved(Source source) => false;
+ accept(ElementVisitor visitor) => null;
@override
- String toString() => "RemoveSource(${source.fullName})";
+ ElementKind get kind => ElementKind.UNIVERSE;
}
/**
- * The interface [IndexOperation] defines the behavior of objects used to perform operations
- * on an index.
+ * Container of information computed by the index - relationships between elements.
*/
-abstract class IndexOperation {
+abstract class IndexStore {
/**
- * Return `true` if this operation returns information from the index.
+ * Notifies the index store that we are going to index the unit with the given element.
*
- * @return `true` if this operation returns information from the index
+ * 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 get isQuery;
+ bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement);
/**
- * Perform the operation implemented by this operation.
+ * 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
*/
- void performOperation();
+ bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement);
/**
- * Return `true` if this operation should be removed from the operation queue when the
- * given resource has been removed.
+ * 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 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
+ * @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
*/
- bool removeWhenSourceRemoved(Source source);
-}
+ List<Location> getRelationships(Element element, Relationship relationship);
-/**
- * [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.
+ * Answer index statistics.
*/
- static AnalysisContext unwrapContext(AnalysisContext context) {
- if (context is InstrumentedAnalysisContextImpl) {
- context = (context as InstrumentedAnalysisContextImpl).basis;
- }
- return context;
- }
+ String get statistics;
/**
- * @return the [Source] of the enclosing [LibraryElement], may be `null`.
+ * 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
*/
- static Source _getLibrarySourceOrNull(Element element) {
- LibraryElement library = element.library;
- if (library == null) {
- return null;
- }
- if (library.isAngularHtml) {
- return null;
- }
- return library.source;
- }
+ void recordRelationship(Element element, Relationship relationship, Location location);
/**
- * This map is used to canonicalize equal keys.
+ * 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
*/
- Map<MemoryIndexStoreImpl_ElementRelationKey, MemoryIndexStoreImpl_ElementRelationKey> _canonicalKeys = {};
+ void removeContext(AnalysisContext context);
/**
- * The mapping of [ElementRelationKey] to the [Location]s, one-to-many.
+ * 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
*/
- Map<MemoryIndexStoreImpl_ElementRelationKey, Set<Location>> _keyToLocations = {};
+ void removeSource(AnalysisContext context, Source source);
/**
- * The mapping of [Source] to the [ElementRelationKey]s. It is used in
- * [removeSource] to identify keys to remove from
- * [keyToLocations].
+ * 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
*/
- Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>>> _contextToSourceToKeys = {};
+ void removeSources(AnalysisContext context, SourceContainer container);
+}
+/**
+ * Visits resolved [HtmlUnit] and adds relationships into [IndexStore].
+ */
+class AngularHtmlIndexContributor extends ExpressionVisitor {
/**
- * The mapping of [Source] to the [Location]s existing in it. It is used in
- * [clearSource0] to identify locations to remove from
- * [keyToLocations].
+ * The [IndexStore] to record relations into.
*/
- Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, List<Location>>> _contextToSourceToLocations = {};
+ final IndexStore _store;
/**
- * The mapping of library [Source] to the [Source]s of part units.
+ * The index contributor used to index Dart [Expression]s.
*/
- Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits = {};
+ IndexContributor _indexContributor;
+
+ HtmlElement _htmlUnitElement;
/**
- * The mapping of unit [Source] to the [Source]s of libraries it is used in.
+ * Initialize a newly created Angular HTML index contributor.
+ *
+ * @param store the [IndexStore] to record relations into.
*/
- Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries = {};
-
- int _sourceCount = 0;
+ AngularHtmlIndexContributor(this._store) {
+ _indexContributor = new IndexContributor_AngularHtmlIndexContributor(_store, this);
+ }
- int _keyCount = 0;
+ @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);
+ }
- int _locationCount = 0;
+ @override
+ Object visitHtmlUnit(ht.HtmlUnit node) {
+ _htmlUnitElement = node.element;
+ CompilationUnitElement dartUnitElement = _htmlUnitElement.angularCompilationUnit;
+ _indexContributor.enterScope(dartUnitElement);
+ return super.visitHtmlUnit(node);
+ }
@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;
+ 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);
}
- LibraryElement libraryElement = unitElement.library;
- if (libraryElement == null) {
- return false;
+ 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);
+ }
}
- CompilationUnitElement definingUnitElement = libraryElement.definingCompilationUnit;
- if (definingUnitElement == null) {
- return false;
+ 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);
+}
+
+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);
+ }
+}
+
+/**
+ * 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 [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})";
+}
+
+/**
+ * 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);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * 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 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 [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})";
+}
+
+/**
+ * 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})";
+}
+
+/**
+ * [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;
@@ -504,294 +988,83 @@ class MemoryIndexStoreImpl implements MemoryIndexStore {
}
/**
- * 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}";
-}
-
-/**
- * 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})";
-}
-
-/**
- * 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);
- }
- }
- }
-}
-
-/**
- * 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.
+ * Removes locations recorded in the given library/unit pair.
*/
- static Iterable<Relationship> values() => _RelationshipMap.values;
+ 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--;
+ }
+ }
+ }
+ }
+ }
+ }
+}
- /**
- * Initialize a newly created relationship to have the given unique identifier.
- *
- * @param uniqueId the unique identifier for this relationship
- */
- Relationship(this._uniqueId);
+class MemoryIndexStoreImpl_ElementRelationKey {
+ final Element _element;
- /**
- * Return the unique identifier for this relationship.
- *
- * @return the unique identifier for this relationship
- */
- String get identifier => _uniqueId;
+ final Relationship _relationship;
+
+ MemoryIndexStoreImpl_ElementRelationKey(this._element, this._relationship);
@override
- String toString() => _uniqueId;
-}
+ 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;
+ }
-/**
- * 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;
+ @override
+ int get hashCode => JavaArrays.makeHashCode([
+ _element.source,
+ _element.nameOffset,
+ _element.kind,
+ _element.displayName,
+ _relationship]);
- /**
- * The context to remove container.
- */
- final AnalysisContext _context;
+ @override
+ String toString() => "${_element} ${_relationship}";
+}
- /**
- * The source container to remove.
- */
- final SourceContainer container;
+class MemoryIndexStoreImpl_Source2 {
+ final Source _librarySource;
- /**
- * 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);
+ final Source _unitSource;
- @override
- bool get isQuery => false;
+ MemoryIndexStoreImpl_Source2(this._librarySource, this._unitSource);
@override
- void performOperation() {
- _indexStore.removeSources(_context, container);
+ 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
- bool removeWhenSourceRemoved(Source source) => false;
+ int get hashCode => JavaArrays.makeHashCode([_librarySource, _unitSource]);
@override
- String toString() => "RemoveSources(${container})";
+ String toString() => "${_librarySource} ${_unitSource}";
}
/**
@@ -815,483 +1088,166 @@ class ProcessorState extends Enum<ProcessorState> {
/**
* 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);
-}
-
-/**
- * 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");
+ static const ProcessorState RUNNING = const ProcessorState('RUNNING', 1);
/**
- * Reference to some [AngularElement].
+ * The processor is currently performing operations but has been asked to stop.
*/
- static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("angular-reference");
+ static const ProcessorState STOP_REQESTED = const ProcessorState('STOP_REQESTED', 2);
/**
- * Reference to some closing tag of an XML element.
+ * The processor has stopped performing operations and cannot be used again.
*/
- static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRelationship("angular-closing-tag-reference");
+ 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);
}
/**
- * Visits resolved [HtmlUnit] and adds relationships into [IndexStore].
+ * Constants used when populating and accessing the index.
*/
-class AngularHtmlIndexContributor extends ExpressionVisitor {
+abstract class IndexConstants {
/**
- * The [IndexStore] to record relations into.
+ * An element used to represent the universe.
*/
- final IndexStore _store;
+ static final Element UNIVERSE = UniverseElement.INSTANCE;
/**
- * The index contributor used to index Dart [Expression]s.
+ * The relationship used to indicate that a container (the left-operand) contains the definition
+ * of a class at a specific location (the right operand).
*/
- IndexContributor _indexContributor;
-
- HtmlElement _htmlUnitElement;
+ static final Relationship DEFINES_CLASS = Relationship.getRelationship("defines-class");
/**
- * Initialize a newly created Angular HTML index contributor.
- *
- * @param store the [IndexStore] to record relations into.
+ * The relationship used to indicate that a container (the left-operand) contains the definition
+ * of a function at a specific location (the right operand).
*/
- 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);
-}
-
-class IndexContributor_AngularHtmlIndexContributor extends IndexContributor {
- final AngularHtmlIndexContributor AngularHtmlIndexContributor_this;
-
- IndexContributor_AngularHtmlIndexContributor(IndexStore arg0, this.AngularHtmlIndexContributor_this) : super(arg0);
-
- @override
- Element peekElement() => AngularHtmlIndexContributor_this._htmlUnitElement;
+ static final Relationship DEFINES_FUNCTION = Relationship.getRelationship("defines-function");
- @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);
- }
-}
+ /**
+ * 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 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 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
+ * 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).
*/
- void getRelationships(Element element, Relationship relationship, RelationshipCallback callback);
+ static final Relationship DEFINES_FUNCTION_TYPE = Relationship.getRelationship("defines-function-type");
/**
- * Answer index statistics.
+ * The relationship used to indicate that a container (the left-operand) contains the definition
+ * of a method at a specific location (the right operand).
*/
- String get statistics;
+ static final Relationship DEFINES_VARIABLE = Relationship.getRelationship("defines-variable");
/**
- * 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
+ * The relationship used to indicate that a name (the left-operand) is defined at a specific
+ * location (the right operand).
*/
- void indexHtmlUnit(AnalysisContext context, ht.HtmlUnit unit);
+ static final Relationship IS_DEFINED_BY = Relationship.getRelationship("is-defined-by");
/**
- * 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
+ * The relationship used to indicate that a type (the left-operand) is extended by a type at a
+ * specific location (the right operand).
*/
- void indexUnit(AnalysisContext context, CompilationUnit unit);
+ static final Relationship IS_EXTENDED_BY = Relationship.getRelationship("is-extended-by");
/**
- * 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
+ * The relationship used to indicate that a type (the left-operand) is implemented by a type at a
+ * specific location (the right operand).
*/
- void removeContext(AnalysisContext context);
+ static final Relationship IS_IMPLEMENTED_BY = Relationship.getRelationship("is-implemented-by");
/**
- * 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
+ * The relationship used to indicate that a type (the left-operand) is mixed into a type at a
+ * specific location (the right operand).
*/
- void removeSource(AnalysisContext context, Source source);
+ static final Relationship IS_MIXED_IN_BY = Relationship.getRelationship("is-mixed-in-by");
/**
- * 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
+ * The relationship used to indicate that a parameter or variable (the left-operand) is read at a
+ * specific location (the right operand).
*/
- void removeSources(AnalysisContext context, SourceContainer container);
+ static final Relationship IS_READ_BY = Relationship.getRelationship("is-read-by");
/**
- * Should be called in separate [Thread] to process request in this [Index]. Does not
- * return until the [stop] method is called.
+ * 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).
*/
- void run();
+ static final Relationship IS_READ_WRITTEN_BY = Relationship.getRelationship("is-read-written-by");
/**
- * Should be called to stop process running [run], so stop processing requests.
+ * The relationship used to indicate that a parameter or variable (the left-operand) is modified
+ * (assigned to) at a specific location (the right operand).
*/
- void stop();
-}
+ static final Relationship IS_WRITTEN_BY = Relationship.getRelationship("is-written-by");
-/**
- * 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
+ * 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.
*/
- bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement);
+ static final Relationship IS_REFERENCED_BY = Relationship.getRelationship("is-referenced-by");
/**
- * 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
+ * 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.
*/
- bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement);
+ static final Relationship IS_REFERENCED_BY_QUALIFIED_RESOLVED = Relationship.getRelationship("is-referenced-by_qualified-resolved");
/**
- * 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
+ * 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.
*/
- List<Location> getRelationships(Element element, Relationship relationship);
+ static final Relationship IS_REFERENCED_BY_QUALIFIED_UNRESOLVED = Relationship.getRelationship("is-referenced-by_qualified-unresolved");
/**
- * Answer index statistics.
+ * 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.
*/
- String get statistics;
+ static final Relationship IS_REFERENCED_BY_QUALIFIED = Relationship.getRelationship("is-referenced-by-qualified");
/**
- * 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
+ * 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.
*/
- void recordRelationship(Element element, Relationship relationship, Location location);
+ static final Relationship IS_REFERENCED_BY_UNQUALIFIED = Relationship.getRelationship("is-referenced-by-unqualified");
/**
- * 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
+ * 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.
*/
- void removeContext(AnalysisContext context);
+ static final Relationship IS_INVOKED_BY = Relationship.getRelationship("is-invoked-by");
/**
- * 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
+ * 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.
*/
- void removeSource(AnalysisContext context, Source source);
+ static final Relationship IS_INVOKED_BY_QUALIFIED = Relationship.getRelationship("is-invoked-by-qualified");
/**
- * 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
+ * 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.
*/
- void removeSources(AnalysisContext context, SourceContainer container);
-}
-
-/**
- * Implementation of [UniverseElement].
- */
-class UniverseElementImpl extends ElementImpl implements UniverseElement {
- static UniverseElementImpl INSTANCE = new UniverseElementImpl();
-
- UniverseElementImpl() : super("--universe--", -1);
+ static final Relationship IS_INVOKED_BY_UNQUALIFIED = Relationship.getRelationship("is-invoked-by-unqualified");
- @override
- accept(ElementVisitor visitor) => null;
+ /**
+ * Reference to some [AngularElement].
+ */
+ static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("angular-reference");
- @override
- ElementKind get kind => ElementKind.UNIVERSE;
+ /**
+ * Reference to some closing tag of an XML element.
+ */
+ static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRelationship("angular-closing-tag-reference");
}
/**
@@ -2154,197 +2110,316 @@ class IndexContributor_ImportElementInfo {
}
/**
- * Special [Element] which is used to index references to the name without specifying concrete
- * kind of this name - field, method or something else.
+ * 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.
*/
-class NameElementImpl extends ElementImpl {
- NameElementImpl(String name) : super("name:${name}", -1);
+abstract class Index {
+ /**
+ * 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);
- @override
- accept(ElementVisitor visitor) => null;
+ /**
+ * Answer index statistics.
+ */
+ String get statistics;
- @override
- ElementKind get kind => ElementKind.NAME;
+ /**
+ * 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();
}
/**
- * Visits resolved [CompilationUnit] and adds Angular specific relationships into
- * [IndexStore].
+ * Instances of the [RemoveContextOperation] implement an operation that removes from the
+ * index any data based on the specified [AnalysisContext].
*/
-class AngularDartIndexContributor extends GeneralizingAstVisitor<Object> {
- final IndexStore _store;
+class RemoveContextOperation implements IndexOperation {
+ /**
+ * The index store against which this operation is being run.
+ */
+ final IndexStore _indexStore;
- AngularDartIndexContributor(this._store);
+ /**
+ * 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
- 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;
+ bool get isQuery => false;
+
+ @override
+ void performOperation() {
+ _indexStore.removeContext(context);
}
@override
- Object visitCompilationUnitMember(CompilationUnitMember node) => null;
+ bool removeWhenSourceRemoved(Source source) => false;
+
+ @override
+ String toString() => "RemoveContext(${context})";
+}
+
+/**
+ * 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;
- void _indexComponent(AngularComponentElement component) {
- _indexProperties(component.properties);
+ @override
+ void performOperation() {
+ List<Location> locations;
+ locations = _indexStore.getRelationships(element, relationship);
+ callback.hasRelationships(element, relationship, locations);
}
- void _indexDirective(AngularDecoratorElement directive) {
- _indexProperties(directive.properties);
- }
+ @override
+ bool removeWhenSourceRemoved(Source source) => false;
- /**
- * 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);
- }
- }
- }
- }
- }
+ @override
+ String toString() => "GetRelationships(${element}, ${relationship})";
}
/**
- * Instances of the [RemoveContextOperation] implement an operation that removes from the
- * index any data based on the specified [AnalysisContext].
+ * Instances of the [RemoveSourceOperation] implement an operation that removes from the index
+ * any data based on the content of a specified source.
*/
-class RemoveContextOperation implements IndexOperation {
+class RemoveSourceOperation implements IndexOperation {
/**
* The index store against which this operation is being run.
*/
final IndexStore _indexStore;
/**
- * The context being removed.
+ * The context in which source being removed.
*/
- final AnalysisContext context;
+ 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
+ * @param context the [AnalysisContext] to remove source in
+ * @param source the [Source] to remove from index
*/
- RemoveContextOperation(this._indexStore, this.context);
+ RemoveSourceOperation(this._indexStore, this._context, this.source);
@override
bool get isQuery => false;
@override
void performOperation() {
- _indexStore.removeContext(context);
+ _indexStore.removeSource(_context, source);
}
@override
bool removeWhenSourceRemoved(Source source) => false;
@override
- String toString() => "RemoveContext(${context})";
+ String toString() => "RemoveSource(${source.fullName})";
}
/**
- * Instances of the [IndexHtmlUnitOperation] implement an operation that adds data to the
- * index based on the resolved [HtmlUnit].
+ * The interface [IndexOperation] defines the behavior of objects used to perform operations
+ * on an index.
*/
-class IndexHtmlUnitOperation implements IndexOperation {
+abstract class IndexOperation {
/**
- * The index store against which this operation is being run.
+ * Return `true` if this operation returns information from the index.
+ *
+ * @return `true` if this operation returns information from the index
*/
- final IndexStore _indexStore;
+ bool get isQuery;
/**
- * The context in which [HtmlUnit] was resolved.
+ * Perform the operation implemented by this operation.
*/
- final AnalysisContext _context;
+ void performOperation();
/**
- * The [HtmlUnit] being indexed.
+ * 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
*/
- final ht.HtmlUnit unit;
+ bool removeWhenSourceRemoved(Source source);
+}
+
+/**
+ * [IndexStore] which keeps all information in memory, but can write it to stream and read
+ * later.
+ */
+abstract class MemoryIndexStore implements IndexStore {
+}
+
+/**
+ * [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);
+}
+/**
+ * Relationship between an element and a location. Relationships are identified by a globally unique
+ * identifier.
+ */
+class Relationship {
/**
- * The element of the [HtmlUnit] being indexed.
+ * The unique identifier for this relationship.
*/
- HtmlElement _htmlElement;
+ final String _uniqueId;
/**
- * The source being indexed.
+ * A table mapping relationship identifiers to relationships.
*/
- Source _source;
+ static Map<String, Relationship> _RelationshipMap = {};
/**
- * Initialize a newly created operation that will index the specified [HtmlUnit].
+ * Return the relationship with the given unique identifier.
*
- * @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]
+ * @param uniqueId the unique identifier for the relationship
+ * @return the relationship with the given unique identifier
*/
- IndexHtmlUnitOperation(this._indexStore, this._context, this.unit) {
- this._htmlElement = unit.element;
- this._source = _htmlElement.source;
+ static Relationship getRelationship(String uniqueId) {
+ Relationship relationship = _RelationshipMap[uniqueId];
+ if (relationship == null) {
+ relationship = new Relationship(uniqueId);
+ _RelationshipMap[uniqueId] = relationship;
+ }
+ return relationship;
}
/**
- * @return the [Source] to be indexed.
+ * @return all registered [Relationship]s.
*/
- Source get source => _source;
-
- @override
- bool get isQuery => false;
+ static Iterable<Relationship> values() => _RelationshipMap.values;
- @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);
- }
- }
+ /**
+ * Initialize a newly created relationship to have the given unique identifier.
+ *
+ * @param uniqueId the unique identifier for this relationship
+ */
+ Relationship(this._uniqueId);
- @override
- bool removeWhenSourceRemoved(Source source) => this._source == source;
+ /**
+ * Return the unique identifier for this relationship.
+ *
+ * @return the unique identifier for this relationship
+ */
+ String get identifier => _uniqueId;
@override
- String toString() => "IndexHtmlUnitOperation(${_source.fullName})";
+ String toString() => _uniqueId;
}
/**
@@ -2399,79 +2474,4 @@ class Location {
@override
String toString() => "[${offset} - ${(offset + length)}) in ${element}";
-}
-
-/**
- * [IndexStore] which keeps all information in memory, but can write it to stream and read
- * later.
- */
-abstract class MemoryIndexStore implements IndexStore {
-}
-
-/**
- * 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})";
-}
-
-/**
- * [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);
-}
-
-/**
- * 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);
}

Powered by Google App Engine
This is Rietveld 408576698