| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/visitor.dart'; | 8 import 'package:analyzer/dart/ast/visitor.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/dart/element/visitor.dart'; | 10 import 'package:analyzer/dart/element/visitor.dart'; |
| 11 import 'package:analyzer/src/dart/analysis/driver.dart'; | 11 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 12 import 'package:analyzer/src/dart/ast/utilities.dart'; | 12 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 13 import 'package:analyzer/src/dart/element/element.dart'; | 13 import 'package:analyzer/src/dart/element/element.dart'; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * Search support for an [AnalysisDriver]. | 16 * Search support for an [AnalysisDriver]. |
| 17 */ | 17 */ |
| 18 class Search { | 18 class Search { |
| 19 final AnalysisDriver _driver; | 19 final AnalysisDriver _driver; |
| 20 | 20 |
| 21 Search(this._driver); | 21 Search(this._driver); |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * Returns references to the element at the given [offset] in the file with | 24 * Returns references to the [element]. |
| 25 * the given [path]. | |
| 26 */ | 25 */ |
| 27 Future<List<SearchResult>> references(String path, int offset) async { | 26 Future<List<SearchResult>> references(Element element) async { |
| 28 // Search only in added files. | |
| 29 if (!_driver.addedFiles.contains(path)) { | |
| 30 return const <SearchResult>[]; | |
| 31 } | |
| 32 | |
| 33 AnalysisResult analysisResult = await _driver.getResult(path); | |
| 34 CompilationUnit unit = analysisResult.unit; | |
| 35 | |
| 36 // Prepare the node. | |
| 37 AstNode node = new NodeLocator(offset).searchWithin(unit); | |
| 38 if (node == null) { | |
| 39 return const <SearchResult>[]; | |
| 40 } | |
| 41 | |
| 42 // Prepare the element. | |
| 43 Element element = ElementLocator.locate(node); | |
| 44 if (element == null) { | 27 if (element == null) { |
| 45 return const <SearchResult>[]; | 28 return const <SearchResult>[]; |
| 46 } | 29 } |
| 47 | 30 |
| 48 ElementKind kind = element.kind; | 31 ElementKind kind = element.kind; |
| 49 if (kind == ElementKind.LABEL || kind == ElementKind.LOCAL_VARIABLE) { | 32 if (kind == ElementKind.LABEL || kind == ElementKind.LOCAL_VARIABLE) { |
| 50 Block block = node.getAncestor((n) => n is Block); | 33 return _searchReferences_Local(element, (n) => n is Block); |
| 51 return _searchReferences_Local(element, unit.element, block); | |
| 52 } | 34 } |
| 53 // TODO(scheglov) support other kinds | 35 // TODO(scheglov) support other kinds |
| 54 return []; | 36 return const <SearchResult>[]; |
| 55 } | 37 } |
| 56 | 38 |
| 57 Future<List<SearchResult>> _searchReferences_Local( | 39 Future<List<SearchResult>> _searchReferences_Local( |
| 58 Element element, | 40 Element element, bool isRootNode(AstNode n)) async { |
| 59 CompilationUnitElement enclosingUnitElement, | 41 String path = element.source.fullName; |
| 60 AstNode enclosingNode) async { | 42 |
| 43 // Prepare the unit. |
| 44 AnalysisResult analysisResult = await _driver.getResult(path); |
| 45 CompilationUnit unit = analysisResult.unit; |
| 46 if (unit == null) { |
| 47 return const <SearchResult>[]; |
| 48 } |
| 49 |
| 50 // Prepare the node. |
| 51 AstNode node = new NodeLocator(element.nameOffset).searchWithin(unit); |
| 52 if (node == null) { |
| 53 return const <SearchResult>[]; |
| 54 } |
| 55 |
| 56 // Prepare the enclosing node. |
| 57 AstNode enclosingNode = node.getAncestor(isRootNode); |
| 58 |
| 59 // Find the matches. |
| 61 _LocalReferencesVisitor visitor = | 60 _LocalReferencesVisitor visitor = |
| 62 new _LocalReferencesVisitor(element, enclosingUnitElement); | 61 new _LocalReferencesVisitor(element, unit.element); |
| 63 enclosingNode?.accept(visitor); | 62 enclosingNode.accept(visitor); |
| 64 return visitor.matches; | 63 return visitor.results; |
| 65 } | 64 } |
| 66 } | 65 } |
| 67 | 66 |
| 68 /** | 67 /** |
| 69 * A single search result. | 68 * A single search result. |
| 70 */ | 69 */ |
| 71 class SearchResult { | 70 class SearchResult { |
| 72 /** | 71 /** |
| 73 * The element that is used at this result. | 72 * The element that is used at this result. |
| 74 */ | 73 */ |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 } | 153 } |
| 155 | 154 |
| 156 /** | 155 /** |
| 157 * Visitor that adds [SearchResult]s for local elements of a block, method, | 156 * Visitor that adds [SearchResult]s for local elements of a block, method, |
| 158 * class or a library - labels, local functions, local variables and parameters, | 157 * class or a library - labels, local functions, local variables and parameters, |
| 159 * type parameters, import prefixes. | 158 * type parameters, import prefixes. |
| 160 */ | 159 */ |
| 161 class _LocalReferencesVisitor extends RecursiveAstVisitor { | 160 class _LocalReferencesVisitor extends RecursiveAstVisitor { |
| 162 final List<SearchResult> matches = <SearchResult>[]; | 161 final List<SearchResult> results = <SearchResult>[]; |
| 163 | 162 |
| 164 final Element element; | 163 final Element element; |
| 165 final CompilationUnitElement enclosingUnitElement; | 164 final CompilationUnitElement enclosingUnitElement; |
| 166 | 165 |
| 167 _LocalReferencesVisitor(this.element, this.enclosingUnitElement); | 166 _LocalReferencesVisitor(this.element, this.enclosingUnitElement); |
| 168 | 167 |
| 169 @override | 168 @override |
| 170 visitSimpleIdentifier(SimpleIdentifier node) { | 169 visitSimpleIdentifier(SimpleIdentifier node) { |
| 171 if (node.inDeclarationContext()) { | 170 if (node.inDeclarationContext()) { |
| 172 return; | 171 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 186 } else if (isGet) { | 185 } else if (isGet) { |
| 187 if (parent is MethodInvocation && parent.methodName == node) { | 186 if (parent is MethodInvocation && parent.methodName == node) { |
| 188 kind = SearchResultKind.INVOCATION; | 187 kind = SearchResultKind.INVOCATION; |
| 189 } else { | 188 } else { |
| 190 kind = SearchResultKind.READ; | 189 kind = SearchResultKind.READ; |
| 191 } | 190 } |
| 192 } else if (isSet) { | 191 } else if (isSet) { |
| 193 kind = SearchResultKind.WRITE; | 192 kind = SearchResultKind.WRITE; |
| 194 } | 193 } |
| 195 } | 194 } |
| 196 _addMatch(node, kind); | 195 _addResult(node, kind); |
| 197 } | 196 } |
| 198 } | 197 } |
| 199 | 198 |
| 200 void _addMatch(AstNode node, SearchResultKind kind) { | 199 void _addResult(AstNode node, SearchResultKind kind) { |
| 201 bool isQualified = node.parent is Label; | 200 bool isQualified = node.parent is Label; |
| 202 var finder = new _ContainingElementFinder(node.offset); | 201 var finder = new _ContainingElementFinder(node.offset); |
| 203 enclosingUnitElement.accept(finder); | 202 enclosingUnitElement.accept(finder); |
| 204 matches.add(new SearchResult._(element, finder.containingElement, kind, | 203 results.add(new SearchResult._(element, finder.containingElement, kind, |
| 205 node.offset, node.length, true, isQualified)); | 204 node.offset, node.length, true, isQualified)); |
| 206 } | 205 } |
| 207 } | 206 } |
| OLD | NEW |