Version 2.17.0-33.0.dev

Merge commit '3b440de0d115ffc26c6efdd8fd84c8f7db7ea78f' into 'dev'
diff --git a/DEPS b/DEPS
index fafb7f0..b13d2dc 100644
--- a/DEPS
+++ b/DEPS
@@ -107,10 +107,10 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "08b0294d0a500d5c02168ef57dcb8868d0c3cb48",
+  "dart_style_rev": "6f894c0ca33686122be9085f06e5b9bf6ad55262",
 
   "dartdoc_rev" : "f9cfab1b84176873c80b89e7c8b54c669344f9ed",
-  "devtools_rev" : "85932bb66aa782c4b2c528be7718960bf256ffb7",
+  "devtools_rev" : "013958fbd45351e5975068756b7b9114465a7f98",
   "ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
   "fixnum_rev": "848341f061359ef7ddc0cad472c2ecbb036b28ac",
   "file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index 68e112e..b5d7f7d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -50,16 +50,22 @@
     final content = StringBuffer();
     const divider = '---';
 
-    // Description.
-    if (hover.elementDescription != null) {
+    // Description + Types.
+    final elementDescription = hover.elementDescription;
+    final staticType = hover.staticType;
+    final isDeprecated = hover.isDeprecated ?? false;
+    if (elementDescription != null) {
       content.writeln('```dart');
-      if (hover.isDeprecated ?? false) {
+      if (isDeprecated) {
         content.write('(deprecated) ');
       }
       content
-        ..writeln(hover.elementDescription)
+        ..writeln(elementDescription)
         ..writeln('```');
     }
+    if (staticType != null) {
+      content.writeln('Type: `$staticType`');
+    }
 
     // Source library.
     final containingLibraryName = hover.containingLibraryName;
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 2c3a578..ab3ae47 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -2034,6 +2034,17 @@
     });
   }
 
