Index: pkg/analysis_services/lib/src/index/index_contributor.dart |
diff --git a/pkg/analysis_services/lib/src/index/index_contributor.dart b/pkg/analysis_services/lib/src/index/index_contributor.dart |
deleted file mode 100644 |
index 2164a4e733bbc0c34ea261fc385a3bde39f9b99b..0000000000000000000000000000000000000000 |
--- a/pkg/analysis_services/lib/src/index/index_contributor.dart |
+++ /dev/null |
@@ -1,1183 +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. |
- |
-library services.src.index.index_contributor; |
- |
-import 'dart:collection' show Queue; |
- |
-import 'package:analysis_services/index/index.dart'; |
-import 'package:analysis_services/index/index_store.dart'; |
-import 'package:analyzer/src/generated/ast.dart'; |
-import 'package:analyzer/src/generated/element.dart'; |
-import 'package:analyzer/src/generated/engine.dart'; |
-import 'package:analyzer/src/generated/html.dart' as ht; |
-import 'package:analyzer/src/generated/java_core.dart'; |
-import 'package:analyzer/src/generated/java_engine.dart'; |
-import 'package:analyzer/src/generated/resolver.dart'; |
-import 'package:analyzer/src/generated/scanner.dart'; |
-import 'package:analyzer/src/generated/source.dart'; |
- |
- |
-/** |
- * Adds data to [store] based on the resolved Dart [unit]. |
- */ |
-void indexDartUnit(IndexStore store, AnalysisContext context, |
- CompilationUnit unit) { |
- // check unit |
- if (unit == null) { |
- return; |
- } |
- // prepare unit element |
- CompilationUnitElement unitElement = unit.element; |
- if (unitElement == null) { |
- return; |
- } |
- // about to index |
- bool mayIndex = store.aboutToIndexDart(context, unitElement); |
- if (!mayIndex) { |
- return; |
- } |
- // do index |
- unit.accept(new _IndexContributor(store)); |
- unit.accept(new _AngularDartIndexContributor(store)); |
- store.doneIndex(); |
-} |
- |
- |
-/** |
- * Adds data to [store] based on the resolved HTML [unit]. |
- */ |
-void indexHtmlUnit(IndexStore store, AnalysisContext context, ht.HtmlUnit unit) |
- { |
- // check unit |
- if (unit == null) { |
- return; |
- } |
- // prepare unit element |
- HtmlElement unitElement = unit.element; |
- if (unitElement == null) { |
- return; |
- } |
- // about to index |
- bool mayIndex = store.aboutToIndexHtml(context, unitElement); |
- if (!mayIndex) { |
- return; |
- } |
- // do index |
- unit.accept(new _AngularHtmlIndexContributor(store)); |
- store.doneIndex(); |
-} |
- |
- |
-/** |
- * 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, |
- location); |
- } |
- } |
- // setter reference |
- if (property.propertyKind.callsSetter()) { |
- PropertyAccessorElement setter = field.setter; |
- if (setter != null) { |
- _store.recordRelationship( |
- setter, |
- IndexConstants.IS_REFERENCED_BY, |
- 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. |
- * |
- * [store] - the [IndexStore] to record relations into. |
- */ |
- _AngularHtmlIndexContributor(this._store) { |
- _indexContributor = new _AngularHtmlIndexContributor_forEmbeddedDart( |
- _store, |
- this); |
- } |
- |
- @override |
- void visitExpression(Expression expression) { |
- // Formatter |
- if (expression is SimpleIdentifier) { |
- Element element = expression.bestElement; |
- if (element is AngularElement) { |
- _store.recordRelationship( |
- element, |
- IndexConstants.ANGULAR_REFERENCE, |
- _createLocationForIdentifier(expression)); |
- 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 _AngularHtmlIndexContributor_forEmbeddedDart extends _IndexContributor { |
- final _AngularHtmlIndexContributor angularContributor; |
- |
- _AngularHtmlIndexContributor_forEmbeddedDart(IndexStore store, |
- this.angularContributor) : super( |
- store); |
- |
- @override |
- Element peekElement() => angularContributor._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 an [HtmlUnit] and every embedded [Expression]. |
- */ |
-abstract class _ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> { |
- /** |
- * Visits the given [Expression]s embedded into tag or attribute. |
- * |
- * [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); |
- } |
- } |
- } |
-} |
- |
- |
-/** |
- * Information about [ImportElement] and place where it is referenced using |
- * [PrefixElement]. |
- */ |
-class _ImportElementInfo { |
- ImportElement _element; |
- |
- int _periodEnd = 0; |
-} |
- |
- |
-/** |
- * Visits a resolved AST and adds relationships into [IndexStore]. |
- */ |
-class _IndexContributor extends GeneralizingAstVisitor<Object> { |
- 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; |
- } |
- |
- /** |
- * 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); |
- } |
- } |
- |
- @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); |
- { |
- 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, |
- _createLocationForOffset(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); |
- { |
- 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 = _createLocationForOffset(start, end - start); |
- } else { |
- int start = node.returnType.end; |
- location = _createLocationForOffset(start, 0); |
- } |
- recordRelationship(element, IndexConstants.NAME_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 = _createLocationForOffset(start, end - start); |
- } else { |
- int start = node.type.end; |
- location = _createLocationForOffset(start, 0); |
- } |
- // record relationship |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- return super.visitConstructorName(node); |
- } |
- |
- @override |
- Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
- LocalVariableElement element = node.element; |
- enterScope(element); |
- try { |
- return super.visitDeclaredIdentifier(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @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); |
- enterScope(element); |
- try { |
- return super.visitFunctionDeclaration(node); |
- } finally { |
- _exitScope(); |
- } |
- } |
- |
- @override |
- Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
- Element element = node.element; |
- _recordElementDefinition(element); |
- 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 = _createLocationForToken(operator, element != null); |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY, 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; |
- Location location = _createLocationForNode(name); |
- // element invocation |
- Element element = name.bestElement; |
- if (element is MethodElement || |
- element is PropertyAccessorElement || |
- element is FunctionElement || |
- element is VariableElement) { |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY, location); |
- } |
- // name invocation |
- { |
- Element nameElement = new NameElement(name.name); |
- _store.recordRelationship( |
- nameElement, |
- IndexConstants.IS_INVOKED_BY, |
- location); |
- } |
- _recordImportElementReferenceWithoutPrefix(name); |
- return super.visitMethodInvocation(node); |
- } |
- |
- @override |
- Object visitPartDirective(PartDirective node) { |
- Element element = node.element; |
- Location location = _createLocationForNode(node.uri); |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- return super.visitPartDirective(node); |
- } |
- |
- @override |
- Object visitPartOfDirective(PartOfDirective node) { |
- Location location = _createLocationForNode(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 NameElement(node.name); |
- Location location = _createLocationForNode(node); |
- // name in declaration |
- if (node.inDeclarationContext()) { |
- recordRelationship( |
- nameElement, |
- IndexConstants.NAME_IS_DEFINED_BY, |
- location); |
- return null; |
- } |
- // prepare information |
- Element element = node.bestElement; |
- // stop if already handled |
- if (_isAlreadyHandledName(node)) { |
- return null; |
- } |
- // record name read/write |
- if (element != null && element.enclosingElement is ClassElement || |
- element == null && location.isQualified) { |
- bool inGetterContext = node.inGetterContext(); |
- bool inSetterContext = node.inSetterContext(); |
- if (inGetterContext && inSetterContext) { |
- _store.recordRelationship( |
- nameElement, |
- IndexConstants.IS_READ_WRITTEN_BY, |
- location); |
- } else if (inGetterContext) { |
- _store.recordRelationship( |
- nameElement, |
- IndexConstants.IS_READ_BY, |
- location); |
- } else if (inSetterContext) { |
- _store.recordRelationship( |
- nameElement, |
- IndexConstants.IS_WRITTEN_BY, |
- location); |
- } |
- } |
- // this.field parameter |
- if (element is FieldFormalParameterElement) { |
- element = (element as FieldFormalParameterElement).field; |
- } |
- // record specific relations |
- if (element is ClassElement || |
- element is FunctionElement || |
- element is FunctionTypeAliasElement || |
- element is LabelElement || |
- element is MethodElement || |
- element is PropertyAccessorElement || |
- element is PropertyInducingElement || |
- element is TypeParameterElement) { |
- recordRelationship(element, IndexConstants.IS_REFERENCED_BY, location); |
- } else if (element is PrefixElement) { |
- _recordImportElementReferenceWithPrefix(node); |
- } 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 = _createLocationForOffset(start, end - start); |
- } else { |
- int start = node.keyword.end; |
- location = _createLocationForOffset(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); |
- } |
- 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 = _createLocationForNode(name); |
- location = _getLocationWithExpressionType(location, node.initializer); |
- recordRelationship(element, IndexConstants.NAME_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; |
- } |
- |
- /** |
- * @return the [Location] representing location of the [AstNode]. |
- */ |
- Location _createLocationForNode(AstNode node) { |
- bool isQualified = _isQualifiedClassMemberAccess(node); |
- bool isResolved = true; |
- if (node is SimpleIdentifier) { |
- isResolved = node.bestElement != null; |
- } |
- Element element = peekElement(); |
- return new Location( |
- element, |
- node.offset, |
- node.length, |
- isQualified: isQualified, |
- isResolved: isResolved); |
- } |
- |
- /** |
- * [offset] - the offset of the location within [Source]. |
- * [length] - the length of the location. |
- * |
- * Returns the [Location] representing the given offset and length within the |
- * inner-most [Element]. |
- */ |
- Location _createLocationForOffset(int offset, int length) { |
- Element element = peekElement(); |
- return new Location(element, offset, length); |
- } |
- |
- /** |
- * @return the [Location] representing location of the [Token]. |
- */ |
- Location _createLocationForToken(Token token, bool isResolved) { |
- Element element = peekElement(); |
- return new Location( |
- element, |
- token.offset, |
- token.length, |
- isQualified: true, |
- isResolved: isResolved); |
- } |
- |
- /** |
- * 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 parent.methodName == node; |
- } |
- return false; |
- } |
- |
- bool _isQualifiedClassMemberAccess(AstNode node) { |
- if (node is SimpleIdentifier) { |
- AstNode parent = node.parent; |
- if (parent is PrefixedIdentifier && parent.identifier == node) { |
- return parent.prefix.staticElement is! PrefixElement; |
- } |
- if (parent is PropertyAccess && parent.propertyName == node) { |
- return parent.realTarget != null; |
- } |
- if (parent is MethodInvocation && parent.methodName == node) { |
- Expression target = parent.realTarget; |
- if (target is SimpleIdentifier && |
- target.staticElement is PrefixElement) { |
- return false; |
- } |
- return target != null; |
- } |
- } |
- return false; |
- } |
- |
- /** |
- * Records the [Element] definition in the library and universe. |
- */ |
- void _recordElementDefinition(Element element) { |
- Location location = createLocation(element); |
- Relationship relationship = IndexConstants.DEFINES; |
- recordRelationship(_libraryElement, relationship, location); |
- recordRelationship(UniverseElement.INSTANCE, relationship, location); |
- } |
- |
- /** |
- * Records [ImportElement] that declares given prefix and imports library with element used |
- * with given prefix node. |
- */ |
- void _recordImportElementReferenceWithPrefix(SimpleIdentifier prefixNode) { |
- _ImportElementInfo info = getImportElementInfo(prefixNode); |
- if (info != null) { |
- int offset = prefixNode.offset; |
- int length = info._periodEnd - offset; |
- Location location = _createLocationForOffset(offset, length); |
- recordRelationship( |
- info._element, |
- IndexConstants.IS_REFERENCED_BY, |
- 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 = _createLocationForOffset(node.offset, 0); |
- recordRelationship( |
- importElement, |
- 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 = _createLocationForNode(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 = _createLocationForToken(operator, element != null); |
- // 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 NameElement(name); |
- recordRelationship(nameElement, IndexConstants.IS_INVOKED_BY, location); |
- } |
- // record element reference |
- if (element != null) { |
- recordRelationship(element, IndexConstants.IS_INVOKED_BY, location); |
- } |
- } |
- |
- /** |
- * Records a relation between [superNode] and its [Element]. |
- */ |
- void _recordSuperType(TypeName superNode, Relationship relationship) { |
- if (superNode != null) { |
- Identifier superName = superNode.name; |
- if (superName != null) { |
- Element superElement = superName.staticElement; |
- recordRelationship( |
- superElement, |
- relationship, |
- _createLocationForNode(superNode)); |
- } |
- } |
- } |
- |
- /** |
- * Creates a [Location] representing declaration 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) { |
- _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 _ImportElementInfo getImportElementInfo(SimpleIdentifier prefixNode) { |
- _ImportElementInfo info = new _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 (prefixed.prefix == prefixNode) { |
- usedElement = prefixed.staticElement; |
- info._periodEnd = prefixed.period.end; |
- } |
- } |
- if (parent is MethodInvocation) { |
- MethodInvocation invocation = parent; |
- if (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. |
- * |
- * [location] - the base location |
- * [expression] - the expression assigned at the given location |
- */ |
- static Location _getLocationWithExpressionType(Location location, |
- Expression expression) { |
- if (expression != null) { |
- return new LocationWithData<DartType>(location, expression.bestType); |
- } |
- 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.from(namespace.definedNames.values); |
- 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 && parent.identifier == node; |
- } |
-} |