Version 2.15.0-300.0.dev

Merge commit '7ff9282868c7a8246f28f58a0725e33735b1148d' into 'dev'
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 10b3a53..cfc49eb 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -302,9 +302,9 @@
     performance.runAsync(
       'request',
       (performance) async {
-        var resolvedUnit = await performance.runAsync(
+        var resolvedUnit = performance.run(
           'resolveForCompletion',
-          (performance) async {
+          (performance) {
             return server.resolveForCompletion(
               path: file,
               offset: offset,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 52456d4..53550d8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -10,20 +10,14 @@
 import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/workspace/pub.dart';
 import 'package:collection/collection.dart';
-import 'package:meta/meta.dart';
 
 /// A contributor of suggestions from not yet imported libraries.
 class NotImportedContributor extends DartCompletionContributor {
-  /// Tests set this function to abort the current request.
-  @visibleForTesting
-  static void Function(FileState)? onFile;
-
   final CompletionBudget budget;
   final Map<protocol.CompletionSuggestion, Uri> notImportedSuggestions;
 
@@ -36,7 +30,6 @@
 
   @override
   Future<void> computeSuggestions() async {
-    var analysisSession = request.analysisSession;
     var analysisDriver = request.analysisContext.driver;
 
     var fsState = analysisDriver.fsState;
@@ -53,9 +46,6 @@
 
     var knownFiles = fsState.knownFiles.toList();
     for (var file in knownFiles) {
-      onFile?.call(file);
-      request.checkAborted();
-
       if (budget.isEmpty) {
         return;
       }
@@ -64,12 +54,12 @@
         continue;
       }
 
-      var elementResult = await analysisSession.getLibraryByUri(file.uriStr);
-      if (elementResult is! LibraryElementResult) {
+      var element = analysisDriver.getLibraryByFile(file);
+      if (element == null) {
         continue;
       }
 
-      var exportNamespace = elementResult.element.exportNamespace;
+      var exportNamespace = element.exportNamespace;
       var exportElements = exportNamespace.definedNames.values.toList();
 
       builder.laterReplacesEarlier = false;
@@ -155,14 +145,15 @@
 
   @override
   bool shouldInclude(FileState file) {
-    var uri = file.uri;
-    if (uri.isScheme('dart')) {
+    var uri = file.uriProperties;
+    if (uri.isDart) {
       return true;
     }
 
     // Normally only package URIs are available.
     // But outside of lib/ we allow any files of this package.
-    if (!uri.isScheme('package')) {
+    var packageName = uri.packageName;
+    if (packageName == null) {
       if (targetInLib) {
         return false;
       } else {
@@ -172,20 +163,13 @@
       }
     }
 
-    // Sanity check.
-    var uriPathSegments = uri.pathSegments;
-    if (uriPathSegments.length < 2) {
-      return false;
-    }
-
     // Any `package:` library from the same package.
-    var packageName = uriPathSegments[0];
     if (packageName == targetPackageName) {
       return true;
     }
 
     // If not the same package, must be public.
-    if (uriPathSegments[1] == 'src') {
+    if (uri.isSrc) {
       return false;
     }
 
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 7782757..c3ec9c3 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -11,7 +11,6 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
-import 'package:analysis_server/src/services/completion/dart/not_imported_contributor.dart';
 import 'package:analysis_server/src/utilities/mocks.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/service.dart';
@@ -229,10 +228,6 @@
     completionDomain.budgetDuration = const Duration(seconds: 30);
   }
 
-  void tearDown() {
-    NotImportedContributor.onFile = null;
-  }
-
   Future<void> test_abort_onAnotherCompletionRequest() async {
     var abortedIdSet = <String>{};
     server.discardedRequests.stream.listen((request) {
@@ -300,38 +295,6 @@
       ..suggestions.assertEmpty();
   }
 
-  Future<void> test_notImported_abort() async {
-    await _configureWithWorkspaceRoot();
-
-    NotImportedContributor.onFile = (file) {
-      if (file.uriStr == 'dart:math') {
-        unawaited(
-          _getSuggestions(
-            path: convertPath(testFilePath),
-            completionOffset: 0,
-            maxResults: 100,
-          ),
-        );
-      }
-    };
-
-    var responseValidator = await _getTestCodeSuggestions('''
-void f() {
-  Rand^
-}
-''');
-
-    responseValidator
-      ..assertIncomplete()
-      ..assertReplacementBack(4)
-      ..assertLibrariesToImport(includes: [], excludes: [
-        'dart:core',
-        'dart:math',
-      ]);
-
-    responseValidator.suggestions.assertEmpty();
-  }
-
   Future<void> test_notImported_dart() async {
     await _configureWithWorkspaceRoot();
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index fee6a89..b1b1ca0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
@@ -688,6 +689,22 @@
     return completer.future;
   }
 
+  /// Return [LibraryElementResult] for the given [file], or `null` if the
+  /// file is a part.
+  LibraryElement? getLibraryByFile(FileState file) {
+    if (file.isPart) {
+      return null;
+    }
+
+    var element = libraryContext.getLibraryElementIfReady(file.uriStr);
+    if (element != null) {
+      return element;
+    }
+
+    libraryContext.load2(file);
+    return libraryContext.getLibraryElement(file.uri);
+  }
+
   /// Return a [Future] that completes with [LibraryElementResult] for the given
   /// [uri], which is either resynthesized from the provided external summary
   /// store, or built for a file to which the given [uri] is resolved.
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index f0f35eb..b728d00 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -94,6 +94,9 @@
   /// The absolute URI of the file.
   final Uri uri;
 
+  /// Properties of the [uri].
+  final FileUriProperties uriProperties;
+
   /// The [Source] of the file with the [uri].
   final Source source;
 
@@ -148,7 +151,7 @@
     this.workspacePackage,
     this._contextFeatureSet,
     this.packageLanguageVersion,
-  );
+  ) : uriProperties = FileUriProperties(uri);
 
   /// The unlinked API signature of the file.
   Uint8List get apiSignature => _apiSignature!;
@@ -971,3 +974,46 @@
         .toSet();
   }
 }
+
+/// Precomputed properties of a file URI, used because [Uri] is relatively
+/// expensive to work with, if we do this thousand times.
+class FileUriProperties {
+  static const int _isDart = 1 << 0;
+  static const int _isSrc = 1 << 1;
+
+  final int _flags;
+  final String? packageName;
+
+  factory FileUriProperties(Uri uri) {
+    if (uri.isScheme('dart')) {
+      return const FileUriProperties._dart();
+    } else if (uri.isScheme('package')) {
+      var segments = uri.pathSegments;
+      if (segments.length >= 2) {
+        return FileUriProperties._package(
+          packageName: segments[0],
+          isSrc: segments[1] == 'src',
+        );
+      }
+    }
+    return const FileUriProperties._unknown();
+  }
+
+  const FileUriProperties._dart()
+      : _flags = _isDart,
+        packageName = null;
+
+  FileUriProperties._package({
+    required String packageName,
+    required bool isSrc,
+  })  : _flags = isSrc ? _isSrc : 0,
+        packageName = packageName;
+
+  const FileUriProperties._unknown()
+      : _flags = 0,
+        packageName = null;
+
+  bool get isDart => (_flags & _isDart) != 0;
+
+  bool get isSrc => (_flags & _isSrc) != 0;
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index dbdb140..4795da1 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -81,6 +81,11 @@
     return elementFactory.libraryOfUri2('$uri');
   }
 
+  /// Return [LibraryElement] if it is ready.
+  LibraryElement? getLibraryElementIfReady(String uriStr) {
+    return elementFactory.libraryOfUriIfReady(uriStr);
+  }
+
   /// We are about to discard this context, mark all libraries invalid.
   void invalidAllLibraries() {
     elementFactory.invalidateAllLibraries();
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 3833cc9..b91377d 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -180,11 +180,18 @@
   LibraryElementImpl libraryOfUri2(String uriStr) {
     var element = libraryOfUri(uriStr);
     if (element == null) {
+      libraryOfUri(uriStr);
       throw StateError('No library: $uriStr');
     }
     return element;
   }
 
+  /// Return the [LibraryElementImpl] if it is ready.
+  LibraryElementImpl? libraryOfUriIfReady(String uriStr) {
+    var element = rootReference.getChild(uriStr).element;
+    return element is LibraryElementImpl ? element : null;
+  }
+
   /// We have linked the bundle, and need to disconnect its libraries, so
   /// that the client can re-add the bundle, this time read from bytes.
   void removeBundle(Set<String> uriStrSet) {
diff --git a/pkg/analyzer/lib/src/util/performance/operation_performance.dart b/pkg/analyzer/lib/src/util/performance/operation_performance.dart
index 3a090d2..3d5ac61b 100644
--- a/pkg/analyzer/lib/src/util/performance/operation_performance.dart
+++ b/pkg/analyzer/lib/src/util/performance/operation_performance.dart
@@ -155,12 +155,9 @@
   ) async {
     var child = _existingOrNewChild(name);
     child._timer.start();
-
-    try {
-      return await operation(child);
-    } finally {
-      child._timer.stop();
-    }
+    var result = await operation(child);
+    child._timer.stop();
+    return result;
   }
 
   @override
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index b1f2a75..5a09829 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -143,7 +143,7 @@
       );
     }
 
-    return elementFactory.libraryOfUri('${source.uri}')!;
+    return elementFactory.libraryOfUri2('${source.uri}');
   }
 
   void setUp() {
diff --git a/tools/VERSION b/tools/VERSION
index dc9f248..35e81ca 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 299
+PRERELEASE 300
 PRERELEASE_PATCH 0
\ No newline at end of file