Use both path and URI to own a file.

If either is owned by some other search, then this search cannot have it.

R=brianwilkerson@google.com

Change-Id: I0758ddce72dfb9dfc54465f98a2542ab1c5eb7ad
Reviewed-on: https://dart-review.googlesource.com/63364
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 b5417e9..6ab014f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -767,16 +767,19 @@
  * Container that keeps track of file owners.
  */
 class SearchedFiles {
-  final Map<Uri, Search> owners = {};
+  final Map<String, Search> pathOwners = {};
+  final Map<Uri, Search> uriOwners = {};
 
   bool add(String path, Search search) {
     var file = search._driver.fsState.getFileForPath(path);
-    var owner = owners[file.uri];
-    if (owner == null) {
-      owners[file.uri] = search;
+    var pathOwner = pathOwners[path];
+    var uriOwner = uriOwners[file.uri];
+    if (pathOwner == null && uriOwner == null) {
+      pathOwners[path] = search;
+      uriOwners[file.uri] = search;
       return true;
     }
-    return identical(owner, search);
+    return identical(pathOwner, search) && identical(uriOwner, search);
   }
 
   void ownAdded(Search search) {
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 373fd4b..917a0cf6 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -82,7 +82,14 @@
     }
   }
 
-  AnalysisDriver createAnalysisDriver({SummaryDataStore externalSummaries}) {
+  AnalysisDriver createAnalysisDriver(
+      {Map<String, List<Folder>> packageMap,
+      SummaryDataStore externalSummaries}) {
+    packageMap ??= <String, List<Folder>>{
+      'test': [provider.getFolder(testProject)],
+      'aaa': [provider.getFolder(_p('/aaa/lib'))],
+      'bbb': [provider.getFolder(_p('/bbb/lib'))],
+    };
     return new AnalysisDriver(
         scheduler,
         logger,
@@ -93,11 +100,7 @@
         new SourceFactory([
           new DartUriResolver(sdk),
           generatedUriResolver,
-          new PackageMapUriResolver(provider, <String, List<Folder>>{
-            'test': [provider.getFolder(testProject)],
-            'aaa': [provider.getFolder(_p('/aaa/lib'))],
-            'bbb': [provider.getFolder(_p('/bbb/lib'))],
-          }),
+          new PackageMapUriResolver(provider, packageMap),
           new ResourceUriResolver(provider)
         ], null, provider),
         createAnalysisOptions(),
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index d3573f1..9ee10f7 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -448,6 +448,55 @@
     assertHasResult(b, 'b', not: true);
   }
 
+  test_references_discover_onlyOwned_samePath() async {
+    var p = _p('/test/lib/t.dart');
+    provider.newFile(p, 'int t;');
+
+    var driver1 = createAnalysisDriver(packageMap: {
+      'test': [provider.newFolder(_p('/test/lib'))]
+    });
+    var driver2 = createAnalysisDriver(packageMap: {});
+
+    var searchedFiles = new SearchedFiles();
+    searchedFiles.ownAdded(driver1.search);
+    searchedFiles.ownAdded(driver2.search); // does not own any file, but...
+
+    // driver1 owns both path and URI.
+    expect(searchedFiles.add(p, driver1.search), isTrue);
+
+    // The path is already owned by driver1, so cannot be handled in driver2.
+    expect(searchedFiles.add(p, driver2.search), isFalse);
+  }
+
+  test_references_discover_onlyOwned_sameUri() async {
+    var a = _p('/aaa/lib/t.dart');
+    var b = _p('/bbb/lib/t.dart');
+
+    provider.newFile(a, 'int t;');
+    provider.newFile(b, 'double t;');
+
+    var driver1 = createAnalysisDriver(packageMap: {
+      'ttt': [provider.newFolder(_p('/aaa/lib'))]
+    });
+    var driver2 = createAnalysisDriver(packageMap: {
+      'ttt': [provider.newFolder(_p('/bbb/lib'))]
+    });
+
+    // driver1 owns `/aaa/lib/t.dart` with `package:ttt/t.dart`.
+    driver1.addFile(a);
+
+    var searchedFiles = new SearchedFiles();
+
+    searchedFiles.ownAdded(driver1.search);
+    searchedFiles.ownAdded(driver2.search); // does not own any file, but...
+
+    // driver1 owns both path and URI.
+    expect(searchedFiles.add(a, driver1.search), isTrue);
+
+    // The URI is already owned by driver1, so cannot be handled in driver2.
+    expect(searchedFiles.add(b, driver2.search), isFalse);
+  }
+
   test_searchMemberReferences_qualified_resolved() async {
     await _resolveTestUnit('''
 class C {
@@ -1646,23 +1695,6 @@
     }
   }
 
-  test_subtypes_partWithoutLibrary() async {
-    await _resolveTestUnit('''
-part of lib;
-
-class A {}
-class B extends A {}
-''');
-    ClassElement a = _findElement('A');
-
-    List<SubtypeResult> subtypes = await driver.search.subtypes(type: a);
-    expect(subtypes, hasLength(1));
-
-    SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
-    expect(b.libraryUri, testUri);
-    expect(b.id, '$testUri;$testUri;B');
-  }
-
   test_subtypes_discover() async {
     var pathT = _p('/test/lib/t.dart');
     var pathA = _p('/aaa/lib/a.dart');
@@ -1790,6 +1822,23 @@
     expect(c.id, endsWith('c.dart;C'));
   }
 
+  test_subtypes_partWithoutLibrary() async {
+    await _resolveTestUnit('''
+part of lib;
+
+class A {}
+class B extends A {}
+''');
+    ClassElement a = _findElement('A');
+
+    List<SubtypeResult> subtypes = await driver.search.subtypes(type: a);
+    expect(subtypes, hasLength(1));
+
+    SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
+    expect(b.libraryUri, testUri);
+    expect(b.id, '$testUri;$testUri;B');
+  }
+
   test_topLevelElements() async {
     await _resolveTestUnit('''
 class A {} // A