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 |
deleted file mode 100644 |
index 08b2c67fb2a7a983a353f7db328ac294486bc003..0000000000000000000000000000000000000000 |
--- a/pkg/analyzer/lib/src/generated/index.dart |
+++ /dev/null |
@@ -1,2586 +0,0 @@ |
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-// This code was auto-generated, is not intended to be edited, and is subject to |
-// significant change. Please see the README file for more information. |
- |
-library engine.index; |
- |
-import 'dart:collection' show Queue; |
-import 'java_core.dart'; |
-import 'java_engine.dart'; |
-import 'source.dart'; |
-import 'scanner.dart' show Token; |
-import 'ast.dart'; |
-import 'element.dart'; |
-import 'resolver.dart' show Namespace, NamespaceBuilder; |
-import 'engine.dart'; |
-import 'html.dart' as ht; |
- |
-/** |
- * Visits resolved [CompilationUnit] and adds Angular specific relationships into |
- * [IndexStore]. |
- */ |
-class AngularDartIndexContributor extends GeneralizingAstVisitor<Object> { |
- final IndexStore _store; |
- |
- AngularDartIndexContributor(this._store); |
- |
- @override |
- Object visitClassDeclaration(ClassDeclaration node) { |
- ClassElement classElement = node.element; |
- if (classElement != null) { |
- List<ToolkitObjectElement> toolkitObjects = classElement.toolkitObjects; |
- for (ToolkitObjectElement object in toolkitObjects) { |
- if (object is AngularComponentElement) { |
- _indexComponent(object); |
- } |
- if (object is AngularDecoratorElement) { |
- AngularDecoratorElement directive = object; |
- _indexDirective(directive); |
- } |
- } |
- } |
- // stop visiting |
- return null; |
- } |
- |
- @override |
- Object visitCompilationUnitMember(CompilationUnitMember node) => null; |
- |
- void _indexComponent(AngularComponentElement component) { |
- _indexProperties(component.properties); |
- } |
- |
- void _indexDirective(AngularDecoratorElement directive) { |
- _indexProperties(directive.properties); |
- } |
- |
- /** |
- * Index [FieldElement] references from [AngularPropertyElement]s. |
- */ |
- void _indexProperties(List<AngularPropertyElement> properties) { |
- for (AngularPropertyElement property in properties) { |
- FieldElement field = property.field; |
- if (field != null) { |
- int offset = property.fieldNameOffset; |
- if (offset == -1) { |
- continue; |
- } |
- int length = field.name.length; |
- Location location = new Location(property, offset, length); |
- // getter reference |
- if (property.propertyKind.callsGetter()) { |
- PropertyAccessorElement getter = field.getter; |
- if (getter != null) { |
- _store.recordRelationship(getter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location); |
- } |
- } |
- // setter reference |
- if (property.propertyKind.callsSetter()) { |
- PropertyAccessorElement setter = field.setter; |
- if (setter != null) { |
- _store.recordRelationship(setter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location); |
- } |
- } |
- } |
- } |
- } |
-} |
- |
-/** |
- * Visits resolved [HtmlUnit] and adds relationships into [IndexStore]. |
- */ |
-class AngularHtmlIndexContributor extends ExpressionVisitor { |
- /** |
- * The [IndexStore] to record relations into. |
- */ |
- final IndexStore _store; |
- |
- /** |
- * The index contributor used to index Dart [Expression]s. |
- */ |
- IndexContributor _indexContributor; |
- |
- HtmlElement _htmlUnitElement; |
- |
- /** |
- * Initialize a newly created Angular HTML index contributor. |
- * |
- * @param store the [IndexStore] to record relations into. |
- */ |
- AngularHtmlIndexContributor(this._store) { |
- _indexContributor = new IndexContributor_AngularHtmlIndexContributor(_store, this); |
- } |
- |
- @override |
- void visitExpression(Expression expression) { |
- // Formatter |
- if (expression is SimpleIdentifier) { |
- SimpleIdentifier identifier = expression; |
- Element element = identifier.bestElement; |
- if (element is AngularElement) { |
- _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, _createLocationForIdentifier(identifier)); |
- return; |
- } |
- } |
- // index as a normal Dart expression |
- expression.accept(_indexContributor); |
- } |
- |
- @override |
- Object visitHtmlUnit(ht.HtmlUnit node) { |
- _htmlUnitElement = node.element; |
- CompilationUnitElement dartUnitElement = _htmlUnitElement.angularCompilationUnit; |
- _indexContributor.enterScope(dartUnitElement); |
- return super.visitHtmlUnit(node); |
- } |
- |
- @override |
- Object visitXmlAttributeNode(ht.XmlAttributeNode node) { |
- Element element = node.element; |
- if (element != null) { |
- ht.Token nameToken = node.nameToken; |
- Location location = _createLocationForToken(nameToken); |
- _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, location); |
- } |
- return super.visitXmlAttributeNode(node); |
- } |
- |
- @override |
- Object visitXmlTagNode(ht.XmlTagNode node) { |
- Element element = node.element; |
- if (element != null) { |
- // tag |
- { |
- ht.Token tagToken = node.tagToken; |
- Location location = _createLocationForToken(tagToken); |
- _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, location); |
- } |
- // maybe add closing tag range |
- ht.Token closingTag = node.closingTag; |
- if (closingTag != null) { |
- Location location = _createLocationForToken(closingTag); |
- _store.recordRelationship(element, IndexConstants.ANGULAR_CLOSING_TAG_REFERENCE, location); |
- } |
- } |
- return super.visitXmlTagNode(node); |
- } |
- |
- Location _createLocationForIdentifier(SimpleIdentifier identifier) => new Location(_htmlUnitElement, identifier.offset, identifier.length); |
- |
- Location _createLocationForToken(ht.Token token) => new Location(_htmlUnitElement, token.offset, token.length); |
-} |
- |
-/** |
- * Instances of the [ClearOperation] implement an operation that removes all of the |
- * information from the index. |
- */ |
-class ClearOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- ClearOperation(this._indexStore); |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- _indexStore.clear(); |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => false; |
- |
- @override |
- String toString() => "ClearOperation()"; |
-} |
- |
-/** |
- * Recursively visits [HtmlUnit] and every embedded [Expression]. |
- */ |
-abstract class ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> { |
- /** |
- * Visits the given [Expression]s embedded into tag or attribute. |
- * |
- * @param expression the [Expression] to visit, not `null` |
- */ |
- void visitExpression(Expression expression); |
- |
- @override |
- Object visitXmlAttributeNode(ht.XmlAttributeNode node) { |
- _visitExpressions(node.expressions); |
- return super.visitXmlAttributeNode(node); |
- } |
- |
- @override |
- Object visitXmlTagNode(ht.XmlTagNode node) { |
- _visitExpressions(node.expressions); |
- return super.visitXmlTagNode(node); |
- } |
- |
- /** |
- * Visits [Expression]s of the given [XmlExpression]s. |
- */ |
- void _visitExpressions(List<ht.XmlExpression> expressions) { |
- for (ht.XmlExpression xmlExpression in expressions) { |
- if (xmlExpression is AngularXmlExpression) { |
- AngularXmlExpression angularXmlExpression = xmlExpression; |
- List<Expression> dartExpressions = angularXmlExpression.expression.expressions; |
- for (Expression dartExpression in dartExpressions) { |
- visitExpression(dartExpression); |
- } |
- } |
- if (xmlExpression is ht.RawXmlExpression) { |
- ht.RawXmlExpression rawXmlExpression = xmlExpression; |
- visitExpression(rawXmlExpression.expression); |
- } |
- } |
- } |
-} |
- |
-/** |
- * Instances of the [GetRelationshipsOperation] implement an operation used to access the |
- * locations that have a specified relationship with a specified element. |
- */ |
-class GetRelationshipsOperation implements IndexOperation { |
- final IndexStore _indexStore; |
- |
- final Element element; |
- |
- final Relationship relationship; |
- |
- final RelationshipCallback callback; |
- |
- /** |
- * Initialize a newly created operation that will access the locations that have a specified |
- * relationship with a specified element. |
- */ |
- GetRelationshipsOperation(this._indexStore, this.element, this.relationship, this.callback); |
- |
- @override |
- bool get isQuery => true; |
- |
- @override |
- void performOperation() { |
- List<Location> locations; |
- locations = _indexStore.getRelationships(element, relationship); |
- callback.hasRelationships(element, relationship, locations); |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => false; |
- |
- @override |
- String toString() => "GetRelationships(${element}, ${relationship})"; |
-} |
- |
-/** |
- * The interface [Index] defines the behavior of objects that maintain an index storing |
- * [Relationship] between [Element]. All of the operations |
- * defined on the index are asynchronous, and results, when there are any, are provided through a |
- * callback. |
- * |
- * Despite being asynchronous, the results of the operations are guaranteed to be consistent with |
- * the expectation that operations are performed in the order in which they are requested. |
- * Modification operations are executed before any read operation. There is no guarantee about the |
- * order in which the callbacks for read operations will be invoked. |
- */ |
-abstract class Index { |
- /** |
- * Asynchronously remove from the index all of the information. |
- */ |
- void clear(); |
- |
- /** |
- * Asynchronously invoke the given callback with an array containing all of the locations of the |
- * elements that have the given relationship with the given element. For example, if the element |
- * represents a method and the relationship is the is-referenced-by relationship, then the |
- * locations that will be passed into the callback will be all of the places where the method is |
- * invoked. |
- * |
- * @param element the element that has the relationship with the locations to be returned |
- * @param relationship the relationship between the given element and the locations to be returned |
- * @param callback the callback that will be invoked when the locations are found |
- */ |
- void getRelationships(Element element, Relationship relationship, RelationshipCallback callback); |
- |
- /** |
- * Answer index statistics. |
- */ |
- String get statistics; |
- |
- /** |
- * Asynchronously process the given [HtmlUnit] in order to record the relationships. |
- * |
- * @param context the [AnalysisContext] in which [HtmlUnit] was resolved |
- * @param unit the [HtmlUnit] being indexed |
- */ |
- void indexHtmlUnit(AnalysisContext context, ht.HtmlUnit unit); |
- |
- /** |
- * Asynchronously process the given [CompilationUnit] in order to record the relationships. |
- * |
- * @param context the [AnalysisContext] in which [CompilationUnit] was resolved |
- * @param unit the [CompilationUnit] being indexed |
- */ |
- void indexUnit(AnalysisContext context, CompilationUnit unit); |
- |
- /** |
- * Asynchronously remove from the index all of the information associated with the given context. |
- * |
- * This method should be invoked when a context is disposed. |
- * |
- * @param context the [AnalysisContext] to remove |
- */ |
- void removeContext(AnalysisContext context); |
- |
- /** |
- * Asynchronously remove from the index all of the information associated with elements or |
- * locations in the given source. This includes relationships between an element in the given |
- * source and any other locations, relationships between any other elements and a location within |
- * the given source. |
- * |
- * This method should be invoked when a source is no longer part of the code base. |
- * |
- * @param context the [AnalysisContext] in which [Source] being removed |
- * @param source the [Source] being removed |
- */ |
- void removeSource(AnalysisContext context, Source source); |
- |
- /** |
- * Asynchronously remove from the index all of the information associated with elements or |
- * locations in the given sources. This includes relationships between an element in the given |
- * sources and any other locations, relationships between any other elements and a location within |
- * the given sources. |
- * |
- * This method should be invoked when multiple sources are no longer part of the code base. |
- * |
- * @param the [AnalysisContext] in which [Source]s being removed |
- * @param container the [SourceContainer] holding the sources being removed |
- */ |
- void removeSources(AnalysisContext context, SourceContainer container); |
- |
- /** |
- * Should be called in separate [Thread] to process request in this [Index]. Does not |
- * return until the [stop] method is called. |
- */ |
- void run(); |
- |
- /** |
- * Should be called to stop process running [run], so stop processing requests. |
- */ |
- void stop(); |
-} |
- |
-/** |
- * Constants used when populating and accessing the index. |
- */ |
-abstract class IndexConstants { |
- /** |
- * An element used to represent the universe. |
- */ |
- static final Element UNIVERSE = UniverseElement.INSTANCE; |
- |
- /** |
- * The relationship used to indicate that a container (the left-operand) contains the definition |
- * of a class at a specific location (the right operand). |
- */ |
- static final Relationship DEFINES_CLASS = Relationship.getRelationship("defines-class"); |
- |
- /** |
- * The relationship used to indicate that a container (the left-operand) contains the definition |
- * of a function at a specific location (the right operand). |
- */ |
- static final Relationship DEFINES_FUNCTION = Relationship.getRelationship("defines-function"); |
- |
- /** |
- * The relationship used to indicate that a container (the left-operand) contains the definition |
- * of a class type alias at a specific location (the right operand). |
- */ |
- static final Relationship DEFINES_CLASS_ALIAS = Relationship.getRelationship("defines-class-alias"); |
- |
- /** |
- * The relationship used to indicate that a container (the left-operand) contains the definition |
- * of a function type at a specific location (the right operand). |
- */ |
- static final Relationship DEFINES_FUNCTION_TYPE = Relationship.getRelationship("defines-function-type"); |
- |
- /** |
- * The relationship used to indicate that a container (the left-operand) contains the definition |
- * of a method at a specific location (the right operand). |
- */ |
- static final Relationship DEFINES_VARIABLE = Relationship.getRelationship("defines-variable"); |
- |
- /** |
- * The relationship used to indicate that a name (the left-operand) is defined at a specific |
- * location (the right operand). |
- */ |
- static final Relationship IS_DEFINED_BY = Relationship.getRelationship("is-defined-by"); |
- |
- /** |
- * The relationship used to indicate that a type (the left-operand) is extended by a type at a |
- * specific location (the right operand). |
- */ |
- static final Relationship IS_EXTENDED_BY = Relationship.getRelationship("is-extended-by"); |
- |
- /** |
- * The relationship used to indicate that a type (the left-operand) is implemented by a type at a |
- * specific location (the right operand). |
- */ |
- static final Relationship IS_IMPLEMENTED_BY = Relationship.getRelationship("is-implemented-by"); |
- |
- /** |
- * The relationship used to indicate that a type (the left-operand) is mixed into a type at a |
- * specific location (the right operand). |
- */ |
- static final Relationship IS_MIXED_IN_BY = Relationship.getRelationship("is-mixed-in-by"); |
- |
- /** |
- * The relationship used to indicate that a parameter or variable (the left-operand) is read at a |
- * specific location (the right operand). |
- */ |
- static final Relationship IS_READ_BY = Relationship.getRelationship("is-read-by"); |
- |
- /** |
- * The relationship used to indicate that a parameter or variable (the left-operand) is both read |
- * and modified at a specific location (the right operand). |
- */ |
- static final Relationship IS_READ_WRITTEN_BY = Relationship.getRelationship("is-read-written-by"); |
- |
- /** |
- * The relationship used to indicate that a parameter or variable (the left-operand) is modified |
- * (assigned to) at a specific location (the right operand). |
- */ |
- static final Relationship IS_WRITTEN_BY = Relationship.getRelationship("is-written-by"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is referenced at a |
- * specific location (the right operand). This is used for everything except read/write operations |
- * for fields, parameters, and variables. Those use either [IS_REFERENCED_BY_QUALIFIED], |
- * [IS_REFERENCED_BY_UNQUALIFIED], [IS_READ_BY], [IS_WRITTEN_BY] or |
- * [IS_READ_WRITTEN_BY], as appropriate. |
- */ |
- static final Relationship IS_REFERENCED_BY = Relationship.getRelationship("is-referenced-by"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is |
- * referenced at a specific location (the right operand). This is used for qualified resolved |
- * references to methods and fields. |
- */ |
- static final Relationship IS_REFERENCED_BY_QUALIFIED_RESOLVED = Relationship.getRelationship("is-referenced-by-qualified-resolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is |
- * referenced at a specific location (the right operand). This is used for qualified unresolved |
- * references to methods and fields. |
- */ |
- static final Relationship IS_REFERENCED_BY_QUALIFIED_UNRESOLVED = Relationship.getRelationship("is-referenced-by-qualified-unresolved"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is referenced at a |
- * specific location (the right operand). This is used for field accessors and methods. |
- */ |
- static final Relationship IS_REFERENCED_BY_QUALIFIED = Relationship.getRelationship("is-referenced-by-qualified"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is referenced at a |
- * specific location (the right operand). This is used for field accessors and methods. |
- */ |
- static final Relationship IS_REFERENCED_BY_UNQUALIFIED = Relationship.getRelationship("is-referenced-by-unqualified"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is invoked at a specific |
- * location (the right operand). This is used for functions. |
- */ |
- static final Relationship IS_INVOKED_BY = Relationship.getRelationship("is-invoked-by"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is invoked at a specific |
- * location (the right operand). This is used for methods. |
- */ |
- static final Relationship IS_INVOKED_BY_QUALIFIED = Relationship.getRelationship("is-invoked-by-qualified"); |
- |
- /** |
- * The relationship used to indicate that an element (the left-operand) is invoked at a specific |
- * location (the right operand). This is used for methods. |
- */ |
- static final Relationship IS_INVOKED_BY_UNQUALIFIED = Relationship.getRelationship("is-invoked-by-unqualified"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is invoked |
- * at a specific location (the right operand). This is used for resolved invocations. |
- */ |
- static final Relationship NAME_IS_INVOKED_BY_RESOLVED = Relationship.getRelationship("name-is-invoked-by-resolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is read at |
- * a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_READ_BY_RESOLVED = Relationship.getRelationship("name-is-read-by-resolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is both |
- * read and written at a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_READ_WRITTEN_BY_RESOLVED = Relationship.getRelationship("name-is-read-written-by-resolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is written |
- * at a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_WRITTEN_BY_RESOLVED = Relationship.getRelationship("name-is-written-by-resolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is invoked |
- * at a specific location (the right operand). This is used for unresolved invocations. |
- */ |
- static final Relationship NAME_IS_INVOKED_BY_UNRESOLVED = Relationship.getRelationship("name-is-invoked-by-unresolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is read at |
- * a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_READ_BY_UNRESOLVED = Relationship.getRelationship("name-is-read-by-unresolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is both |
- * read and written at a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_READ_WRITTEN_BY_UNRESOLVED = Relationship.getRelationship("name-is-read-written-by-unresolved"); |
- |
- /** |
- * The relationship used to indicate that an [NameElementImpl] (the left-operand) is written |
- * at a specific location (the right operand). |
- */ |
- static final Relationship NAME_IS_WRITTEN_BY_UNRESOLVED = Relationship.getRelationship("name-is-written-by-unresolved"); |
- |
- /** |
- * Reference to some [AngularElement]. |
- */ |
- static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("angular-reference"); |
- |
- /** |
- * Reference to some closing tag of an XML element. |
- */ |
- static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRelationship("angular-closing-tag-reference"); |
-} |
- |
-/** |
- * Visits resolved AST and adds relationships into [IndexStore]. |
- */ |
-class IndexContributor extends GeneralizingAstVisitor<Object> { |
- /** |
- * @return the [Location] representing location of the [Element]. |
- */ |
- static Location createLocation(Element element) { |
- if (element != null) { |
- int offset = element.nameOffset; |
- int length = element.displayName.length; |
- return new Location(element, offset, length); |
- } |
- return null; |
- } |
- |
- /** |
- * @return the [ImportElement] that is referenced by this node with [PrefixElement], |
- * may be `null`. |
- */ |
- static ImportElement getImportElement(SimpleIdentifier prefixNode) { |
- IndexContributor_ImportElementInfo info = getImportElementInfo(prefixNode); |
- return info != null ? info._element : null; |
- } |
- |
- /** |
- * @return the [ImportElementInfo] with [ImportElement] that is referenced by this |
- * node with [PrefixElement], may be `null`. |
- */ |
- static IndexContributor_ImportElementInfo getImportElementInfo(SimpleIdentifier prefixNode) { |
- IndexContributor_ImportElementInfo info = new IndexContributor_ImportElementInfo(); |
- // prepare environment |
- AstNode parent = prefixNode.parent; |
- CompilationUnit unit = prefixNode.getAncestor((node) => node is CompilationUnit); |
- LibraryElement libraryElement = unit.element.library; |
- // prepare used element |
- Element usedElement = null; |
- if (parent is PrefixedIdentifier) { |
- PrefixedIdentifier prefixed = parent; |
- if (identical(prefixed.prefix, prefixNode)) { |
- usedElement = prefixed.staticElement; |
- info._periodEnd = prefixed.period.end; |
- } |
- } |
- if (parent is MethodInvocation) { |
- MethodInvocation invocation = parent; |
- if (identical(invocation.target, prefixNode)) { |
- usedElement = invocation.methodName.staticElement; |
- info._periodEnd = invocation.period.end; |
- } |
- } |
- // we need used Element |
- if (usedElement == null) { |
- return null; |
- } |
- // find ImportElement |
- String prefix = prefixNode.name; |
- Map<ImportElement, Set<Element>> importElementsMap = {}; |
- info._element = _internalGetImportElement(libraryElement, prefix, usedElement, importElementsMap); |
- if (info._element == null) { |
- return null; |
- } |
- return info; |
- } |
- |
- /** |
- * If the given expression has resolved type, returns the new location with this type. |
- * |
- * @param location the base location |
- * @param expression the expression assigned at the given location |
- */ |
- static Location _getLocationWithExpressionType(Location location, Expression expression) { |
- if (expression != null) { |
- return new LocationWithData<DartType>.con1(location, expression.bestType); |
- } |
- return location; |
- } |
- |
- /** |
- * If the given node is the part of the [ConstructorFieldInitializer], returns location with |
- * type of the initializer expression. |
- */ |
- static Location _getLocationWithInitializerType(SimpleIdentifier node, Location location) { |
- if (node.parent is ConstructorFieldInitializer) { |
- ConstructorFieldInitializer initializer = node.parent as ConstructorFieldInitializer; |
- if (identical(initializer.fieldName, node)) { |
- location = _getLocationWithExpressionType(location, initializer.expression); |
- } |
- } |
- return location; |
- } |
- |
- /** |
- * If the given identifier has a synthetic [PropertyAccessorElement], i.e. accessor for |
- * normal field, and it is LHS of assignment, then include [Type] of the assigned value into |
- * the [Location]. |
- * |
- * @param identifier the identifier to record location |
- * @param element the element of the identifier |
- * @param location the raw location |
- * @return the [Location] with the type of the assigned value |
- */ |
- static Location _getLocationWithTypeAssignedToField(SimpleIdentifier identifier, Element element, Location location) { |
- // we need accessor |
- if (element is! PropertyAccessorElement) { |
- return location; |
- } |
- PropertyAccessorElement accessor = element as PropertyAccessorElement; |
- // should be setter |
- if (!accessor.isSetter) { |
- return location; |
- } |
- // accessor should be synthetic, i.e. field normal |
- if (!accessor.isSynthetic) { |
- return location; |
- } |
- // should be LHS of assignment |
- AstNode parent; |
- { |
- AstNode node = identifier; |
- parent = node.parent; |
- // new T().field = x; |
- if (parent is PropertyAccess) { |
- PropertyAccess propertyAccess = parent as PropertyAccess; |
- if (identical(propertyAccess.propertyName, node)) { |
- node = propertyAccess; |
- parent = propertyAccess.parent; |
- } |
- } |
- // obj.field = x; |
- if (parent is PrefixedIdentifier) { |
- PrefixedIdentifier prefixedIdentifier = parent as PrefixedIdentifier; |
- if (identical(prefixedIdentifier.identifier, node)) { |
- node = prefixedIdentifier; |
- parent = prefixedIdentifier.parent; |
- } |
- } |
- } |
- // OK, remember the type |
- if (parent is AssignmentExpression) { |
- AssignmentExpression assignment = parent as AssignmentExpression; |
- Expression rhs = assignment.rightHandSide; |
- location = _getLocationWithExpressionType(location, rhs); |
- } |
- // done |
- return location; |
- } |
- |
- /** |
- * @return the [ImportElement] that declares given [PrefixElement] and imports library |
- * with given "usedElement". |
- */ |
- static ImportElement _internalGetImportElement(LibraryElement libraryElement, String prefix, Element usedElement, Map<ImportElement, Set<Element>> importElementsMap) { |
- // validate Element |
- if (usedElement == null) { |
- return null; |
- } |
- if (usedElement.enclosingElement is! CompilationUnitElement) { |
- return null; |
- } |
- LibraryElement usedLibrary = usedElement.library; |
- // find ImportElement that imports used library with used prefix |
- List<ImportElement> candidates = null; |
- for (ImportElement importElement in libraryElement.imports) { |
- // required library |
- if (importElement.importedLibrary != usedLibrary) { |
- continue; |
- } |
- // required prefix |
- PrefixElement prefixElement = importElement.prefix; |
- if (prefix == null) { |
- if (prefixElement != null) { |
- continue; |
- } |
- } else { |
- if (prefixElement == null) { |
- continue; |
- } |
- if (prefix != prefixElement.name) { |
- continue; |
- } |
- } |
- // no combinators => only possible candidate |
- if (importElement.combinators.length == 0) { |
- return importElement; |
- } |
- // OK, we have candidate |
- if (candidates == null) { |
- candidates = []; |
- } |
- candidates.add(importElement); |
- } |
- // no candidates, probably element is defined in this library |
- if (candidates == null) { |
- return null; |
- } |
- // one candidate |
- if (candidates.length == 1) { |
- return candidates[0]; |
- } |
- // ensure that each ImportElement has set of elements |
- for (ImportElement importElement in candidates) { |
- if (importElementsMap.containsKey(importElement)) { |
- continue; |
- } |
- Namespace namespace = new NamespaceBuilder().createImportNamespaceForDirective(importElement); |
- Set<Element> elements = new Set(); |
- importElementsMap[importElement] = elements; |
- } |
- // use import namespace to choose correct one |
- for (MapEntry<ImportElement, Set<Element>> entry in getMapEntrySet(importElementsMap)) { |
- if (entry.getValue().contains(usedElement)) { |
- return entry.getKey(); |
- } |
- } |
- // not found |
- return null; |
- } |
- |
- /** |
- * @return `true` if given "node" is part of an import [Combinator]. |
- */ |
- static bool _isIdentifierInImportCombinator(SimpleIdentifier node) { |
- AstNode parent = node.parent; |
- return parent is Combinator; |
- } |
- |
- /** |
- * @return `true` if given "node" is part of [PrefixedIdentifier] "prefix.node". |
- */ |
- static bool _isIdentifierInPrefixedIdentifier(SimpleIdentifier node) { |
- AstNode parent = node.parent; |
- return parent is PrefixedIdentifier && identical(parent.identifier, node); |
- } |
- |
- final IndexStore _store; |
- |
- LibraryElement _libraryElement; |
- |
- Map<ImportElement, Set<Element>> _importElementsMap = {}; |
- |
- /** |
- * A stack whose top element (the element with the largest index) is an element representing the |
- * inner-most enclosing scope. |
- */ |
- Queue<Element> _elementStack = new Queue(); |
- |
- IndexContributor(this._store); |
- |
- /** |
- * Enter a new scope represented by the given [Element]. |
- */ |
- void enterScope(Element element) { |
- _elementStack.addFirst(element); |
- } |
- |
- /** |
- * @return the inner-most enclosing [Element], may be `null`. |
- */ |
- Element peekElement() { |
- for (Element element in _elementStack) { |
- if (element != null) { |
- return element; |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitAssignmentExpression(AssignmentExpression node) { |
- _recordOperatorReference(node.operator, node.bestElement); |
- return super.visitAssignmentExpression(node); |
- } |
- |
- @override |
- Object visitBinaryExpression(BinaryExpression node) { |
- _recordOperatorReference(node.operator, node.bestElement); |
- return super.visitBinaryExpression(node); |
- } |
- |
- @override |
- Object visitClassDeclaration(ClassDeclaration node) { |
- ClassElement element = node.element; |
- enterScope(element); |
- try { |
- _recordElementDefinition(element, IndexConstants.DEFINES_CLASS); |
- { |
- ExtendsClause extendsClause = node.extendsClause; |
- if (extendsClause != null) { |
- TypeName superclassNode = extendsClause.superclass; |
- _recordSuperType(superclassNode, IndexConstants.IS_EXTENDED_BY); |
- } else { |
- InterfaceType superType = element.supertype; |
- if (superType != null) { |
- ClassElement objectElement = superType.element; |
- recordRelationship(objectElement, IndexConstants.IS_EXTENDED_BY, _createLocationFromOffset(node.name.offset, 0)); |
- } |
- } |
- } |
- { |
- WithClause withClause = node.withClause; |
- if (withClause != null) { |
- for (TypeName mixinNode in withClause.mixinTypes) { |
- _recordSuperType(mixinNode, IndexConstants.IS_MIXED_IN_BY); |
- } |
- } |
- } |
- { |
- ImplementsClause implementsClause = node.implementsClause; |
- if (implementsClause != null) { |
- for (TypeName interfaceNode in implementsClause.interfaces) { |
- _recordSuperType(interfaceNode, IndexConstants.IS_IMPLEMENTED_BY); |
- } |
- } |
- } |
- return super.visitClassDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitClassTypeAlias(ClassTypeAlias node) { |
- ClassElement element = node.element; |
- enterScope(element); |
- try { |
- _recordElementDefinition(element, IndexConstants.DEFINES_CLASS_ALIAS); |
- { |
- TypeName superclassNode = node.superclass; |
- if (superclassNode != null) { |
- _recordSuperType(superclassNode, IndexConstants.IS_EXTENDED_BY); |
- } |
- } |
- { |
- WithClause withClause = node.withClause; |
- if (withClause != null) { |
- for (TypeName mixinNode in withClause.mixinTypes) { |
- _recordSuperType(mixinNode, IndexConstants.IS_MIXED_IN_BY); |
- } |
- } |
- } |
- { |
- ImplementsClause implementsClause = node.implementsClause; |
- if (implementsClause != null) { |
- for (TypeName interfaceNode in implementsClause.interfaces) { |
- _recordSuperType(interfaceNode, IndexConstants.IS_IMPLEMENTED_BY); |
- } |
- } |
- } |
- return super.visitClassTypeAlias(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitCompilationUnit(CompilationUnit node) { |
- CompilationUnitElement unitElement = node.element; |
- if (unitElement != null) { |
- _elementStack.add(unitElement); |
- _libraryElement = unitElement.enclosingElement; |
- if (_libraryElement != null) { |
- return super.visitCompilationUnit(node); |
- } |
- } |
- return null; |
- } |
- |
- @override |
- Object visitConstructorDeclaration(ConstructorDeclaration node) { |
- ConstructorElement element = node.element; |
- // define |
- { |
- Location location; |
- if (node.name != null) { |
- int start = node.period.offset; |
- int end = node.name.end; |
- location = _createLocationFromOffset(start, end - start); |
- } else { |
- int start = node.returnType.end; |
- location = _createLocationFromOffset(start, 0); |
- } |
- recordRelationship(element, IndexConstants.IS_DEFINED_BY, location); |
- } |
- // visit children |
- enterScope(element); |
- try { |
- return super.visitConstructorDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitConstructorName(ConstructorName node) { |
- ConstructorElement element = node.staticElement; |
- // in 'class B = A;' actually A constructors are invoked |
- if (element != null && element.isSynthetic && element.redirectedConstructor != null) { |
- element = element.redirectedConstructor; |
- } |
- // prepare location |
- Location location; |
- if (node.name != null) { |
- int start = node.period.offset; |
- int end = node.name.end; |
- location = _createLocationFromOffset(start, end - start); |
- } else { |
- int start = node.type.end; |
- location = _createLocationFromOffset(start, 0); |
- } |
- // record relationship |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- return super.visitConstructorName(node); |
- } |
- |
- @override |
- Object visitExportDirective(ExportDirective node) { |
- ExportElement element = node.element; |
- if (element != null) { |
- LibraryElement expLibrary = element.exportedLibrary; |
- _recordLibraryReference(node, expLibrary); |
- } |
- return super.visitExportDirective(node); |
- } |
- |
- @override |
- Object visitFormalParameter(FormalParameter node) { |
- ParameterElement element = node.element; |
- enterScope(element); |
- try { |
- return super.visitFormalParameter(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitFunctionDeclaration(FunctionDeclaration node) { |
- Element element = node.element; |
- _recordElementDefinition(element, IndexConstants.DEFINES_FUNCTION); |
- enterScope(element); |
- try { |
- return super.visitFunctionDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
- Element element = node.element; |
- _recordElementDefinition(element, IndexConstants.DEFINES_FUNCTION_TYPE); |
- return super.visitFunctionTypeAlias(node); |
- } |
- |
- @override |
- Object visitImportDirective(ImportDirective node) { |
- ImportElement element = node.element; |
- if (element != null) { |
- LibraryElement impLibrary = element.importedLibrary; |
- _recordLibraryReference(node, impLibrary); |
- } |
- return super.visitImportDirective(node); |
- } |
- |
- @override |
- Object visitIndexExpression(IndexExpression node) { |
- MethodElement element = node.bestElement; |
- if (element is MethodElement) { |
- Token operator = node.leftBracket; |
- Location location = _createLocationFromToken(operator); |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, location); |
- } |
- return super.visitIndexExpression(node); |
- } |
- |
- @override |
- Object visitMethodDeclaration(MethodDeclaration node) { |
- ExecutableElement element = node.element; |
- enterScope(element); |
- try { |
- return super.visitMethodDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitMethodInvocation(MethodInvocation node) { |
- SimpleIdentifier name = node.methodName; |
- Element element = name.bestElement; |
- if (element is MethodElement || element is PropertyAccessorElement) { |
- Location location = _createLocationFromNode(name); |
- Relationship relationship; |
- if (node.target != null) { |
- relationship = IndexConstants.IS_INVOKED_BY_QUALIFIED; |
- } else { |
- relationship = IndexConstants.IS_INVOKED_BY_UNQUALIFIED; |
- } |
- recordRelationship(element, relationship, location); |
- } |
- if (element is FunctionElement || element is VariableElement) { |
- Location location = _createLocationFromNode(name); |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY, location); |
- } |
- // name invocation |
- { |
- Element nameElement = new NameElementImpl(name.name); |
- Location location = _createLocationFromNode(name); |
- Relationship kind = element != null ? IndexConstants.NAME_IS_INVOKED_BY_RESOLVED : IndexConstants.NAME_IS_INVOKED_BY_UNRESOLVED; |
- _store.recordRelationship(nameElement, kind, location); |
- } |
- _recordImportElementReferenceWithoutPrefix(name); |
- return super.visitMethodInvocation(node); |
- } |
- |
- @override |
- Object visitPartDirective(PartDirective node) { |
- Element element = node.element; |
- Location location = _createLocationFromNode(node.uri); |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- return super.visitPartDirective(node); |
- } |
- |
- @override |
- Object visitPartOfDirective(PartOfDirective node) { |
- Location location = _createLocationFromNode(node.libraryName); |
- recordRelationship(node.element, IndexConstants.IS_REFERENCED_BY, location); |
- return null; |
- } |
- |
- @override |
- Object visitPostfixExpression(PostfixExpression node) { |
- _recordOperatorReference(node.operator, node.bestElement); |
- return super.visitPostfixExpression(node); |
- } |
- |
- @override |
- Object visitPrefixExpression(PrefixExpression node) { |
- _recordOperatorReference(node.operator, node.bestElement); |
- return super.visitPrefixExpression(node); |
- } |
- |
- @override |
- Object visitSimpleIdentifier(SimpleIdentifier node) { |
- Element nameElement = new NameElementImpl(node.name); |
- Location location = _createLocationFromNode(node); |
- // name in declaration |
- if (node.inDeclarationContext()) { |
- recordRelationship(nameElement, IndexConstants.IS_DEFINED_BY, location); |
- return null; |
- } |
- // prepare information |
- Element element = node.bestElement; |
- // qualified name reference |
- _recordQualifiedMemberReference(node, element, nameElement, location); |
- // stop if already handled |
- if (_isAlreadyHandledName(node)) { |
- return null; |
- } |
- // record name read/write |
- { |
- bool inGetterContext = node.inGetterContext(); |
- bool inSetterContext = node.inSetterContext(); |
- if (inGetterContext && inSetterContext) { |
- Relationship kind = element != null ? IndexConstants.NAME_IS_READ_WRITTEN_BY_RESOLVED : IndexConstants.NAME_IS_READ_WRITTEN_BY_UNRESOLVED; |
- _store.recordRelationship(nameElement, kind, location); |
- } else if (inGetterContext) { |
- Relationship kind = element != null ? IndexConstants.NAME_IS_READ_BY_RESOLVED : IndexConstants.NAME_IS_READ_BY_UNRESOLVED; |
- _store.recordRelationship(nameElement, kind, location); |
- } else if (inSetterContext) { |
- Relationship kind = element != null ? IndexConstants.NAME_IS_WRITTEN_BY_RESOLVED : IndexConstants.NAME_IS_WRITTEN_BY_UNRESOLVED; |
- _store.recordRelationship(nameElement, kind, location); |
- } |
- } |
- // record specific relations |
- if (element is ClassElement || element is FunctionElement || element is FunctionTypeAliasElement || element is LabelElement || element is TypeParameterElement) { |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- } else if (element is FieldElement) { |
- location = _getLocationWithInitializerType(node, location); |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- } else if (element is FieldFormalParameterElement) { |
- FieldFormalParameterElement fieldParameter = element; |
- FieldElement field = fieldParameter.field; |
- recordRelationship(field, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location); |
- } else if (element is PrefixElement) { |
- _recordImportElementReferenceWithPrefix(node); |
- } else if (element is PropertyAccessorElement || element is MethodElement) { |
- location = _getLocationWithTypeAssignedToField(node, element, location); |
- if (node.isQualified) { |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY_QUALIFIED, location); |
- } else { |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, location); |
- } |
- } else if (element is ParameterElement || element is LocalVariableElement) { |
- bool inGetterContext = node.inGetterContext(); |
- bool inSetterContext = node.inSetterContext(); |
- if (inGetterContext && inSetterContext) { |
- recordRelationship(element, IndexConstants.IS_READ_WRITTEN_BY, location); |
- } else if (inGetterContext) { |
- recordRelationship(element, IndexConstants.IS_READ_BY, location); |
- } else if (inSetterContext) { |
- recordRelationship(element, IndexConstants.IS_WRITTEN_BY, location); |
- } else { |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- } |
- } |
- _recordImportElementReferenceWithoutPrefix(node); |
- return super.visitSimpleIdentifier(node); |
- } |
- |
- @override |
- Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
- ConstructorElement element = node.staticElement; |
- Location location; |
- if (node.constructorName != null) { |
- int start = node.period.offset; |
- int end = node.constructorName.end; |
- location = _createLocationFromOffset(start, end - start); |
- } else { |
- int start = node.keyword.end; |
- location = _createLocationFromOffset(start, 0); |
- } |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- return super.visitSuperConstructorInvocation(node); |
- } |
- |
- @override |
- Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
- VariableDeclarationList variables = node.variables; |
- for (VariableDeclaration variableDeclaration in variables.variables) { |
- Element element = variableDeclaration.element; |
- _recordElementDefinition(element, IndexConstants.DEFINES_VARIABLE); |
- } |
- return super.visitTopLevelVariableDeclaration(node); |
- } |
- |
- @override |
- Object visitTypeParameter(TypeParameter node) { |
- TypeParameterElement element = node.element; |
- enterScope(element); |
- try { |
- return super.visitTypeParameter(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitVariableDeclaration(VariableDeclaration node) { |
- VariableElement element = node.element; |
- // record declaration |
- { |
- SimpleIdentifier name = node.name; |
- Location location = _createLocationFromNode(name); |
- location = _getLocationWithExpressionType(location, node.initializer); |
- recordRelationship(element, IndexConstants.IS_DEFINED_BY, location); |
- } |
- // visit |
- enterScope(element); |
- try { |
- return super.visitVariableDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitVariableDeclarationList(VariableDeclarationList node) { |
- NodeList<VariableDeclaration> variables = node.variables; |
- if (variables != null) { |
- // use first VariableDeclaration as Element for Location(s) in type |
- { |
- TypeName type = node.type; |
- if (type != null) { |
- for (VariableDeclaration variableDeclaration in variables) { |
- enterScope(variableDeclaration.element); |
- try { |
- type.accept(this); |
- } finally { |
- _exitScope(); |
- } |
- // only one iteration |
- break; |
- } |
- } |
- } |
- // visit variables |
- variables.accept(this); |
- } |
- return null; |
- } |
- |
- /** |
- * Record the given relationship between the given [Element] and [Location]. |
- */ |
- void recordRelationship(Element element, Relationship relationship, Location location) { |
- if (element != null && location != null) { |
- _store.recordRelationship(element, relationship, location); |
- } |
- } |
- |
- /** |
- * @return the [Location] representing location of the [AstNode]. |
- */ |
- Location _createLocationFromNode(AstNode node) => _createLocationFromOffset(node.offset, node.length); |
- |
- /** |
- * @param offset the offset of the location within [Source] |
- * @param length the length of the location |
- * @return the [Location] representing the given offset and length within the inner-most |
- * [Element]. |
- */ |
- Location _createLocationFromOffset(int offset, int length) { |
- Element element = peekElement(); |
- return new Location(element, offset, length); |
- } |
- |
- /** |
- * @return the [Location] representing location of the [Token]. |
- */ |
- Location _createLocationFromToken(Token token) => _createLocationFromOffset(token.offset, token.length); |
- |
- /** |
- * Exit the current scope. |
- */ |
- void _exitScope() { |
- _elementStack.removeFirst(); |
- } |
- |
- /** |
- * @return `true` if given node already indexed as more interesting reference, so it should |
- * not be indexed again. |
- */ |
- bool _isAlreadyHandledName(SimpleIdentifier node) { |
- AstNode parent = node.parent; |
- if (parent is MethodInvocation) { |
- return identical(parent.methodName, node); |
- } |
- return false; |
- } |
- |
- /** |
- * Records the [Element] definition in the library and universe. |
- */ |
- void _recordElementDefinition(Element element, Relationship relationship) { |
- Location location = createLocation(element); |
- recordRelationship(_libraryElement, relationship, location); |
- recordRelationship(IndexConstants.UNIVERSE, relationship, location); |
- } |
- |
- /** |
- * Records [ImportElement] reference if given [SimpleIdentifier] references some |
- * top-level element and not qualified with import prefix. |
- */ |
- void _recordImportElementReferenceWithoutPrefix(SimpleIdentifier node) { |
- if (_isIdentifierInImportCombinator(node)) { |
- return; |
- } |
- if (_isIdentifierInPrefixedIdentifier(node)) { |
- return; |
- } |
- Element element = node.staticElement; |
- ImportElement importElement = _internalGetImportElement(_libraryElement, null, element, _importElementsMap); |
- if (importElement != null) { |
- Location location = _createLocationFromOffset(node.offset, 0); |
- recordRelationship(importElement, IndexConstants.IS_REFERENCED_BY, location); |
- } |
- } |
- |
- /** |
- * Records [ImportElement] that declares given prefix and imports library with element used |
- * with given prefix node. |
- */ |
- void _recordImportElementReferenceWithPrefix(SimpleIdentifier prefixNode) { |
- IndexContributor_ImportElementInfo info = getImportElementInfo(prefixNode); |
- if (info != null) { |
- int offset = prefixNode.offset; |
- int length = info._periodEnd - offset; |
- Location location = _createLocationFromOffset(offset, length); |
- recordRelationship(info._element, IndexConstants.IS_REFERENCED_BY, location); |
- } |
- } |
- |
- /** |
- * Records reference to defining [CompilationUnitElement] of the given |
- * [LibraryElement]. |
- */ |
- void _recordLibraryReference(UriBasedDirective node, LibraryElement library) { |
- if (library != null) { |
- Location location = _createLocationFromNode(node.uri); |
- recordRelationship(library.definingCompilationUnit, IndexConstants.IS_REFERENCED_BY, location); |
- } |
- } |
- |
- /** |
- * Record reference to the given operator [Element] and name. |
- */ |
- void _recordOperatorReference(Token operator, Element element) { |
- // prepare location |
- Location location = _createLocationFromToken(operator); |
- // record name reference |
- { |
- String name = operator.lexeme; |
- if (name == "++") { |
- name = "+"; |
- } |
- if (name == "--") { |
- name = "-"; |
- } |
- if (StringUtilities.endsWithChar(name, 0x3D) && name != "==") { |
- name = name.substring(0, name.length - 1); |
- } |
- Element nameElement = new NameElementImpl(name); |
- Relationship relationship = element != null ? IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED : IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED; |
- recordRelationship(nameElement, relationship, location); |
- } |
- // record element reference |
- if (element != null) { |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY_QUALIFIED, location); |
- } |
- } |
- |
- /** |
- * Records reference if the given [SimpleIdentifier] looks like a qualified property access |
- * or method invocation. |
- */ |
- void _recordQualifiedMemberReference(SimpleIdentifier node, Element element, Element nameElement, Location location) { |
- if (node.isQualified) { |
- Relationship relationship = element != null ? IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED : IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED; |
- recordRelationship(nameElement, relationship, location); |
- } |
- } |
- |
- /** |
- * Records extends/implements relationships between given [ClassElement] and [Type] of |
- * "superNode". |
- */ |
- void _recordSuperType(TypeName superNode, Relationship relationship) { |
- if (superNode != null) { |
- Identifier superName = superNode.name; |
- if (superName != null) { |
- Element superElement = superName.staticElement; |
- recordRelationship(superElement, relationship, _createLocationFromNode(superNode)); |
- } |
- } |
- } |
-} |
- |
-class IndexContributor_AngularHtmlIndexContributor extends IndexContributor { |
- final AngularHtmlIndexContributor AngularHtmlIndexContributor_this; |
- |
- IndexContributor_AngularHtmlIndexContributor(IndexStore arg0, this.AngularHtmlIndexContributor_this) : super(arg0); |
- |
- @override |
- Element peekElement() => AngularHtmlIndexContributor_this._htmlUnitElement; |
- |
- @override |
- void recordRelationship(Element element, Relationship relationship, Location location) { |
- AngularElement angularElement = AngularHtmlUnitResolver.getAngularElement(element); |
- if (angularElement != null) { |
- element = angularElement; |
- relationship = IndexConstants.ANGULAR_REFERENCE; |
- } |
- super.recordRelationship(element, relationship, location); |
- } |
-} |
- |
-/** |
- * Information about [ImportElement] and place where it is referenced using |
- * [PrefixElement]. |
- */ |
-class IndexContributor_ImportElementInfo { |
- ImportElement _element; |
- |
- int _periodEnd = 0; |
-} |
- |
-/** |
- * Instances of the [IndexHtmlUnitOperation] implement an operation that adds data to the |
- * index based on the resolved [HtmlUnit]. |
- */ |
-class IndexHtmlUnitOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- /** |
- * The context in which [HtmlUnit] was resolved. |
- */ |
- final AnalysisContext _context; |
- |
- /** |
- * The [HtmlUnit] being indexed. |
- */ |
- final ht.HtmlUnit unit; |
- |
- /** |
- * The element of the [HtmlUnit] being indexed. |
- */ |
- HtmlElement _htmlElement; |
- |
- /** |
- * The source being indexed. |
- */ |
- Source _source; |
- |
- /** |
- * Initialize a newly created operation that will index the specified [HtmlUnit]. |
- * |
- * @param indexStore the index store against which this operation is being run |
- * @param context the context in which [HtmlUnit] was resolved |
- * @param unit the fully resolved [HtmlUnit] |
- */ |
- IndexHtmlUnitOperation(this._indexStore, this._context, this.unit) { |
- this._htmlElement = unit.element; |
- this._source = _htmlElement.source; |
- } |
- |
- /** |
- * @return the [Source] to be indexed. |
- */ |
- Source get source => _source; |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- try { |
- bool mayIndex = _indexStore.aboutToIndexHtml(_context, _htmlElement); |
- if (!mayIndex) { |
- return; |
- } |
- AngularHtmlIndexContributor contributor = new AngularHtmlIndexContributor(_indexStore); |
- unit.accept(contributor); |
- _indexStore.doneIndex(); |
- } catch (exception) { |
- AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.location}", exception); |
- } |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => this._source == source; |
- |
- @override |
- String toString() => "IndexHtmlUnitOperation(${_source.fullName})"; |
-} |
- |
-/** |
- * The interface [IndexOperation] defines the behavior of objects used to perform operations |
- * on an index. |
- */ |
-abstract class IndexOperation { |
- /** |
- * Return `true` if this operation returns information from the index. |
- * |
- * @return `true` if this operation returns information from the index |
- */ |
- bool get isQuery; |
- |
- /** |
- * Perform the operation implemented by this operation. |
- */ |
- void performOperation(); |
- |
- /** |
- * Return `true` if this operation should be removed from the operation queue when the |
- * given resource has been removed. |
- * |
- * @param source the [Source] that has been removed |
- * @return `true` if this operation should be removed from the operation queue as a |
- * result of removing the resource |
- */ |
- bool removeWhenSourceRemoved(Source source); |
-} |
- |
-/** |
- * Container of information computed by the index - relationships between elements. |
- */ |
-abstract class IndexStore { |
- /** |
- * Notifies the index store that we are going to index the unit with the given element. |
- * |
- * If the unit is a part of a library, then all its locations are removed. If it is a defining |
- * compilation unit of a library, then index store also checks if some previously indexed parts of |
- * the library are not parts of the library anymore, and clears their information. |
- * |
- * @param the [AnalysisContext] in which unit being indexed |
- * @param unitElement the element of the unit being indexed |
- * @return `true` the given [AnalysisContext] is active, or `false` if it was |
- * removed before, so no any unit may be indexed with it |
- */ |
- bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement); |
- |
- /** |
- * Notifies the index store that we are going to index the given [HtmlElement]. |
- * |
- * @param the [AnalysisContext] in which unit being indexed |
- * @param htmlElement the [HtmlElement] being indexed |
- * @return `true` the given [AnalysisContext] is active, or `false` if it was |
- * removed before, so no any unit may be indexed with it |
- */ |
- bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement); |
- |
- /** |
- * Removes all of the information. |
- */ |
- void clear(); |
- |
- /** |
- * Notifies that index store that the current Dart or HTML unit indexing is done. |
- * |
- * If this method is not invoked after corresponding "aboutToIndex*" invocation, all recorded |
- * information may be lost. |
- */ |
- void doneIndex(); |
- |
- /** |
- * Return the locations of the elements that have the given relationship with the given element. |
- * For example, if the element represents a method and the relationship is the is-referenced-by |
- * relationship, then the returned locations will be all of the places where the method is |
- * invoked. |
- * |
- * @param element the the element that has the relationship with the locations to be returned |
- * @param relationship the [Relationship] between the given element and the locations to be |
- * returned |
- * @return the locations that have the given relationship with the given element |
- */ |
- List<Location> getRelationships(Element element, Relationship relationship); |
- |
- /** |
- * Answer index statistics. |
- */ |
- String get statistics; |
- |
- /** |
- * Record that the given element and location have the given relationship. For example, if the |
- * relationship is the is-referenced-by relationship, then the element would be the element being |
- * referenced and the location would be the point at which it is referenced. Each element can have |
- * the same relationship with multiple locations. In other words, if the following code were |
- * executed |
- * |
- * <pre> |
- * recordRelationship(element, isReferencedBy, location1); |
- * recordRelationship(element, isReferencedBy, location2); |
- * </pre> |
- * |
- * then both relationships would be maintained in the index and the result of executing |
- * |
- * <pre> |
- * getRelationship(element, isReferencedBy); |
- * </pre> |
- * |
- * would be an array containing both <code>location1</code> and <code>location2</code>. |
- * |
- * @param element the element that is related to the location |
- * @param relationship the [Relationship] between the element and the location |
- * @param location the [Location] where relationship happens |
- */ |
- void recordRelationship(Element element, Relationship relationship, Location location); |
- |
- /** |
- * Remove from the index all of the information associated with [AnalysisContext]. |
- * |
- * This method should be invoked when a context is disposed. |
- * |
- * @param the [AnalysisContext] being removed |
- */ |
- void removeContext(AnalysisContext context); |
- |
- /** |
- * Remove from the index all of the information associated with elements or locations in the given |
- * source. This includes relationships between an element in the given source and any other |
- * locations, relationships between any other elements and a location within the given source. |
- * |
- * This method should be invoked when a source is no longer part of the code base. |
- * |
- * @param the [AnalysisContext] in which [Source] being removed |
- * @param source the source being removed |
- */ |
- void removeSource(AnalysisContext context, Source source); |
- |
- /** |
- * Remove from the index all of the information associated with elements or locations in the given |
- * sources. This includes relationships between an element in the given sources and any other |
- * locations, relationships between any other elements and a location within the given sources. |
- * |
- * This method should be invoked when multiple sources are no longer part of the code base. |
- * |
- * @param the [AnalysisContext] in which [Source]s being removed |
- * @param container the [SourceContainer] holding the sources being removed |
- */ |
- void removeSources(AnalysisContext context, SourceContainer container); |
-} |
- |
-/** |
- * Instances of the [IndexUnitOperation] implement an operation that adds data to the index |
- * based on the resolved [CompilationUnit]. |
- */ |
-class IndexUnitOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- /** |
- * The context in which compilation unit was resolved. |
- */ |
- final AnalysisContext _context; |
- |
- /** |
- * The compilation unit being indexed. |
- */ |
- final CompilationUnit unit; |
- |
- /** |
- * The element of the compilation unit being indexed. |
- */ |
- CompilationUnitElement _unitElement; |
- |
- /** |
- * The source being indexed. |
- */ |
- Source _source; |
- |
- /** |
- * Initialize a newly created operation that will index the specified unit. |
- * |
- * @param indexStore the index store against which this operation is being run |
- * @param context the context in which compilation unit was resolved |
- * @param unit the fully resolved AST structure |
- */ |
- IndexUnitOperation(this._indexStore, this._context, this.unit) { |
- this._unitElement = unit.element; |
- this._source = _unitElement.source; |
- } |
- |
- /** |
- * @return the [Source] to be indexed. |
- */ |
- Source get source => _source; |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- try { |
- bool mayIndex = _indexStore.aboutToIndexDart(_context, _unitElement); |
- if (!mayIndex) { |
- return; |
- } |
- unit.accept(new IndexContributor(_indexStore)); |
- unit.accept(new AngularDartIndexContributor(_indexStore)); |
- _indexStore.doneIndex(); |
- } catch (exception) { |
- AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.location}", exception); |
- } |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => this._source == source; |
- |
- @override |
- String toString() => "IndexUnitOperation(${_source.fullName})"; |
-} |
- |
-/** |
- * Instances of the class <code>Location</code> represent a location related to an element. The |
- * location is expressed as an offset and length, but the offset is relative to the resource |
- * containing the element rather than the start of the element within that resource. |
- */ |
-class Location { |
- /** |
- * An empty array of locations. |
- */ |
- static List<Location> EMPTY_ARRAY = new List<Location>(0); |
- |
- /** |
- * The element containing this location. |
- */ |
- final Element element; |
- |
- /** |
- * The offset of this location within the resource containing the element. |
- */ |
- final int offset; |
- |
- /** |
- * The length of this location. |
- */ |
- final int length; |
- |
- /** |
- * Internal field used to hold a key that is referenced at this location. |
- */ |
- Object internalKey; |
- |
- /** |
- * Initialize a newly create location to be relative to the given element at the given offset with |
- * the given length. |
- * |
- * @param element the [Element] containing this location |
- * @param offset the offset of this location within the resource containing the element |
- * @param length the length of this location |
- */ |
- Location(this.element, this.offset, this.length) { |
- if (element == null) { |
- throw new IllegalArgumentException("element location cannot be null"); |
- } |
- } |
- |
- /** |
- * Returns a clone of this [Location]. |
- */ |
- Location newClone() => new Location(element, offset, length); |
- |
- @override |
- String toString() => "[${offset} - ${(offset + length)}) in ${element}"; |
-} |
- |
-/** |
- * [Location] with attached data. |
- */ |
-class LocationWithData<D> extends Location { |
- final D data; |
- |
- LocationWithData.con1(Location location, this.data) : super(location.element, location.offset, location.length); |
- |
- LocationWithData.con2(Element element, int offset, int length, this.data) : super(element, offset, length); |
- |
- @override |
- Location newClone() => new LocationWithData<D>.con2(element, offset, length, data); |
-} |
- |
-/** |
- * [IndexStore] which keeps all information in memory, but can write it to stream and read |
- * later. |
- */ |
-abstract class MemoryIndexStore implements IndexStore { |
-} |
- |
-/** |
- * [IndexStore] which keeps full index in memory. |
- */ |
-class MemoryIndexStoreImpl implements MemoryIndexStore { |
- /** |
- * When logging is on, [AnalysisEngine] actually creates |
- * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used to create |
- * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisContextImpl] |
- * when perform any operation. |
- */ |
- static AnalysisContext unwrapContext(AnalysisContext context) { |
- if (context is InstrumentedAnalysisContextImpl) { |
- context = (context as InstrumentedAnalysisContextImpl).basis; |
- } |
- return context; |
- } |
- |
- /** |
- * @return the [Source] of the enclosing [LibraryElement], may be `null`. |
- */ |
- static Source _getLibrarySourceOrNull(Element element) { |
- LibraryElement library = element.library; |
- if (library == null) { |
- return null; |
- } |
- if (library.isAngularHtml) { |
- return null; |
- } |
- return library.source; |
- } |
- |
- /** |
- * This map is used to canonicalize equal keys. |
- */ |
- Map<MemoryIndexStoreImpl_ElementRelationKey, MemoryIndexStoreImpl_ElementRelationKey> _canonicalKeys = {}; |
- |
- /** |
- * The mapping of [ElementRelationKey] to the [Location]s, one-to-many. |
- */ |
- Map<MemoryIndexStoreImpl_ElementRelationKey, Set<Location>> _keyToLocations = {}; |
- |
- /** |
- * The mapping of [Source] to the [ElementRelationKey]s. It is used in |
- * [removeSource] to identify keys to remove from |
- * [keyToLocations]. |
- */ |
- Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>>> _contextToSourceToKeys = {}; |
- |
- /** |
- * The mapping of [Source] to the [Location]s existing in it. It is used in |
- * [clearSource0] to identify locations to remove from |
- * [keyToLocations]. |
- */ |
- Map<AnalysisContext, Map<MemoryIndexStoreImpl_Source2, List<Location>>> _contextToSourceToLocations = {}; |
- |
- /** |
- * The mapping of library [Source] to the [Source]s of part units. |
- */ |
- Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits = {}; |
- |
- /** |
- * The mapping of unit [Source] to the [Source]s of libraries it is used in. |
- */ |
- Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries = {}; |
- |
- int _sourceCount = 0; |
- |
- int _keyCount = 0; |
- |
- int _locationCount = 0; |
- |
- @override |
- bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElement) { |
- context = unwrapContext(context); |
- // may be already disposed in other thread |
- if (context.isDisposed) { |
- return false; |
- } |
- // validate unit |
- if (unitElement == null) { |
- return false; |
- } |
- LibraryElement libraryElement = unitElement.library; |
- if (libraryElement == null) { |
- return false; |
- } |
- CompilationUnitElement definingUnitElement = libraryElement.definingCompilationUnit; |
- if (definingUnitElement == null) { |
- return false; |
- } |
- // prepare sources |
- Source library = definingUnitElement.source; |
- Source unit = unitElement.source; |
- // special handling for the defining library unit |
- if (unit == library) { |
- // prepare new parts |
- Set<Source> newParts = new Set(); |
- for (CompilationUnitElement part in libraryElement.parts) { |
- newParts.add(part.source); |
- } |
- // prepare old parts |
- Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context]; |
- if (libraryToUnits == null) { |
- libraryToUnits = {}; |
- _contextToLibraryToUnits[context] = libraryToUnits; |
- } |
- Set<Source> oldParts = libraryToUnits[library]; |
- // check if some parts are not in the library now |
- if (oldParts != null) { |
- Set<Source> noParts = oldParts.difference(newParts); |
- for (Source noPart in noParts) { |
- _removeLocations(context, library, noPart); |
- } |
- } |
- // remember new parts |
- libraryToUnits[library] = newParts; |
- } |
- // remember libraries in which unit is used |
- _recordUnitInLibrary(context, library, unit); |
- // remove locations |
- _removeLocations(context, library, unit); |
- // remove keys |
- { |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context]; |
- if (sourceToKeys != null) { |
- MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit); |
- bool hadSource = sourceToKeys.remove(source2) != null; |
- if (hadSource) { |
- _sourceCount--; |
- } |
- } |
- } |
- // OK, we can index |
- return true; |
- } |
- |
- @override |
- bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement) { |
- context = unwrapContext(context); |
- // may be already disposed in other thread |
- if (context.isDisposed) { |
- return false; |
- } |
- // remove locations |
- Source source = htmlElement.source; |
- _removeLocations(context, null, source); |
- // remove keys |
- { |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context]; |
- if (sourceToKeys != null) { |
- MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(null, source); |
- bool hadSource = sourceToKeys.remove(source2) != null; |
- if (hadSource) { |
- _sourceCount--; |
- } |
- } |
- } |
- // remember libraries in which unit is used |
- _recordUnitInLibrary(context, null, source); |
- // OK, we can index |
- return true; |
- } |
- |
- @override |
- void clear() { |
- _canonicalKeys.clear(); |
- _keyToLocations.clear(); |
- _contextToSourceToKeys.clear(); |
- _contextToSourceToLocations.clear(); |
- _contextToLibraryToUnits.clear(); |
- _contextToUnitToLibraries.clear(); |
- } |
- |
- @override |
- void doneIndex() { |
- } |
- |
- @override |
- List<Location> getRelationships(Element element, Relationship relationship) { |
- MemoryIndexStoreImpl_ElementRelationKey key = new MemoryIndexStoreImpl_ElementRelationKey(element, relationship); |
- Set<Location> locations = _keyToLocations[key]; |
- if (locations != null) { |
- return new List.from(locations); |
- } |
- return Location.EMPTY_ARRAY; |
- } |
- |
- @override |
- String get statistics => "${_locationCount} relationships in ${_keyCount} keys in ${_sourceCount} sources"; |
- |
- int internalGetKeyCount() => _keyToLocations.length; |
- |
- int internalGetLocationCount() { |
- int count = 0; |
- for (Set<Location> locations in _keyToLocations.values) { |
- count += locations.length; |
- } |
- return count; |
- } |
- |
- int internalGetLocationCountForContext(AnalysisContext context) { |
- context = unwrapContext(context); |
- int count = 0; |
- for (Set<Location> locations in _keyToLocations.values) { |
- for (Location location in locations) { |
- if (identical(location.element.context, context)) { |
- count++; |
- } |
- } |
- } |
- return count; |
- } |
- |
- int internalGetSourceKeyCount(AnalysisContext context) { |
- int count = 0; |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context]; |
- if (sourceToKeys != null) { |
- for (Set<MemoryIndexStoreImpl_ElementRelationKey> keys in sourceToKeys.values) { |
- count += keys.length; |
- } |
- } |
- return count; |
- } |
- |
- @override |
- void recordRelationship(Element element, Relationship relationship, Location location) { |
- if (element == null || location == null) { |
- return; |
- } |
- location = location.newClone(); |
- // at the index level we don't care about Member(s) |
- if (element is Member) { |
- element = (element as Member).baseElement; |
- } |
- // System.out.println(element + " " + relationship + " " + location); |
- // prepare information |
- AnalysisContext elementContext = element.context; |
- AnalysisContext locationContext = location.element.context; |
- Source elementSource = element.source; |
- Source locationSource = location.element.source; |
- Source elementLibrarySource = _getLibrarySourceOrNull(element); |
- Source locationLibrarySource = _getLibrarySourceOrNull(location.element); |
- // sanity check |
- if (locationContext == null) { |
- return; |
- } |
- if (locationSource == null) { |
- return; |
- } |
- if (elementContext == null && element is! NameElementImpl && element is! UniverseElementImpl) { |
- return; |
- } |
- if (elementSource == null && element is! NameElementImpl && element is! UniverseElementImpl) { |
- return; |
- } |
- // may be already disposed in other thread |
- if (elementContext != null && elementContext.isDisposed) { |
- return; |
- } |
- if (locationContext.isDisposed) { |
- return; |
- } |
- // record: key -> location(s) |
- MemoryIndexStoreImpl_ElementRelationKey key = _getCanonicalKey(element, relationship); |
- { |
- Set<Location> locations = _keyToLocations.remove(key); |
- if (locations == null) { |
- locations = _createLocationIdentitySet(); |
- } else { |
- _keyCount--; |
- } |
- _keyToLocations[key] = locations; |
- _keyCount++; |
- locations.add(location); |
- _locationCount++; |
- } |
- // record: location -> key |
- location.internalKey = key; |
- // prepare source pairs |
- MemoryIndexStoreImpl_Source2 elementSource2 = new MemoryIndexStoreImpl_Source2(elementLibrarySource, elementSource); |
- MemoryIndexStoreImpl_Source2 locationSource2 = new MemoryIndexStoreImpl_Source2(locationLibrarySource, locationSource); |
- // record: element source -> keys |
- { |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[elementContext]; |
- if (sourceToKeys == null) { |
- sourceToKeys = {}; |
- _contextToSourceToKeys[elementContext] = sourceToKeys; |
- } |
- Set<MemoryIndexStoreImpl_ElementRelationKey> keys = sourceToKeys[elementSource2]; |
- if (keys == null) { |
- keys = new Set(); |
- sourceToKeys[elementSource2] = keys; |
- _sourceCount++; |
- } |
- keys.remove(key); |
- keys.add(key); |
- } |
- // record: location source -> locations |
- { |
- Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[locationContext]; |
- if (sourceToLocations == null) { |
- sourceToLocations = {}; |
- _contextToSourceToLocations[locationContext] = sourceToLocations; |
- } |
- List<Location> locations = sourceToLocations[locationSource2]; |
- if (locations == null) { |
- locations = []; |
- sourceToLocations[locationSource2] = locations; |
- } |
- locations.add(location); |
- } |
- } |
- |
- @override |
- void removeContext(AnalysisContext context) { |
- context = unwrapContext(context); |
- if (context == null) { |
- return; |
- } |
- // remove sources |
- removeSources(context, null); |
- // remove context |
- _contextToSourceToKeys.remove(context); |
- _contextToSourceToLocations.remove(context); |
- _contextToLibraryToUnits.remove(context); |
- _contextToUnitToLibraries.remove(context); |
- } |
- |
- @override |
- void removeSource(AnalysisContext context, Source unit) { |
- context = unwrapContext(context); |
- if (context == null) { |
- return; |
- } |
- // remove locations defined in source |
- Map<Source, Set<Source>> unitToLibraries = _contextToUnitToLibraries[context]; |
- if (unitToLibraries != null) { |
- Set<Source> libraries = unitToLibraries.remove(unit); |
- if (libraries != null) { |
- for (Source library in libraries) { |
- MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit); |
- // remove locations defined in source |
- _removeLocations(context, library, unit); |
- // remove keys for elements defined in source |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context]; |
- if (sourceToKeys != null) { |
- Set<MemoryIndexStoreImpl_ElementRelationKey> keys = sourceToKeys.remove(source2); |
- if (keys != null) { |
- for (MemoryIndexStoreImpl_ElementRelationKey key in keys) { |
- _canonicalKeys.remove(key); |
- Set<Location> locations = _keyToLocations.remove(key); |
- if (locations != null) { |
- _keyCount--; |
- _locationCount -= locations.length; |
- } |
- } |
- _sourceCount--; |
- } |
- } |
- } |
- } |
- } |
- } |
- |
- @override |
- void removeSources(AnalysisContext context, SourceContainer container) { |
- context = unwrapContext(context); |
- if (context == null) { |
- return; |
- } |
- // remove sources #1 |
- Map<MemoryIndexStoreImpl_Source2, Set<MemoryIndexStoreImpl_ElementRelationKey>> sourceToKeys = _contextToSourceToKeys[context]; |
- if (sourceToKeys != null) { |
- List<MemoryIndexStoreImpl_Source2> sources = []; |
- for (MemoryIndexStoreImpl_Source2 source2 in sources) { |
- Source source = source2._unitSource; |
- if (container == null || container.contains(source)) { |
- removeSource(context, source); |
- } |
- } |
- } |
- // remove sources #2 |
- Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[context]; |
- if (sourceToLocations != null) { |
- List<MemoryIndexStoreImpl_Source2> sources = []; |
- for (MemoryIndexStoreImpl_Source2 source2 in sources) { |
- Source source = source2._unitSource; |
- if (container == null || container.contains(source)) { |
- removeSource(context, source); |
- } |
- } |
- } |
- } |
- |
- /** |
- * Creates new [Set] that uses object identity instead of equals. |
- */ |
- Set<Location> _createLocationIdentitySet() => new Set<Location>.identity(); |
- |
- /** |
- * @return the canonical [ElementRelationKey] for given [Element] and |
- * [Relationship], i.e. unique instance for this combination. |
- */ |
- MemoryIndexStoreImpl_ElementRelationKey _getCanonicalKey(Element element, Relationship relationship) { |
- MemoryIndexStoreImpl_ElementRelationKey key = new MemoryIndexStoreImpl_ElementRelationKey(element, relationship); |
- MemoryIndexStoreImpl_ElementRelationKey canonicalKey = _canonicalKeys[key]; |
- if (canonicalKey == null) { |
- canonicalKey = key; |
- _canonicalKeys[key] = canonicalKey; |
- } |
- return canonicalKey; |
- } |
- |
- void _recordUnitInLibrary(AnalysisContext context, Source library, Source unit) { |
- Map<Source, Set<Source>> unitToLibraries = _contextToUnitToLibraries[context]; |
- if (unitToLibraries == null) { |
- unitToLibraries = {}; |
- _contextToUnitToLibraries[context] = unitToLibraries; |
- } |
- Set<Source> libraries = unitToLibraries[unit]; |
- if (libraries == null) { |
- libraries = new Set(); |
- unitToLibraries[unit] = libraries; |
- } |
- libraries.add(library); |
- } |
- |
- /** |
- * Removes locations recorded in the given library/unit pair. |
- */ |
- void _removeLocations(AnalysisContext context, Source library, Source unit) { |
- MemoryIndexStoreImpl_Source2 source2 = new MemoryIndexStoreImpl_Source2(library, unit); |
- Map<MemoryIndexStoreImpl_Source2, List<Location>> sourceToLocations = _contextToSourceToLocations[context]; |
- if (sourceToLocations != null) { |
- List<Location> sourceLocations = sourceToLocations.remove(source2); |
- if (sourceLocations != null) { |
- for (Location location in sourceLocations) { |
- MemoryIndexStoreImpl_ElementRelationKey key = location.internalKey as MemoryIndexStoreImpl_ElementRelationKey; |
- Set<Location> relLocations = _keyToLocations[key]; |
- if (relLocations != null) { |
- relLocations.remove(location); |
- _locationCount--; |
- // no locations with this key |
- if (relLocations.isEmpty) { |
- _canonicalKeys.remove(key); |
- _keyToLocations.remove(key); |
- _keyCount--; |
- } |
- } |
- } |
- } |
- } |
- } |
-} |
- |
-class MemoryIndexStoreImpl_ElementRelationKey { |
- final Element _element; |
- |
- final Relationship _relationship; |
- |
- MemoryIndexStoreImpl_ElementRelationKey(this._element, this._relationship); |
- |
- @override |
- bool operator ==(Object obj) { |
- MemoryIndexStoreImpl_ElementRelationKey other = obj as MemoryIndexStoreImpl_ElementRelationKey; |
- Element otherElement = other._element; |
- return identical(other._relationship, _relationship) && otherElement.nameOffset == _element.nameOffset && otherElement.kind == _element.kind && otherElement.displayName == _element.displayName && otherElement.source == _element.source; |
- } |
- |
- @override |
- int get hashCode => JavaArrays.makeHashCode([ |
- _element.source, |
- _element.nameOffset, |
- _element.kind, |
- _element.displayName, |
- _relationship]); |
- |
- @override |
- String toString() => "${_element} ${_relationship}"; |
-} |
- |
-class MemoryIndexStoreImpl_Source2 { |
- final Source _librarySource; |
- |
- final Source _unitSource; |
- |
- MemoryIndexStoreImpl_Source2(this._librarySource, this._unitSource); |
- |
- @override |
- bool operator ==(Object obj) { |
- if (identical(obj, this)) { |
- return true; |
- } |
- if (obj is! MemoryIndexStoreImpl_Source2) { |
- return false; |
- } |
- MemoryIndexStoreImpl_Source2 other = obj as MemoryIndexStoreImpl_Source2; |
- return other._librarySource == _librarySource && other._unitSource == _unitSource; |
- } |
- |
- @override |
- int get hashCode => JavaArrays.makeHashCode([_librarySource, _unitSource]); |
- |
- @override |
- String toString() => "${_librarySource} ${_unitSource}"; |
-} |
- |
-/** |
- * Special [Element] which is used to index references to the name without specifying concrete |
- * kind of this name - field, method or something else. |
- */ |
-class NameElementImpl extends ElementImpl { |
- NameElementImpl(String name) : super("name:${name}", -1); |
- |
- @override |
- accept(ElementVisitor visitor) => null; |
- |
- @override |
- ElementKind get kind => ElementKind.NAME; |
-} |
- |
-/** |
- * The enumeration <code>ProcessorState</code> represents the possible states of an operation |
- * processor. |
- */ |
-class ProcessorState extends Enum<ProcessorState> { |
- /** |
- * The processor is ready to be run (has not been run before). |
- */ |
- static const ProcessorState READY = const ProcessorState('READY', 0); |
- |
- /** |
- * The processor is currently performing operations. |
- */ |
- static const ProcessorState RUNNING = const ProcessorState('RUNNING', 1); |
- |
- /** |
- * The processor is currently performing operations but has been asked to stop. |
- */ |
- static const ProcessorState STOP_REQESTED = const ProcessorState('STOP_REQESTED', 2); |
- |
- /** |
- * The processor has stopped performing operations and cannot be used again. |
- */ |
- static const ProcessorState STOPPED = const ProcessorState('STOPPED', 3); |
- |
- static const List<ProcessorState> values = const [READY, RUNNING, STOP_REQESTED, STOPPED]; |
- |
- const ProcessorState(String name, int ordinal) : super(name, ordinal); |
-} |
- |
-/** |
- * Relationship between an element and a location. Relationships are identified by a globally unique |
- * identifier. |
- */ |
-class Relationship { |
- /** |
- * The unique identifier for this relationship. |
- */ |
- final String _uniqueId; |
- |
- /** |
- * A table mapping relationship identifiers to relationships. |
- */ |
- static Map<String, Relationship> _RelationshipMap = {}; |
- |
- /** |
- * Return the relationship with the given unique identifier. |
- * |
- * @param uniqueId the unique identifier for the relationship |
- * @return the relationship with the given unique identifier |
- */ |
- static Relationship getRelationship(String uniqueId) { |
- Relationship relationship = _RelationshipMap[uniqueId]; |
- if (relationship == null) { |
- relationship = new Relationship(uniqueId); |
- _RelationshipMap[uniqueId] = relationship; |
- } |
- return relationship; |
- } |
- |
- /** |
- * @return all registered [Relationship]s. |
- */ |
- static Iterable<Relationship> values() => _RelationshipMap.values; |
- |
- /** |
- * Initialize a newly created relationship to have the given unique identifier. |
- * |
- * @param uniqueId the unique identifier for this relationship |
- */ |
- Relationship(this._uniqueId); |
- |
- /** |
- * Return the unique identifier for this relationship. |
- * |
- * @return the unique identifier for this relationship |
- */ |
- String get identifier => _uniqueId; |
- |
- @override |
- String toString() => _uniqueId; |
-} |
- |
-/** |
- * The interface <code>RelationshipCallback</code> defines the behavior of objects that are invoked |
- * with the results of a query about a given relationship. |
- */ |
-abstract class RelationshipCallback { |
- /** |
- * This method is invoked when the locations that have a specified relationship with a specified |
- * element are available. For example, if the element is a field and the relationship is the |
- * is-referenced-by relationship, then this method will be invoked with each location at which the |
- * field is referenced. |
- * |
- * @param element the [Element] that has the relationship with the locations |
- * @param relationship the relationship between the given element and the locations |
- * @param locations the locations that were found |
- */ |
- void hasRelationships(Element element, Relationship relationship, List<Location> locations); |
-} |
- |
-/** |
- * Instances of the [RemoveContextOperation] implement an operation that removes from the |
- * index any data based on the specified [AnalysisContext]. |
- */ |
-class RemoveContextOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- /** |
- * The context being removed. |
- */ |
- final AnalysisContext context; |
- |
- /** |
- * Initialize a newly created operation that will remove the specified resource. |
- * |
- * @param indexStore the index store against which this operation is being run |
- * @param context the [AnalysisContext] to remove |
- */ |
- RemoveContextOperation(this._indexStore, this.context); |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- _indexStore.removeContext(context); |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => false; |
- |
- @override |
- String toString() => "RemoveContext(${context})"; |
-} |
- |
-/** |
- * Instances of the [RemoveSourceOperation] implement an operation that removes from the index |
- * any data based on the content of a specified source. |
- */ |
-class RemoveSourceOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- /** |
- * The context in which source being removed. |
- */ |
- final AnalysisContext _context; |
- |
- /** |
- * The source being removed. |
- */ |
- final Source source; |
- |
- /** |
- * Initialize a newly created operation that will remove the specified resource. |
- * |
- * @param indexStore the index store against which this operation is being run |
- * @param context the [AnalysisContext] to remove source in |
- * @param source the [Source] to remove from index |
- */ |
- RemoveSourceOperation(this._indexStore, this._context, this.source); |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- _indexStore.removeSource(_context, source); |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => false; |
- |
- @override |
- String toString() => "RemoveSource(${source.fullName})"; |
-} |
- |
-/** |
- * Instances of the [RemoveSourcesOperation] implement an operation that removes from the |
- * index any data based on the content of source belonging to a [SourceContainer]. |
- */ |
-class RemoveSourcesOperation implements IndexOperation { |
- /** |
- * The index store against which this operation is being run. |
- */ |
- final IndexStore _indexStore; |
- |
- /** |
- * The context to remove container. |
- */ |
- final AnalysisContext _context; |
- |
- /** |
- * The source container to remove. |
- */ |
- final SourceContainer container; |
- |
- /** |
- * Initialize a newly created operation that will remove the specified resource. |
- * |
- * @param indexStore the index store against which this operation is being run |
- * @param context the [AnalysisContext] to remove container in |
- * @param container the [SourceContainer] to remove from index |
- */ |
- RemoveSourcesOperation(this._indexStore, this._context, this.container); |
- |
- @override |
- bool get isQuery => false; |
- |
- @override |
- void performOperation() { |
- _indexStore.removeSources(_context, container); |
- } |
- |
- @override |
- bool removeWhenSourceRemoved(Source source) => false; |
- |
- @override |
- String toString() => "RemoveSources(${container})"; |
-} |
- |
-/** |
- * The interface `UniverseElement` defines element to use when we want to request "defines" |
- * relations without specifying exact library. |
- */ |
-abstract class UniverseElement implements Element { |
- static final UniverseElement INSTANCE = UniverseElementImpl.INSTANCE; |
-} |
- |
-/** |
- * Implementation of [UniverseElement]. |
- */ |
-class UniverseElementImpl extends ElementImpl implements UniverseElement { |
- static UniverseElementImpl INSTANCE = new UniverseElementImpl(); |
- |
- UniverseElementImpl() : super("--universe--", -1); |
- |
- @override |
- accept(ElementVisitor visitor) => null; |
- |
- @override |
- ElementKind get kind => ElementKind.UNIVERSE; |
-} |