Version 2.18.0-58.0.dev

Merge commit 'eabec1c6a554a3cc13dcd41a09675ec8cf79d3e2' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index c044e59..2878d4e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -130,7 +130,6 @@
             offset,
             triggerCharacter,
             token,
-            maxResults: maxResults,
           );
         },
       );
@@ -294,9 +293,8 @@
     OperationPerformanceImpl performance,
     int offset,
     String? triggerCharacter,
-    CancellationToken token, {
-    required int maxResults,
-  }) async {
+    CancellationToken token,
+  ) async {
     final useSuggestionSets =
         suggestFromUnimportedLibraries && capabilities.applyEdit;
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 97707e5..e1c9a9c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -166,6 +166,9 @@
   final _requestedLibraries =
       <String, List<Completer<ResolvedLibraryResult>>>{};
 
+  /// The queue of requests for completion.
+  final List<_ResolveForCompletionRequest> _resolveForCompletionRequests = [];
+
   /// The task that discovers available files.  If this field is not `null`,
   /// and the task is not completed, it should be performed and completed
   /// before any name searching task.
@@ -401,6 +404,9 @@
 
   @override
   AnalysisDriverPriority get workPriority {
+    if (_resolveForCompletionRequests.isNotEmpty) {
+      return AnalysisDriverPriority.completion;
+    }
     if (_requestedFiles.isNotEmpty) {
       return AnalysisDriverPriority.interactive;
     }
@@ -1044,6 +1050,19 @@
       _discoverDartCore();
     }
 
+    if (_resolveForCompletionRequests.isNotEmpty) {
+      final request = _resolveForCompletionRequests.removeLast();
+      try {
+        final result = _resolveForCompletion(request);
+        request.completer.complete(result);
+      } catch (exception, stackTrace) {
+        _reportException(request.path, exception, stackTrace);
+        request.completer.completeError(exception, stackTrace);
+        _clearLibraryContextAfterException();
+      }
+      return;
+    }
+
     // Analyze a requested file.
     if (_requestedFiles.isNotEmpty) {
       String path = _requestedFiles.keys.first;
@@ -1311,54 +1330,14 @@
     required int offset,
     required OperationPerformanceImpl performance,
   }) async {
-    if (!_isAbsolutePath(path)) {
-      return null;
-    }
-
-    if (!_fsState.hasUri(path)) {
-      return null;
-    }
-
-    // Process pending changes.
-    while (_fileTracker.verifyChangedFilesIfNeeded()) {}
-
-    var file = _fsState.getFileForPath(path);
-
-    var library = file.isPart ? file.library : file;
-    if (library == null) {
-      return null;
-    }
-
-    await libraryContext.load(library);
-    var unitElement = libraryContext.computeUnitElement(library, file)
-        as CompilationUnitElementImpl;
-
-    var analysisResult = LibraryAnalyzer(
-      analysisOptions as AnalysisOptionsImpl,
-      declaredVariables,
-      sourceFactory,
-      libraryContext.elementFactory.libraryOfUri2(library.uriStr),
-      libraryContext.elementFactory.analysisSession.inheritanceManager,
-      library,
-      testingData: testingData,
-    ).analyzeForCompletion(
-      file: file,
+    final request = _ResolveForCompletionRequest(
+      path: path,
       offset: offset,
-      unitElement: unitElement,
       performance: performance,
     );
-
-    return ResolvedForCompletionResultImpl(
-      analysisSession: currentSession,
-      path: path,
-      uri: file.uri,
-      exists: file.exists,
-      content: file.content,
-      lineInfo: file.lineInfo,
-      parsedUnit: analysisResult.parsedUnit,
-      unitElement: unitElement,
-      resolvedNodes: analysisResult.resolvedNodes,
-    );
+    _resolveForCompletionRequests.add(request);
+    _scheduler.notify(this);
+    return request.completer.future;
   }
 
   void _addDeclaredVariablesToSignature(ApiSignature buffer) {
@@ -1869,6 +1848,57 @@
     );
   }
 
+  Future<ResolvedForCompletionResultImpl?> _resolveForCompletion(
+    _ResolveForCompletionRequest request,
+  ) async {
+    final path = request.path;
+    if (!_isAbsolutePath(path)) {
+      return null;
+    }
+
+    if (!_fsState.hasUri(path)) {
+      return null;
+    }
+
+    var file = _fsState.getFileForPath(path);
+
+    var library = file.isPart ? file.library : file;
+    if (library == null) {
+      return null;
+    }
+
+    await libraryContext.load(library);
+    var unitElement = libraryContext.computeUnitElement(library, file)
+        as CompilationUnitElementImpl;
+
+    var analysisResult = LibraryAnalyzer(
+      analysisOptions as AnalysisOptionsImpl,
+      declaredVariables,
+      sourceFactory,
+      libraryContext.elementFactory.libraryOfUri2(library.uriStr),
+      libraryContext.elementFactory.analysisSession.inheritanceManager,
+      library,
+      testingData: testingData,
+    ).analyzeForCompletion(
+      file: file,
+      offset: request.offset,
+      unitElement: unitElement,
+      performance: request.performance,
+    );
+
+    return ResolvedForCompletionResultImpl(
+      analysisSession: currentSession,
+      path: path,
+      uri: file.uri,
+      exists: file.exists,
+      content: file.content,
+      lineInfo: file.lineInfo,
+      parsedUnit: analysisResult.parsedUnit,
+      unitElement: unitElement,
+      resolvedNodes: analysisResult.resolvedNodes,
+    );
+  }
+
   /// Serialize the given [resolvedUnit] errors and index into bytes.
   Uint8List _serializeResolvedUnit(
       CompilationUnit resolvedUnit, List<AnalysisError> errors) {
@@ -2002,7 +2032,8 @@
   generalChanged,
   changedFiles,
   priority,
-  interactive
+  interactive,
+  completion
 }
 
 /// Instances of this class schedule work in multiple [AnalysisDriver]s so that
