Return PartWithoutLibraryResult when a part without its library.

Change-Id: I5eb384d77c263b489b10e112a79115bf028e79af
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245081
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/analysis/notification_outline_test.dart b/pkg/analysis_server/test/analysis/notification_outline_test.dart
index 262673b..4347bad 100644
--- a/pkg/analysis_server/test/analysis/notification_outline_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_outline_test.dart
@@ -96,6 +96,12 @@
   }
 
   Future<void> test_libraryName_hasPartOfDirective() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library lib;
+
+part 'test.dart';
+''');
+
     addTestFile('''
 part of my.lib;
 ''');
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index de8f23e..8e86727 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -742,8 +742,8 @@
 }
 ''');
     await findElementReferences('fff(p) {}', false);
-    expect(results, hasLength(1));
-    assertHasResult(SearchResultKind.INVOCATION, 'fff(10);');
+    // A part without library, no results.
+    expect(results, isEmpty);
   }
 
   Future<void> test_parameter() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 0d839ec..f6e0668 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -2272,6 +2272,7 @@
     assertSuggestKeywords([]);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_part_of() async {
     addTestSource('part of foo;^');
     await computeSuggestions();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart
index 74236cce..7c1d58c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_parameter_required_test.dart
@@ -105,6 +105,7 @@
 ''');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_function_hasZero_partOfName_noLibrary() async {
     await resolveTestCode('''
 part of my_lib;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
index 31ee456..196a197 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
@@ -79,6 +79,7 @@
 ''', target: a);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_inPart_partOfName_noLibrary() async {
     await resolveTestCode('''
 part of my_lib;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
index af26bc4..0cc45cd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_field_test.dart
@@ -383,6 +383,7 @@
     });
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_inPart_self() async {
     await resolveTestCode('''
 part of lib;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
index 7566168..f7f443f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_getter_test.dart
@@ -326,6 +326,7 @@
     });
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_qualified_instance_inPart_self() async {
     await resolveTestCode('''
 part of lib;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_setter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_setter_test.dart
index fea7674..db18da2 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_setter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_setter_test.dart
@@ -320,6 +320,7 @@
     });
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49046')
   Future<void> test_qualified_instance_inPart_self() async {
     await resolveTestCode('''
 part of lib;
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 97198d9..200ebaf 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -195,6 +195,22 @@
   CompilationUnit get unit;
 }
 
+/// The type of [InvalidResult] returned when the file is a part, and its
+/// containing library is not known.
+///
+/// Clients may not extend, implement or mix-in this class.
+///
+/// TODO(scheglov) Add an error that points at the `part of` location.
+abstract class PartWithoutLibraryResult
+    implements
+        InvalidResult,
+        SomeErrorsResult,
+        SomeResolvedUnitResult,
+        SomeUnitElementResult {
+  /// The absolute and normalized path of the file.
+  String get path;
+}
+
 /// The result of building resolved AST(s) for the whole library.
 ///
 /// Clients may not extend, implement or mix-in this class.
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 522a0c4..1160d53 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -159,7 +159,7 @@
 
   /// The mapping from the files for which analysis was requested using
   /// [getResult] to the [Completer]s to report the result.
-  final _requestedFiles = <String, List<Completer<ResolvedUnitResult>>>{};
+  final _requestedFiles = <String, List<Completer<SomeResolvedUnitResult>>>{};
 
   /// The mapping from the files for which analysis was requested using
   /// [getResolvedLibrary] to the [Completer]s to report the result.
@@ -182,35 +182,17 @@
 
   /// The mapping from the files for which errors were requested using
   /// [getErrors] to the [Completer]s to report the result.
-  final _errorsRequestedFiles = <String, List<Completer<ErrorsResult>>>{};
-
-  /// The requests from [_errorsRequestedFiles] for files which were found to
-  /// be parts without known libraries, so delayed.
-  final _errorsRequestedParts = <String, List<Completer<ErrorsResult>>>{};
+  final _errorsRequestedFiles = <String, List<Completer<SomeErrorsResult>>>{};
 
   /// The mapping from the files for which the index was requested using
   /// [getIndex] to the [Completer]s to report the result.
   final _indexRequestedFiles =
-      <String, List<Completer<AnalysisDriverUnitIndex>>>{};
+      <String, List<Completer<AnalysisDriverUnitIndex?>>>{};
 
   /// The mapping from the files for which the unit element was requested using
   /// [getUnitElement] to the [Completer]s to report the result.
   final _unitElementRequestedFiles =
-      <String, List<Completer<UnitElementResult>>>{};
-
-  /// The mapping from the files for which the unit element was requested using
-  /// [getUnitElement], and which were found to be parts without known
-  /// libraries, to the [Completer]s to report the result.
-  final _unitElementRequestedParts =
-      <String, List<Completer<UnitElementResult>>>{};
-
-  /// The mapping from the files for which analysis was requested using
-  /// [getResult], and which were found to be parts without known libraries,
-  /// to the [Completer]s to report the result.
-  final _requestedParts = <String, List<Completer<ResolvedUnitResult>>>{};
-
-  /// The set of part files that are currently scheduled for analysis.
-  final _partsToAnalyze = <String>{};
+      <String, List<Completer<SomeUnitElementResult>>>{};
 
   /// The controller for the [results] stream.
   final _resultController = StreamController<Object>();
@@ -249,6 +231,11 @@
   /// Whether `dart:core` has been transitively discovered.
   bool _hasDartCoreDiscovered = false;
 
+  /// This flag is reset to `false` when a new file is added, because it
+  /// might be a library, so that some files that were disconnected parts
+  /// could be analyzed now.
+  bool _hasLibrariesDiscovered = false;
+
   /// If testing data is being retained, a pointer to the object that is
   /// retaining the testing data.  Otherwise `null`.
   final TestingData? testingData;
@@ -311,9 +298,7 @@
     return hasPendingFileChanges ||
         _fileTracker.hasChangedFiles ||
         _requestedFiles.isNotEmpty ||
-        _requestedParts.isNotEmpty ||
-        _fileTracker.hasPendingFiles ||
-        _partsToAnalyze.isNotEmpty;
+        _fileTracker.hasPendingFiles;
   }
 
   bool get hasPendingFileChanges => _pendingFileChanges.isNotEmpty;
@@ -455,11 +440,7 @@
     if (_fileTracker.hasPendingFiles) {
       return AnalysisDriverPriority.general;
     }
-    if (_errorsRequestedParts.isNotEmpty ||
-        _requestedParts.isNotEmpty ||
-        _partsToAnalyze.isNotEmpty ||
-        _unitElementRequestedParts.isNotEmpty ||
-        _pendingFileChangesCompleters.isNotEmpty) {
+    if (_pendingFileChangesCompleters.isNotEmpty) {
       return AnalysisDriverPriority.general;
     }
     return AnalysisDriverPriority.nothing;
@@ -627,9 +608,9 @@
       );
     }
 
-    var completer = Completer<ErrorsResult>();
+    var completer = Completer<SomeErrorsResult>();
     _errorsRequestedFiles
-        .putIfAbsent(path, () => <Completer<ErrorsResult>>[])
+        .putIfAbsent(path, () => <Completer<SomeErrorsResult>>[])
         .add(completer);
     _scheduler.notify(this);
     return completer.future;
@@ -699,9 +680,9 @@
     if (!_fsState.hasUri(path)) {
       return Future.value();
     }
-    var completer = Completer<AnalysisDriverUnitIndex>();
+    var completer = Completer<AnalysisDriverUnitIndex?>();
     _indexRequestedFiles
-        .putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex>>[])
+        .putIfAbsent(path, () => <Completer<AnalysisDriverUnitIndex?>>[])
         .add(completer);
     _scheduler.notify(this);
     return completer.future;
@@ -918,9 +899,9 @@
     }
 
     // Schedule analysis.
-    var completer = Completer<ResolvedUnitResult>();
+    var completer = Completer<SomeResolvedUnitResult>();
     _requestedFiles
-        .putIfAbsent(path, () => <Completer<ResolvedUnitResult>>[])
+        .putIfAbsent(path, () => <Completer<SomeResolvedUnitResult>>[])
         .add(completer);
     _scheduler.notify(this);
     return completer.future;
@@ -964,9 +945,9 @@
       );
     }
 
-    var completer = Completer<UnitElementResult>();
+    var completer = Completer<SomeUnitElementResult>();
     _unitElementRequestedFiles
-        .putIfAbsent(path, () => <Completer<UnitElementResult>>[])
+        .putIfAbsent(path, () => <Completer<SomeUnitElementResult>>[])
         .add(completer);
     _scheduler.notify(this);
     return completer.future;
@@ -1041,10 +1022,8 @@
 
   @override
   Future<void> performWork() async {
-    if (!_hasDartCoreDiscovered) {
-      _hasDartCoreDiscovered = true;
-      _discoverDartCore();
-    }
+    _discoverDartCore();
+    _discoverLibraries();
 
     if (_resolveForCompletionRequests.isNotEmpty) {
       final request = _resolveForCompletionRequests.removeLast();
@@ -1061,27 +1040,26 @@
 
     // Analyze a requested file.
     if (_requestedFiles.isNotEmpty) {
-      String path = _requestedFiles.keys.first;
+      final path = _requestedFiles.keys.first;
+      final completers = _requestedFiles.remove(path)!;
+      _fileTracker.fileWasAnalyzed(path);
       try {
-        var result = await _computeAnalysisResult(path, withUnit: true);
-        // If a part without a library, delay its analysis.
-        if (result == null) {
-          _requestedParts
-              .putIfAbsent(path, () => [])
-              .addAll(_requestedFiles.remove(path)!);
-          return;
+        final result = await _computeAnalysisResult(path, withUnit: true);
+        final SomeResolvedUnitResult unitResult;
+        if (result != null) {
+          unitResult = result.unitResult!;
+        } else {
+          unitResult = PartWithoutLibraryResultImpl(
+            path: path,
+          );
         }
-        // Notify the completers.
-        for (var completer in _requestedFiles.remove(path)!) {
-          completer.complete(result.unitResult!);
+        for (final completer in completers) {
+          completer.complete(unitResult);
         }
-        // Remove from to be analyzed and produce it now.
-        _fileTracker.fileWasAnalyzed(path);
-        _resultController.add(result.unitResult!);
+        _resultController.add(unitResult);
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
-        _fileTracker.fileWasAnalyzed(path);
-        for (var completer in _requestedFiles.remove(path)!) {
+        for (final completer in completers) {
           completer.completeError(exception, stackTrace);
         }
         _clearLibraryContextAfterException();
@@ -1112,14 +1090,10 @@
       var completers = _errorsRequestedFiles.remove(path)!;
       var result = await _computeErrors(
         path: path,
-        asIsIfPartWithoutLibrary: false,
       );
-      if (result != null) {
-        for (var completer in completers) {
-          completer.complete(result);
-        }
-      } else {
-        _errorsRequestedParts.putIfAbsent(path, () => []).addAll(completers);
+      result ??= PartWithoutLibraryResultImpl(path: path);
+      for (var completer in completers) {
+        completer.complete(result);
       }
       return;
     }
@@ -1127,7 +1101,7 @@
     // Process an index request.
     if (_indexRequestedFiles.isNotEmpty) {
       String path = _indexRequestedFiles.keys.first;
-      AnalysisDriverUnitIndex index = await _computeIndex(path);
+      final index = await _computeIndex(path);
       for (var completer in _indexRequestedFiles.remove(path)!) {
         completer.complete(index);
       }
@@ -1137,16 +1111,11 @@
     // Process a unit element request.
     if (_unitElementRequestedFiles.isNotEmpty) {
       String path = _unitElementRequestedFiles.keys.first;
-      UnitElementResult? result = await _computeUnitElement(path);
       var completers = _unitElementRequestedFiles.remove(path)!;
-      if (result != null) {
-        for (var completer in completers) {
-          completer.complete(result);
-        }
-      } else {
-        _unitElementRequestedParts
-            .putIfAbsent(path, () => [])
-            .addAll(completers);
+      SomeUnitElementResult? result = await _computeUnitElement(path);
+      result ??= PartWithoutLibraryResultImpl(path: path);
+      for (var completer in completers) {
+        completer.complete(result);
       }
       return;
     }
@@ -1186,7 +1155,14 @@
           try {
             var result = await _computeAnalysisResult(path, withUnit: true);
             if (result == null) {
-              _partsToAnalyze.add(path);
+              // We report an invalid result (instead of silently ignoring
+              // this disconnected part) so that the listener of the stream
+              // knows, and for example removes all errors.
+              _resultController.add(
+                PartWithoutLibraryResultImpl(
+                  path: path,
+                ),
+              );
             } else {
               _resultController.add(result.unitResult!);
             }
@@ -1208,7 +1184,11 @@
         var result = await _computeAnalysisResult(path,
             withUnit: false, skipIfSameSignature: true);
         if (result == null) {
-          _partsToAnalyze.add(path);
+          _resultController.add(
+            PartWithoutLibraryResultImpl(
+              path: path,
+            ),
+          );
         } else if (result.isUnchangedErrors) {
           // We found that the set of errors is the same as we produced the
           // last time, so we don't need to produce it again now.
@@ -1224,79 +1204,6 @@
       }
       return;
     }
-
-    // Analyze a requested part file.
-    if (_requestedParts.isNotEmpty) {
-      String path = _requestedParts.keys.first;
-      try {
-        var result = await _computeAnalysisResult(path,
-            withUnit: true, asIsIfPartWithoutLibrary: true);
-        result!;
-        // Notify the completers.
-        for (var completer in _requestedParts.remove(path)!) {
-          completer.complete(result.unitResult!);
-        }
-        // Remove from to be analyzed and produce it now.
-        _partsToAnalyze.remove(path);
-        _resultController.add(result.unitResult!);
-      } catch (exception, stackTrace) {
-        _reportException(path, exception, stackTrace);
-        _partsToAnalyze.remove(path);
-        for (var completer in _requestedParts.remove(path)!) {
-          completer.completeError(exception, stackTrace);
-        }
-        _clearLibraryContextAfterException();
-      }
-      return;
-    }
-
-    // Analyze a general part.
-    if (_partsToAnalyze.isNotEmpty) {
-      String path = _partsToAnalyze.first;
-      _partsToAnalyze.remove(path);
-      try {
-        var withUnit = _priorityFiles.contains(path);
-        if (withUnit) {
-          var result = await _computeAnalysisResult(path,
-              withUnit: true, asIsIfPartWithoutLibrary: true);
-          _resultController.add(result!.unitResult!);
-        } else {
-          var result = await _computeAnalysisResult(path,
-              withUnit: false, asIsIfPartWithoutLibrary: true);
-          _resultController.add(result!.errorsResult!);
-        }
-      } catch (exception, stackTrace) {
-        _reportException(path, exception, stackTrace);
-        _clearLibraryContextAfterException();
-      }
-      return;
-    }
-
-    // Process a unit element request for a part.
-    if (_unitElementRequestedParts.isNotEmpty) {
-      String path = _unitElementRequestedParts.keys.first;
-      var result =
-          await _computeUnitElement(path, asIsIfPartWithoutLibrary: true);
-      result!;
-      for (var completer in _unitElementRequestedParts.remove(path)!) {
-        completer.complete(result);
-      }
-      return;
-    }
-
-    // Compute errors in a part.
-    if (_errorsRequestedParts.isNotEmpty) {
-      var path = _errorsRequestedParts.keys.first;
-      var completers = _errorsRequestedParts.remove(path)!;
-      var result = await _computeErrors(
-        path: path,
-        asIsIfPartWithoutLibrary: true,
-      );
-      for (var completer in completers) {
-        completer.complete(result);
-      }
-      return;
-    }
   }
 
   /// Remove the file with the given [path] from the list of files to analyze.
@@ -1496,24 +1403,16 @@
     });
   }
 
-  Future<ErrorsResult?> _computeErrors({
+  Future<SomeErrorsResult?> _computeErrors({
     required String path,
-    required bool asIsIfPartWithoutLibrary,
   }) async {
-    var analysisResult = await _computeAnalysisResult(path,
-        withUnit: false, asIsIfPartWithoutLibrary: asIsIfPartWithoutLibrary);
-
-    if (analysisResult == null) {
-      return null;
-    }
-
-    return analysisResult.errorsResult;
+    var analysisResult = await _computeAnalysisResult(path, withUnit: false);
+    return analysisResult?.errorsResult;
   }
 
-  Future<AnalysisDriverUnitIndex> _computeIndex(String path) async {
-    var analysisResult = await _computeAnalysisResult(path,
-        withUnit: false, asIsIfPartWithoutLibrary: true);
-    return analysisResult!._index!;
+  Future<AnalysisDriverUnitIndex?> _computeIndex(String path) async {
+    var analysisResult = await _computeAnalysisResult(path, withUnit: false);
+    return analysisResult?._index;
   }
 
   /// Return the newly computed resolution result of the library with the
@@ -1646,6 +1545,11 @@
   /// The current workaround for this is to discover `dart:core` before any
   /// analysis.
   void _discoverDartCore() {
+    if (_hasDartCoreDiscovered) {
+      return;
+    }
+    _hasDartCoreDiscovered = true;
+
     _fsState.getFileForUri(Uri.parse('dart:core')).map(
       (file) {
         file?.transitiveFiles;
@@ -1654,6 +1558,17 @@
     );
   }
 
+  void _discoverLibraries() {
+    if (_hasLibrariesDiscovered) {
+      return;
+    }
+    _hasLibrariesDiscovered = true;
+
+    for (final path in _fileTracker.addedFiles) {
+      _fsState.getFileForPath(path);
+    }
+  }
+
   void _fillSalt() {
     _fillSaltForUnlinked();
     _fillSaltForElements();
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index 0c957ae..cef3e18 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -139,6 +139,15 @@
   LineInfo get lineInfo => unit.lineInfo;
 }
 
+class PartWithoutLibraryResultImpl implements PartWithoutLibraryResult {
+  @override
+  final String path;
+
+  PartWithoutLibraryResultImpl({
+    required this.path,
+  });
+}
+
 class ResolvedForCompletionResultImpl {
   final AnalysisSession analysisSession;
   final String path;
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 4d58c07..5f260ff 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -6019,6 +6019,7 @@
       implicitly uses the same version as the defining compilation unit:
 
       ```dart
+      %uri="lib/part.dart"
       part of 'test.dart';
       ```
 
@@ -10939,6 +10940,7 @@
       by URI:
 
       ```dart
+      %uri="lib/part_file.dart"
       part of 'test.dart';
       ```
   POSITIONAL_SUPER_FORMAL_PARAMETER_WITH_POSITIONAL_ARGUMENT:
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 870d899..82158be 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -270,15 +270,20 @@
   }
 
   test_annotation_onDirective_partOf() async {
-    newFile('$testPackageLibPath/a.dart', r'''
+    final a = newFile('$testPackageLibPath/a.dart', r'''
 part 'test.dart';
 ''');
+
     addTestFile(r'''
 @a
 part of 'a.dart';
 
 const a = 1;
 ''');
+
+    // Make sure that the part knows its library.
+    contextFor(a.path).currentSession.getParsedUnit(a.path);
+
     await resolveTestFile();
 
     var directive = findNode.partOf('a.dart');
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 60fd9f7..5a963a6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -2734,21 +2734,15 @@
   }
 
   test_part_getResult_noLibrary() async {
-    var c = convertPath('/test/lib/c.dart');
-    newFile(c, r'''
+    final c = newFile('/test/lib/c.dart', r'''
 part of a;
 class C {}
-var a = new A();
-var b = new B();
 ''');
 
-    driver.addFile(c);
-
-    // There is no library which c.dart is a part of, so it has unresolved
-    // A and B references.
-    ResolvedUnitResult result = await driver.getResultValid(c);
-    expect(result.errors, isNotEmpty);
-    expect(result.unit, isNotNull);
+    // There is no library which c.dart is a part of, so invalid result.
+    final result = await driver.getResult(c.path);
+    result as PartWithoutLibraryResult;
+    expect(result.path, c.path);
   }
 
   test_part_getUnitElement_afterLibrary() async {
@@ -2829,28 +2823,14 @@
   }
 
   test_part_getUnitElement_noLibrary() async {
-    var c = convertPath('/test/lib/c.dart');
-    newFile(c, r'''
+    final c = newFile('/test/lib/c.dart', r'''
 part of a;
-var a = new A();
-var b = new B();
 ''');
 
-    driver.addFile(c);
-
-    // We don't know the library of c.dart, but we should get a result.
-    // The types "A" and "B" are unresolved.
-    {
-      var result = await driver.getUnitElement(c);
-      result as UnitElementResult;
-      var partUnit = result.element;
-
-      expect(partUnit.topLevelVariables[0].name, 'a');
-      assertType(partUnit.topLevelVariables[0].type, 'dynamic');
-
-      expect(partUnit.topLevelVariables[1].name, 'b');
-      assertType(partUnit.topLevelVariables[1].type, 'dynamic');
-    }
+    // We don't know the library of c.dart, so invalid result.
+    var result = await driver.getUnitElement(c.path);
+    result as PartWithoutLibraryResult;
+    expect(result.path, c.path);
   }
 
   test_part_results_afterLibrary() async {
@@ -2889,15 +2869,16 @@
 
     // Update a.dart so that c.dart is not a part.
     {
+      allResults.clear();
+
       modifyFile(a, '// does not use c.dart anymore');
       driver.changeFile(a);
       await waitForIdleWithoutExceptions();
 
-      // Now c.dart does not have a library context, so A and B cannot be
-      // resolved, so there are errors.
-      var result =
-          allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
-      expect(result.errors, isNotEmpty);
+      // Now c.dart does not know the library, so invalid result.
+      allResults
+          .whereType<PartWithoutLibraryResult>()
+          .lastWhere((r) => r.path == c);
     }
   }
 
@@ -2949,11 +2930,29 @@
 
     await waitForIdleWithoutExceptions();
 
-    // There is no library which c.dart is a part of, so it has unresolved
-    // A and B references.
-    var result =
-        allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
-    expect(result.errors, isNotEmpty);
+    // We don't know the library for `c.dart`, so report an invalid result.
+    allResults
+        .whereType<PartWithoutLibraryResult>()
+        .lastWhere((result) => result.path == c);
+  }
+
+  test_part_results_noLibrary_priority() async {
+    var c = newFile('/test/lib/c.dart', r'''
+part of a;
+class C {}
+var a = new A();
+var b = new B();
+''');
+
+    driver.addFile(c.path);
+    driver.priorityFiles = [c.path];
+
+    await waitForIdleWithoutExceptions();
+
+    // We don't know the library for `c.dart`, so report an invalid result.
+    allResults
+        .whereType<PartWithoutLibraryResult>()
+        .lastWhere((result) => result.path == c.path);
   }
 
   test_part_results_priority_beforeLibrary() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index ba431f2..490c069 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -2526,24 +2526,6 @@
     expect(c.id, endsWith('c.dart;C'));
   }
 
