Fix search for private elements inside of discovered packages.

R=brianwilkerson@google.com

Change-Id: Ie2e4055369624d89c090a55787477a235754db5e
Reviewed-on: https://dart-review.googlesource.com/58940
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 1212bdc..0817ced 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -305,23 +305,24 @@
       return _searchReferences_Field(element, searchedFiles);
     } else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
       if (element.enclosingElement is ExecutableElement) {
-        return _searchReferences_Local(element, (n) => n is Block);
+        return _searchReferences_Local(
+            element, (n) => n is Block, searchedFiles);
       }
       return _searchReferences_Function(element, searchedFiles);
     } else if (kind == ElementKind.IMPORT) {
-      return _searchReferences_Import(element);
+      return _searchReferences_Import(element, searchedFiles);
     } else if (kind == ElementKind.LABEL ||
         kind == ElementKind.LOCAL_VARIABLE) {
-      return _searchReferences_Local(element, (n) => n is Block);
+      return _searchReferences_Local(element, (n) => n is Block, searchedFiles);
     } else if (kind == ElementKind.LIBRARY) {
-      return _searchReferences_Library(element);
+      return _searchReferences_Library(element, searchedFiles);
     } else if (kind == ElementKind.PARAMETER) {
       return _searchReferences_Parameter(element, searchedFiles);
     } else if (kind == ElementKind.PREFIX) {
-      return _searchReferences_Prefix(element);
+      return _searchReferences_Prefix(element, searchedFiles);
     } else if (kind == ElementKind.TYPE_PARAMETER) {
       return _searchReferences_Local(
-          element, (n) => n.parent is CompilationUnit);
+          element, (n) => n.parent is CompilationUnit, searchedFiles);
     }
     return const <SearchResult>[];
   }
