Search for ImportElement(s).

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org/2542583003 .
This commit is contained in:
Konstantin Shcheglov 2016-11-30 12:12:22 -08:00
parent 4686d364bb
commit fa0b825269
2 changed files with 167 additions and 0 deletions

View file

@ -13,6 +13,7 @@ import 'package:analyzer/src/dart/analysis/index.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/resolver/scope.dart' show NamespaceBuilder;
import 'package:analyzer/src/summary/idl.dart';
import 'package:collection/collection.dart';
@ -55,6 +56,8 @@ class Search {
return _searchReferences_Local(element, (n) => n is Block);
}
return _searchReferences_Function(element);
} else if (kind == ElementKind.IMPORT) {
return _searchReferences_Import(element);
} else if (kind == ElementKind.LABEL ||
kind == ElementKind.LOCAL_VARIABLE) {
return _searchReferences_Local(element, (n) => n is Block);
@ -155,6 +158,27 @@ class Search {
return results;
}
Future<List<SearchResult>> _searchReferences_Import(
ImportElement element) async {
// Search only in drivers to which the library was added.
String path = element.source.fullName;
if (!_driver.addedFiles.contains(path)) {
return const <SearchResult>[];
}
List<SearchResult> results = <SearchResult>[];
LibraryElement libraryElement = element.library;
for (CompilationUnitElement unitElement in libraryElement.units) {
String unitPath = unitElement.source.fullName;
AnalysisResult unitAnalysisResult = await _driver.getResult(unitPath);
_ImportElementReferencesVisitor visitor =
new _ImportElementReferencesVisitor(element, unitElement);
unitAnalysisResult.unit.accept(visitor);
results.addAll(visitor.results);
}
return results;
}
Future<List<SearchResult>> _searchReferences_Local(
Element element, bool isRootNode(AstNode n)) async {
String path = element.source.fullName;
@ -309,6 +333,72 @@ class _ContainingElementFinder extends GeneralizingElementVisitor {
}
}
/**
* Visitor that adds [SearchResult]s for references to the [importElement].
*/
class _ImportElementReferencesVisitor extends RecursiveAstVisitor {
final List<SearchResult> results = <SearchResult>[];
final ImportElement importElement;
final CompilationUnitElement enclosingUnitElement;
Set<Element> importedElements;
_ImportElementReferencesVisitor(
ImportElement element, this.enclosingUnitElement)
: importElement = element {
importedElements = new NamespaceBuilder()
.createImportNamespaceForDirective(element)
.definedNames
.values
.toSet();
}
@override
visitExportDirective(ExportDirective node) {}
@override
visitImportDirective(ImportDirective node) {}
@override
visitSimpleIdentifier(SimpleIdentifier node) {
if (node.inDeclarationContext()) {
return;
}
if (importElement.prefix != null) {
if (node.staticElement == importElement.prefix) {
AstNode parent = node.parent;
if (parent is PrefixedIdentifier && parent.prefix == node) {
if (importedElements.contains(parent.staticElement)) {
_addResultForPrefix(node, parent.identifier);
}
}
if (parent is MethodInvocation && parent.target == node) {
if (importedElements.contains(parent.methodName.staticElement)) {
_addResultForPrefix(node, parent.methodName);
}
}
}
} else {
if (importedElements.contains(node.staticElement)) {
_addResult(node.offset, 0);
}
}
}
void _addResult(int offset, int length) {
Element enclosingElement =
_getEnclosingElement(enclosingUnitElement, offset);
results.add(new SearchResult._(importElement, enclosingElement,
SearchResultKind.REFERENCE, offset, length, true, false));
}
void _addResultForPrefix(SimpleIdentifier prefixNode, AstNode nextNode) {
int prefixOffset = prefixNode.offset;
_addResult(prefixOffset, nextNode.offset - prefixOffset);
}
}
class _IndexRequest {
final AnalysisDriverUnitIndex index;

View file

@ -300,6 +300,83 @@ main() {
await _verifyReferences(element, expected);
}
test_searchReferences_ImportElement_noPrefix() async {
await _resolveTestUnit('''
import 'dart:math' show max, PI, Random hide min;
export 'dart:math' show max, PI, Random hide min;
main() {
print(PI);
print(new Random());
print(max(1, 2));
}
Random bar() => null;
''');
ImportElement element = testLibraryElement.imports[0];
Element mainElement = await _findElement('main');
Element barElement = await _findElement('bar');
var kind = SearchResultKind.REFERENCE;
var expected = [
_expectId(mainElement, kind, 'PI);', length: 0),
_expectId(mainElement, kind, 'Random()', length: 0),
_expectId(mainElement, kind, 'max(', length: 0),
_expectId(barElement, kind, 'Random bar()', length: 0),
];
await _verifyReferences(element, expected);
}
test_searchReferences_ImportElement_withPrefix() async {
await _resolveTestUnit('''
import 'dart:math' as math show max, PI, Random hide min;
export 'dart:math' show max, PI, Random hide min;
main() {
print(math.PI);
print(new math.Random());
print(math.max(1, 2));
}
math.Random bar() => null;
''');
ImportElement element = testLibraryElement.imports[0];
Element mainElement = await _findElement('main');
Element barElement = await _findElement('bar');
var kind = SearchResultKind.REFERENCE;
var length = 'math.'.length;
var expected = [
_expectId(mainElement, kind, 'math.PI);', length: length),
_expectId(mainElement, kind, 'math.Random()', length: length),
_expectId(mainElement, kind, 'math.max(', length: length),
_expectId(barElement, kind, 'math.Random bar()', length: length),
];
await _verifyReferences(element, expected);
}
test_searchReferences_ImportElement_withPrefix_forMultipleImports() async {
await _resolveTestUnit('''
import 'dart:async' as p;
import 'dart:math' as p;
main() {
p.Random;
p.Future;
}
''');
Element mainElement = await _findElement('main');
var kind = SearchResultKind.REFERENCE;
var length = 'p.'.length;
{
ImportElement element = testLibraryElement.imports[0];
var expected = [
_expectId(mainElement, kind, 'p.Future;', length: length),
];
await _verifyReferences(element, expected);
}
{
ImportElement element = testLibraryElement.imports[1];
var expected = [
_expectId(mainElement, kind, 'p.Random', length: length),
];
await _verifyReferences(element, expected);
}
}
test_searchReferences_LabelElement() async {
await _resolveTestUnit('''
main() {