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/analysis/index.dart'; | 12 import 'package:analyzer/src/dart/analysis/index.dart'; |
13 import 'package:analyzer/src/dart/ast/utilities.dart'; | 13 import 'package:analyzer/src/dart/ast/utilities.dart'; |
14 import 'package:analyzer/src/dart/element/element.dart'; | 14 import 'package:analyzer/src/dart/element/element.dart'; |
15 import 'package:analyzer/src/dart/element/member.dart'; | 15 import 'package:analyzer/src/dart/element/member.dart'; |
| 16 import 'package:analyzer/src/dart/resolver/scope.dart' show NamespaceBuilder; |
16 import 'package:analyzer/src/summary/idl.dart'; | 17 import 'package:analyzer/src/summary/idl.dart'; |
17 import 'package:collection/collection.dart'; | 18 import 'package:collection/collection.dart'; |
18 | 19 |
19 Element _getEnclosingElement(CompilationUnitElement unitElement, int offset) { | 20 Element _getEnclosingElement(CompilationUnitElement unitElement, int offset) { |
20 var finder = new _ContainingElementFinder(offset); | 21 var finder = new _ContainingElementFinder(offset); |
21 unitElement.accept(finder); | 22 unitElement.accept(finder); |
22 return finder.containingElement; | 23 return finder.containingElement; |
23 } | 24 } |
24 | 25 |
25 /** | 26 /** |
(...skipping 22 matching lines...) Expand all Loading... |
48 } else if (kind == ElementKind.GETTER) { | 49 } else if (kind == ElementKind.GETTER) { |
49 return _searchReferences_Getter(element); | 50 return _searchReferences_Getter(element); |
50 } else if (kind == ElementKind.FIELD || | 51 } else if (kind == ElementKind.FIELD || |
51 kind == ElementKind.TOP_LEVEL_VARIABLE) { | 52 kind == ElementKind.TOP_LEVEL_VARIABLE) { |
52 return _searchReferences_Field(element); | 53 return _searchReferences_Field(element); |
53 } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) { | 54 } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) { |
54 if (element.enclosingElement is ExecutableElement) { | 55 if (element.enclosingElement is ExecutableElement) { |
55 return _searchReferences_Local(element, (n) => n is Block); | 56 return _searchReferences_Local(element, (n) => n is Block); |
56 } | 57 } |
57 return _searchReferences_Function(element); | 58 return _searchReferences_Function(element); |
| 59 } else if (kind == ElementKind.IMPORT) { |
| 60 return _searchReferences_Import(element); |
58 } else if (kind == ElementKind.LABEL || | 61 } else if (kind == ElementKind.LABEL || |
59 kind == ElementKind.LOCAL_VARIABLE) { | 62 kind == ElementKind.LOCAL_VARIABLE) { |
60 return _searchReferences_Local(element, (n) => n is Block); | 63 return _searchReferences_Local(element, (n) => n is Block); |
61 } else if (kind == ElementKind.PARAMETER) { | 64 } else if (kind == ElementKind.PARAMETER) { |
62 return _searchReferences_Parameter(element); | 65 return _searchReferences_Parameter(element); |
63 } else if (kind == ElementKind.PREFIX) { | 66 } else if (kind == ElementKind.PREFIX) { |
64 return _searchReferences_Prefix(element); | 67 return _searchReferences_Prefix(element); |
65 } else if (kind == ElementKind.TYPE_PARAMETER) { | 68 } else if (kind == ElementKind.TYPE_PARAMETER) { |
66 return _searchReferences_Local( | 69 return _searchReferences_Local( |
67 element, (n) => n.parent is CompilationUnit); | 70 element, (n) => n.parent is CompilationUnit); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 Future<List<SearchResult>> _searchReferences_Getter( | 151 Future<List<SearchResult>> _searchReferences_Getter( |
149 PropertyAccessorElement getter) async { | 152 PropertyAccessorElement getter) async { |
150 List<SearchResult> results = <SearchResult>[]; | 153 List<SearchResult> results = <SearchResult>[]; |
151 await _addResults(results, getter, { | 154 await _addResults(results, getter, { |
152 IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE, | 155 IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE, |
153 IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION | 156 IndexRelationKind.IS_INVOKED_BY: SearchResultKind.INVOCATION |
154 }); | 157 }); |
155 return results; | 158 return results; |
156 } | 159 } |
157 | 160 |
| 161 Future<List<SearchResult>> _searchReferences_Import( |
| 162 ImportElement element) async { |
| 163 // Search only in drivers to which the library was added. |
| 164 String path = element.source.fullName; |
| 165 if (!_driver.addedFiles.contains(path)) { |
| 166 return const <SearchResult>[]; |
| 167 } |
| 168 |
| 169 List<SearchResult> results = <SearchResult>[]; |
| 170 LibraryElement libraryElement = element.library; |
| 171 for (CompilationUnitElement unitElement in libraryElement.units) { |
| 172 String unitPath = unitElement.source.fullName; |
| 173 AnalysisResult unitAnalysisResult = await _driver.getResult(unitPath); |
| 174 _ImportElementReferencesVisitor visitor = |
| 175 new _ImportElementReferencesVisitor(element, unitElement); |
| 176 unitAnalysisResult.unit.accept(visitor); |
| 177 results.addAll(visitor.results); |
| 178 } |
| 179 return results; |
| 180 } |
| 181 |
158 Future<List<SearchResult>> _searchReferences_Local( | 182 Future<List<SearchResult>> _searchReferences_Local( |
159 Element element, bool isRootNode(AstNode n)) async { | 183 Element element, bool isRootNode(AstNode n)) async { |
160 String path = element.source.fullName; | 184 String path = element.source.fullName; |
161 if (!_driver.addedFiles.contains(path)) { | 185 if (!_driver.addedFiles.contains(path)) { |
162 return const <SearchResult>[]; | 186 return const <SearchResult>[]; |
163 } | 187 } |
164 | 188 |
165 // Prepare the unit. | 189 // Prepare the unit. |
166 AnalysisResult analysisResult = await _driver.getResult(path); | 190 AnalysisResult analysisResult = await _driver.getResult(path); |
167 CompilationUnit unit = analysisResult.unit; | 191 CompilationUnit unit = analysisResult.unit; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 if (element.codeOffset != null && | 326 if (element.codeOffset != null && |
303 element.codeOffset <= offset && | 327 element.codeOffset <= offset && |
304 offset <= element.codeOffset + element.codeLength) { | 328 offset <= element.codeOffset + element.codeLength) { |
305 containingElement = element; | 329 containingElement = element; |
306 super.visitElement(element); | 330 super.visitElement(element); |
307 } | 331 } |
308 } | 332 } |
309 } | 333 } |
310 } | 334 } |
311 | 335 |
| 336 /** |
| 337 * Visitor that adds [SearchResult]s for references to the [importElement]. |
| 338 */ |
| 339 class _ImportElementReferencesVisitor extends RecursiveAstVisitor { |
| 340 final List<SearchResult> results = <SearchResult>[]; |
| 341 |
| 342 final ImportElement importElement; |
| 343 final CompilationUnitElement enclosingUnitElement; |
| 344 |
| 345 Set<Element> importedElements; |
| 346 |
| 347 _ImportElementReferencesVisitor( |
| 348 ImportElement element, this.enclosingUnitElement) |
| 349 : importElement = element { |
| 350 importedElements = new NamespaceBuilder() |
| 351 .createImportNamespaceForDirective(element) |
| 352 .definedNames |
| 353 .values |
| 354 .toSet(); |
| 355 } |
| 356 |
| 357 @override |
| 358 visitExportDirective(ExportDirective node) {} |
| 359 |
| 360 @override |
| 361 visitImportDirective(ImportDirective node) {} |
| 362 |
| 363 @override |
| 364 visitSimpleIdentifier(SimpleIdentifier node) { |
| 365 if (node.inDeclarationContext()) { |
| 366 return; |
| 367 } |
| 368 if (importElement.prefix != null) { |
| 369 if (node.staticElement == importElement.prefix) { |
| 370 AstNode parent = node.parent; |
| 371 if (parent is PrefixedIdentifier && parent.prefix == node) { |
| 372 if (importedElements.contains(parent.staticElement)) { |
| 373 _addResultForPrefix(node, parent.identifier); |
| 374 } |
| 375 } |
| 376 if (parent is MethodInvocation && parent.target == node) { |
| 377 if (importedElements.contains(parent.methodName.staticElement)) { |
| 378 _addResultForPrefix(node, parent.methodName); |
| 379 } |
| 380 } |
| 381 } |
| 382 } else { |
| 383 if (importedElements.contains(node.staticElement)) { |
| 384 _addResult(node.offset, 0); |
| 385 } |
| 386 } |
| 387 } |
| 388 |
| 389 void _addResult(int offset, int length) { |
| 390 Element enclosingElement = |
| 391 _getEnclosingElement(enclosingUnitElement, offset); |
| 392 results.add(new SearchResult._(importElement, enclosingElement, |
| 393 SearchResultKind.REFERENCE, offset, length, true, false)); |
| 394 } |
| 395 |
| 396 void _addResultForPrefix(SimpleIdentifier prefixNode, AstNode nextNode) { |
| 397 int prefixOffset = prefixNode.offset; |
| 398 _addResult(prefixOffset, nextNode.offset - prefixOffset); |
| 399 } |
| 400 } |
| 401 |
312 class _IndexRequest { | 402 class _IndexRequest { |
313 final AnalysisDriverUnitIndex index; | 403 final AnalysisDriverUnitIndex index; |
314 | 404 |
315 _IndexRequest(this.index); | 405 _IndexRequest(this.index); |
316 | 406 |
317 /** | 407 /** |
318 * Return the [element]'s identifier in the [index] or `-1` if the | 408 * Return the [element]'s identifier in the [index] or `-1` if the |
319 * [element] is not referenced in the [index]. | 409 * [element] is not referenced in the [index]. |
320 */ | 410 */ |
321 int findElementId(Element element) { | 411 int findElementId(Element element) { |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 } | 628 } |
539 | 629 |
540 void _addResult(AstNode node, SearchResultKind kind) { | 630 void _addResult(AstNode node, SearchResultKind kind) { |
541 bool isQualified = node.parent is Label; | 631 bool isQualified = node.parent is Label; |
542 Element enclosingElement = | 632 Element enclosingElement = |
543 _getEnclosingElement(enclosingUnitElement, node.offset); | 633 _getEnclosingElement(enclosingUnitElement, node.offset); |
544 results.add(new SearchResult._(element, enclosingElement, kind, node.offset, | 634 results.add(new SearchResult._(element, enclosingElement, kind, node.offset, |
545 node.length, true, isQualified)); | 635 node.length, true, isQualified)); |
546 } | 636 } |
547 } | 637 } |
OLD | NEW |