-  test_subtypes_class_partWithoutLibrary() async {
-    await resolveTestCode('''
-part of lib;
-
-class A {}
-class B extends A {}
-''');
-    var a = findElement.class_('A');
-
-    List<SubtypeResult> subtypes =
-        await driver.search.subtypes(SearchedFiles(), type: a);
-    expect(subtypes, hasLength(1));
-
-    SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
-    expect(b.libraryUri, testUriStr);
-    expect(b.id, '$testUriStr;$testUriStr;B');
-  }
-
   test_subtypes_enum() async {
     await resolveTestCode('''
 class A {}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
index 90054d2..479a695 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_async_exported_from_core_test.dart
@@ -2,9 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../dart/resolution/context_collection_resolution.dart';
 import 'sdk_constraint_verifier_support.dart';
 
 main() {
@@ -49,14 +52,31 @@
   }
 
   test_equals_implicitImportOfCore_inPart() async {
-    newFile('/lib.dart', '''
+    writeTestPackagePubspecYamlFile(
+      PubspecYamlFileConfig(
+        sdkVersion: '>=2.1.0',
+      ),
+    );
+
+    final lib = newFile('$testPackageLibPath/lib.dart', '''
 library lib;
+
+part 'a.dart';
 ''');
-    await verifyVersion('2.1.0', '''
+
+    final a = newFile('$testPackageLibPath/a.dart', r'''
 part of lib;
 
 Future<int> zero() async => 0;
 ''');
+
+    final analysisSession = contextFor(lib.path).currentSession;
+    final resolvedLibrary = await analysisSession.getResolvedLibrary(lib.path);
+    resolvedLibrary as ResolvedLibraryResult;
+
+    final resolvedPart = resolvedLibrary.units.last;
+    expect(resolvedPart.path, a.path);
+    assertErrorsInList(resolvedPart.errors, []);
   }
 
   test_lessThan_explicitImportOfAsync() async {
@@ -97,14 +117,31 @@
   }
 
   test_lessThan_implicitImportOfCore_inPart() async {
-    newFile('/lib.dart', '''
+    writeTestPackagePubspecYamlFile(
+      PubspecYamlFileConfig(
+        sdkVersion: '>=2.0.0',
+      ),
+    );
+
+    final lib = newFile('$testPackageLibPath/lib.dart', '''
 library lib;
+
+part 'a.dart';
 ''');
-    await verifyVersion('2.0.0', '''
+
+    final a = newFile('$testPackageLibPath/a.dart', r'''
 part of lib;
 
 Future<int> zero() async => 0;
-''', expectedErrors: [
+''');
+
+    final analysisSession = contextFor(lib.path).currentSession;
+    final resolvedLibrary = await analysisSession.getResolvedLibrary(lib.path);
+    resolvedLibrary as ResolvedLibraryResult;
+
+    final resolvedPart = resolvedLibrary.units.last;
+    expect(resolvedPart.path, a.path);
+    assertErrorsInList(resolvedPart.errors, [
       error(HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE, 14, 6),
     ]);
   }
diff --git a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
index 3c42768..f4b9318 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
@@ -3068,16 +3068,17 @@
         int T1;
         F1() { }
         class X {X.c(); X._d(); z() {}}''');
-    addSource('/home/test/lib/a.dart', '''
+    final a = newFile('/home/test/lib/a.dart', '''
         library libA;
         import 'b.dart';
-        part "$testFile";
+        part 'test.dart';
         class A { }
         var m;''');
     addTestSource('''
         part of libA;
         class B { B.bar(int x); }
         main() {new ^}''');
+    await resolveFile(a.path);
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 8609209..e1df28b 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -5730,10 +5730,9 @@
   Future<void> test_part_metadata() async {
     var pathContext = resourceProvider.pathContext;
     addSource(pathContext.join(pathContext.dirname(testFile), 'part.dart'), '''
-part of test;
+part of 'test.dart';
 ''');
     await analyze('''
-library test;
 @deprecated
 part 'part.dart';
 ''');
@@ -5744,10 +5743,13 @@
   Future<void> test_part_of_identifier() async {
     var pathContext = resourceProvider.pathContext;
     var testFileName = pathContext.basename(testFile);
-    addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
+    var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
+    addSource(libPath, '''
 library test;
 part '$testFileName';
 ''');
+    // Discover the library for the part.
+    session.getParsedUnit(libPath);
     await analyze('''
 part of test;
 ''');
@@ -5758,13 +5760,16 @@
   Future<void> test_part_of_metadata() async {
     var pathContext = resourceProvider.pathContext;
     var testFileName = pathContext.basename(testFile);
-    addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
-library test;
+    var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
+    addSource(libPath, '''
 part '$testFileName';
 ''');
+    // TODO(scheglov) This should not be necessary, we use URI, so can find it.
+    // Discover the library for the part.
+    session.getParsedUnit(libPath);
     await analyze('''
 @deprecated
-part of test;
+part of 'lib.dart';
 ''');
     // No assertions needed; the AnnotationTracker mixin verifies that the
     // metadata was visited.
@@ -5773,9 +5778,13 @@
   Future<void> test_part_of_path() async {
     var pathContext = resourceProvider.pathContext;
     var testFileName = pathContext.basename(testFile);
-    addSource(pathContext.join(pathContext.dirname(testFile), 'lib.dart'), '''
+    var libPath = pathContext.join(pathContext.dirname(testFile), 'lib.dart');
+    addSource(libPath, '''
 part '$testFileName';
 ''');
+    // TODO(scheglov) This should not be necessary, we use URI, so can find it.
+    // Discover the library for the part.
+    session.getParsedUnit(libPath);
     await analyze('''
 part of 'lib.dart';
 ''');