| 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 |