@@ -470,7 +471,7 @@
     String path = element.source.fullName;
     if (name.startsWith('_')) {
       String libraryPath = element.library.source.fullName;
-      if (_driver.addedFiles.contains(libraryPath)) {
+      if (searchedFiles.add(libraryPath, this)) {
         FileState library = _driver.fsState.getFileForPath(libraryPath);
         List<FileState> candidates = [library]..addAll(library.partedFiles);
         for (FileState file in candidates) {
@@ -603,10 +604,9 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Import(
-      ImportElement element) async {
-    // Search only in drivers to which the library was added.
+      ImportElement element, SearchedFiles searchedFiles) async {
     String path = element.source.fullName;
-    if (!_driver.addedFiles.contains(path)) {
+    if (!searchedFiles.add(path, this)) {
       return const <SearchResult>[];
     }
 
@@ -624,10 +624,9 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Library(
-      LibraryElement element) async {
-    // Search only in drivers to which the library with the prefix was added.
+      LibraryElement element, SearchedFiles searchedFiles) async {
     String path = element.source.fullName;
-    if (!_driver.addedFiles.contains(path)) {
+    if (!searchedFiles.add(path, this)) {
       return const <SearchResult>[];
     }
 
@@ -651,10 +650,10 @@
     return results;
   }
 
-  Future<List<SearchResult>> _searchReferences_Local(
-      Element element, bool isRootNode(AstNode n)) async {
+  Future<List<SearchResult>> _searchReferences_Local(Element element,
+      bool isRootNode(AstNode n), SearchedFiles searchedFiles) async {
     String path = element.source.fullName;
-    if (!_driver.addedFiles.contains(path)) {
+    if (!searchedFiles.add(path, this)) {
       return const <SearchResult>[];
     }
 
@@ -687,10 +686,14 @@
   Future<List<SearchResult>> _searchReferences_Parameter(
       ParameterElement parameter, SearchedFiles searchedFiles) async {
     List<SearchResult> results = <SearchResult>[];
-    results.addAll(await _searchReferences_Local(parameter, (AstNode node) {
-      AstNode parent = node.parent;
-      return parent is ClassDeclaration || parent is CompilationUnit;
-    }));
+    results.addAll(await _searchReferences_Local(
+      parameter,
+      (AstNode node) {
+        AstNode parent = node.parent;
+        return parent is ClassDeclaration || parent is CompilationUnit;
+      },
+      searchedFiles,
+    ));
     if (parameter.isOptional) {
       results.addAll(await _searchReferences(parameter, searchedFiles));
     }
@@ -698,10 +701,9 @@
   }
 
   Future<List<SearchResult>> _searchReferences_Prefix(
-      PrefixElement element) async {
-    // Search only in drivers to which the library with the prefix was added.
+      PrefixElement element, SearchedFiles searchedFiles) async {
     String path = element.source.fullName;
-    if (!_driver.addedFiles.contains(path)) {
+    if (!searchedFiles.add(path, this)) {
       return const <SearchResult>[];
     }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index ac55908..82570b6 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -856,6 +856,31 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_ImportElement_noPrefix_inPackage() async {
+    testFile = _p('/aaa/lib/a.dart');
+    await _resolveTestUnit('''
+import 'dart:math' show max, PI, Random hide min;
+export 'dart:math' show max, PI, Random hide min;
+main() {
+  PI;
+  new Random();
+  max(1, 2);
+}
+Random bar() => null;
+''', addToDriver: false);
+    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(1, 2);', 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;
@@ -952,6 +977,32 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_LibraryElement_inPackage() async {
+    testFile = _p('/aaa/lib/a.dart');
+    var partPathA = _p('/aaa/lib/unitA.dart');
+    var partPathB = _p('/aaa/lib/unitB.dart');
+
+    var codeA = 'part of lib; // A';
+    var codeB = 'part of lib; // B';
+    provider.newFile(partPathA, codeA);
+    provider.newFile(partPathB, codeB);
+    await _resolveTestUnit('''
+library lib;
+part 'unitA.dart';
+part 'unitB.dart';
+''', addToDriver: false);
+    LibraryElement element = testLibraryElement;
+    CompilationUnitElement unitElementA = element.parts[0];
+    CompilationUnitElement unitElementB = element.parts[1];
+    var expected = [
+      new ExpectedResult(unitElementA, SearchResultKind.REFERENCE,
+          codeA.indexOf('lib; // A'), 'lib'.length),
+      new ExpectedResult(unitElementB, SearchResultKind.REFERENCE,
+          codeB.indexOf('lib; // B'), 'lib'.length),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_LocalVariableElement() async {
     await _resolveTestUnit(r'''
 main() {
@@ -973,7 +1024,7 @@
     await _verifyReferences(element, expected);
   }
 
-  test_searchReferences_localVariableElement_inForEachLoop() async {
+  test_searchReferences_LocalVariableElement_inForEachLoop() async {
     await _resolveTestUnit('''
 main() {
   for (var v in []) {
@@ -995,6 +1046,30 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_LocalVariableElement_inPackage() async {
+    testFile = _p('/aaa/lib/a.dart');
+
+    await _resolveTestUnit('''
+main() {
+  var v;
+  v = 1;
+  v += 2;
+  print(v);
+  v();
+}
+''', addToDriver: false);
+    Element element = findElementsByName(testUnit, 'v').single;
+    Element main = _findElement('main');
+
+    var expected = [
+      _expectId(main, SearchResultKind.WRITE, 'v = 1;'),
+      _expectId(main, SearchResultKind.READ_WRITE, 'v += 2;'),
+      _expectId(main, SearchResultKind.READ, 'v);'),
+      _expectId(main, SearchResultKind.INVOCATION, 'v();')
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_MethodElement() async {
     await _resolveTestUnit('''
 class A {
@@ -1212,6 +1287,36 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_PrefixElement_inPackage() async {
+    testFile = _p('/aaa/lib/a.dart');
+    var partPath = _p('/aaa/lib/my_part.dart');
+
+    String partCode = r'''
+part of my_lib;
+ppp.Future c;
+''';
+    provider.newFile(partPath, partCode);
+    await _resolveTestUnit('''
+library my_lib;
+import 'dart:async' as ppp;
+part 'my_part.dart';
+main() {
+  ppp.Future a;
+  ppp.Stream b;
+}
+''', addToDriver: false);
+    PrefixElement element = _findElementAtString('ppp;');
+    Element main = _findElement('main');
+    Element c = findChildElement(testLibraryElement, 'c');
+    var expected = [
+      _expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
+      _expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
+      new ExpectedResult(c, SearchResultKind.REFERENCE,
+          partCode.indexOf('ppp.Future c'), 'ppp'.length)
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_private_declaredInDefiningUnit() async {
     String p1 = _p('$testProject/part1.dart');
     String p2 = _p('$testProject/part2.dart');
@@ -1294,6 +1399,40 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_private_inPackage() async {
+    testFile = _p('/aaa/lib/a.dart');
+    var p1 = _p('/aaa/lib/part1.dart');
+    var p2 = _p('/aaa/lib/part2.dart');
+
+    String code1 = 'part of lib; _C v1;';
+    String code2 = 'part of lib; _C v2;';
+
+    provider.newFile(p1, code1);
+    provider.newFile(p2, code2);
+
+    await _resolveTestUnit('''
+library lib;
+part 'part1.dart';
+part 'part2.dart';
+class _C {}
+_C v;
+''', addToDriver: false);
+
+    Element element = testUnitElement.types.single;
+    Element v = testUnitElement.topLevelVariables[0];
+    Element v1 = testLibraryElement.parts[0].topLevelVariables[0];
+    Element v2 = testLibraryElement.parts[1].topLevelVariables[0];
+    var expected = [
+      new ExpectedResult(
+          v, SearchResultKind.REFERENCE, testCode.indexOf('_C v;'), 2),
+      new ExpectedResult(
+          v1, SearchResultKind.REFERENCE, code1.indexOf('_C v1;'), 2),
+      new ExpectedResult(
+          v2, SearchResultKind.REFERENCE, code2.indexOf('_C v2;'), 2),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_PropertyAccessorElement_getter() async {
     await _resolveTestUnit('''
 class A {
@@ -1672,8 +1811,13 @@
 
   String _p(String path) => provider.convertPath(path);
 
-  Future<Null> _resolveTestUnit(String code) async {
-    addTestFile(code);
+  Future<Null> _resolveTestUnit(String code, {bool addToDriver: true}) async {
+    if (addToDriver) {
+      addTestFile(code);
+    } else {
+      testCode = code;
+      provider.newFile(testFile, testCode);
+    }
     if (testUnit == null) {
       AnalysisResult result = await driver.getResult(testFile);
       testUnit = result.unit;