@@ -2618,3 +2649,16 @@
     return true;
   }
 }
+
+class _ResolveForCompletionRequest {
+  final String path;
+  final int offset;
+  final OperationPerformanceImpl performance;
+  final Completer<ResolvedForCompletionResultImpl?> completer = Completer();
+
+  _ResolveForCompletionRequest({
+    required this.path,
+    required this.offset,
+    required this.performance,
+  });
+}
diff --git a/pkg/analyzer/lib/src/utilities/extensions/stream.dart b/pkg/analyzer/lib/src/utilities/extensions/stream.dart
new file mode 100644
index 0000000..a310cab
--- /dev/null
+++ b/pkg/analyzer/lib/src/utilities/extensions/stream.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// 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 'dart:async';
+
+class _WhereTypeStreamSink<S, T> implements EventSink<S> {
+  final EventSink<T> _sink;
+
+  _WhereTypeStreamSink(this._sink);
+
+  @override
+  void add(S data) {
+    if (data is T) {
+      _sink.add(data);
+    }
+  }
+
+  @override
+  void addError(e, [StackTrace? stackTrace]) => _sink.addError(e, stackTrace);
+
+  @override
+  void close() => _sink.close();
+}
+
+class _WhereTypeStreamTransformer<S, T> extends StreamTransformerBase<S, T> {
+  @override
+  Stream<T> bind(Stream<S> stream) => Stream.eventTransformed(
+      stream, (sink) => _WhereTypeStreamSink<S, T>(sink));
+}
+
+extension StreamExtension<T> on Stream<T> {
+  Stream<S> whereType<S>() => transform(_WhereTypeStreamTransformer<T, S>());
+}
diff --git a/pkg/analyzer/test/src/utilities/extensions/stream_test.dart b/pkg/analyzer/test/src/utilities/extensions/stream_test.dart
new file mode 100644
index 0000000..bf63f75
--- /dev/null
+++ b/pkg/analyzer/test/src/utilities/extensions/stream_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// 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/src/utilities/extensions/stream.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(StreamExtensionTest);
+  });
+}
+
+@reflectiveTest
+class StreamExtensionTest {
+  test_whereType() async {
+    var result = await Stream<Object?>.fromIterable([0, '1', 2])
+        .whereType<int>()
+        .toList();
+    expect(result, [0, 2]);
+  }
+}
diff --git a/pkg/analyzer/test/src/utilities/extensions/test_all.dart b/pkg/analyzer/test/src/utilities/extensions/test_all.dart
index e8928d7..8beb97b 100644
--- a/pkg/analyzer/test/src/utilities/extensions/test_all.dart
+++ b/pkg/analyzer/test/src/utilities/extensions/test_all.dart
@@ -5,11 +5,13 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'collection_test.dart' as collection;
+import 'stream_test.dart' as stream;
 import 'string_test.dart' as string;
 
 main() {
   defineReflectiveSuite(() {
     collection.main();
+    stream.main();
     string.main();
   }, name: 'extensions');
 }
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index d4d2864..86c2bf8 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -5,6 +5,7 @@
 #include "platform/globals.h"
 
 #include "include/dart_tools_api.h"
+#include "platform/utils.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
@@ -23,7 +24,7 @@
     free(const_cast<char*>(test_output_));
     test_output_ = NULL;
   }
-  test_output_ = strdup(buffer);
+  test_output_ = Utils::StrDup(buffer);
 
   // Also print to stdout to see the overall result.
   OS::PrintErr("%s", test_output_);
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index 483eaba..d1c087d 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -4,6 +4,7 @@
 
 #include "vm/tags.h"
 
+#include "platform/utils.h"
 #include "vm/isolate.h"
 #include "vm/json_stream.h"
 #include "vm/native_entry.h"
@@ -159,7 +160,7 @@
       return;
     }
   }
-  subscribed_tags_.Add(strdup(tag));
+  subscribed_tags_.Add(Utils::StrDup(tag));
 }
 
 void UserTags::RemoveStreamableTagName(const char* tag) {
diff --git a/tools/VERSION b/tools/VERSION
index a15f79a..f388a5b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 57
+PRERELEASE 58
 PRERELEASE_PATCH 0
\ No newline at end of file