+  Future<void> test_inComment_block_beforeDartDoc() async {
+    addTestFile('''
+/* text ^ */
+
+/// some doc comments
+class SomeClass {}
+  ''');
+    await getSuggestions();
+    expect(suggestions, isEmpty);
+  }
+
   Future<void> test_inComment_block_beforeNode() async {
     addTestFile('''
   void f(aaa, bbb) {
@@ -2059,6 +2070,17 @@
     expect(suggestions, isEmpty);
   }
 
+  Future<void> test_inComment_endOfLine_beforeDartDoc() async {
+    addTestFile('''
+// text ^
+
+/// some doc comments
+class SomeClass {}
+  ''');
+    await getSuggestions();
+    expect(suggestions, isEmpty);
+  }
+
   Future<void> test_inComment_endOfLine_beforeNode() async {
     addTestFile('''
   void f(aaa, bbb) {
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 19c80c0..bb8423b 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -68,6 +68,7 @@
 ```dart
 String abc
 ```
+Type: `String`
 *package:test/main.dart*
 
 ---
@@ -159,6 +160,32 @@
     expect(markup.value, contains('This is a string.'));
   }
 
+  Future<void> test_promotedTypes() async {
+    final content = '''
+void f(aaa) {
+  if (aaa is String) {
+    print([[aa^a]]);
+  }
+}
+    ''';
+
+    final expectedHoverContent = '''
+```dart
+dynamic aaa
+```
+Type: `String`
+    '''
+        .trim();
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final hover = await getHover(mainFileUri, positionFromMarker(content));
+    expect(hover, isNotNull);
+    expect(hover!.range, equals(rangeFromMarkers(content)));
+    expect(hover.contents, isNotNull);
+    expect(_getStringContents(hover), equals(expectedHoverContent));
+  }
+
   Future<void> test_range_multiLineConstructorCall() async {
     final content = '''
     final a = new [[Str^ing.fromCharCodes]]([
@@ -229,6 +256,7 @@
 ```dart
 String abc
 ```
+Type: `String`
 *package:test/main.dart*
     '''
         .trim();
@@ -327,6 +355,7 @@
 ```dart
 String? abc
 ```
+Type: `String?`
 *package:test/main.dart*
     '''
         .trim();
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index ef97f63..53c2a00 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -624,13 +624,11 @@
     /// or delayed, depending on the value of
     /// [provider.delayWatcherInitialization].
     void setupWatcher() {
-      if (!provider._pathToWatchers.containsKey(path)) {
-        provider._pathToWatchers[path] = <StreamController<WatchEvent>>[];
-      }
-      provider._pathToWatchers[path]!.add(streamController);
+      var watchers = provider._pathToWatchers[path] ??= [];
+      watchers.add(streamController);
       streamController.done.then((_) {
-        provider._pathToWatchers[path]!.remove(streamController);
-        if (provider._pathToWatchers[path]!.isEmpty) {
+        watchers.remove(streamController);
+        if (watchers.isEmpty) {
           provider._pathToWatchers.remove(path);
         }
       });
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index e235487..9c20706 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -564,6 +564,7 @@
     if (token.type != TokenType.EOF && offset >= token.offset) {
       return null;
     }
+    final startToken = token;
     token = token.precedingComments;
     while (token != null) {
       if (offset <= token.offset) {
@@ -576,6 +577,21 @@
       }
       token = token.next;
     }
+
+    // It's possible the supplied token was a DartDoc token and there were
+    // normal comments before it that don't show up in precedingComments so
+    // check for them too.
+    token = startToken.previous;
+    while (token != null &&
+        offset <= token.end &&
+        (token.type == TokenType.SINGLE_LINE_COMMENT ||
+            token.type == TokenType.MULTI_LINE_COMMENT)) {
+      if (offset >= token.offset) {
+        return token;
+      }
+      token = token.previous;
+    }
+
     return null;
   }
 
diff --git a/pkg/dds/lib/src/dap/utils.dart b/pkg/dds/lib/src/dap/utils.dart
index fa47866..8dcfbae 100644
--- a/pkg/dds/lib/src/dap/utils.dart
+++ b/pkg/dds/lib/src/dap/utils.dart
@@ -21,6 +21,10 @@
 /// was necessarily a stack frame or that calling `toString` will return the
 /// original input text.
 stack.Frame? parseStackFrame(String line) {
+  // Because we split on \r, on Windows there may be trailing \r which prevents
+  // package:stack_trace from parsing correctly.
+  line = line.trim();
+
   /// Helper to try parsing a frame with [parser], returning `null` if it
   /// fails to parse.
   stack.Frame? tryParseFrame(stack.Frame Function(String) parser) {
diff --git a/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
index 8d133e3..ad7a346 100644
--- a/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue_46886.dart.textual_outline.expect
@@ -1,13 +1,10 @@
 // @dart = 2.13
 class Foo {
-  Foo operator >>>(_) => this;
+  Foo operator >>> (_) => this;
 }
-
 extension on Symbol {
   String operator >(_) => "Greater Than used";
   String call(_) => "Called";
 }
-
 abstract class Bar implements List<List<List<String>>> {}
-
 main() {}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
index 4ca0a85..9f1c16a 100644
--- a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
@@ -3,8 +3,10 @@
   A.foo() : this(42, z: "foo", false);
   factory A.bar(int x, bool y, {required String z}) = A;
 }
+
 class B extends A {
   B() : super(42, z: "foo", false);
 }
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3d107d4
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A {
+  A(int x, bool y, {required String z});
+  A.foo() : this(42, z: "foo", false);
+  factory A.bar(int x, bool y, {required String z}) = A;
+}
+
+class B extends A {
+  B() : super(42, z: "foo", false);
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index d95e1b6..86a420c 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -100,6 +100,7 @@
 general/issue43363: FormatterCrash
 general/issue45490: FormatterCrash
 general/issue45700.crash: FormatterCrash
+general/issue_46886: FormatterCrash
 general/issue47495: FormatterCrash
 general/issue47728_2: FormatterCrash
 general/issue47728_3: FormatterCrash
@@ -151,7 +152,6 @@
 late_lowering/skip_late_final_uninitialized_instance_fields/main: FormatterCrash
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
 macros/macro_class: FormatterCrash
-named_arguments_anywhere/redirecting_constructor_initializers: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
 nnbd/duplicates_instance: FormatterCrash
diff --git a/tools/VERSION b/tools/VERSION
index 36036a4..e29da8b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 32
+PRERELEASE 33
 PRERELEASE_PATCH 0
\ No newline at end of file