Version 2.17.0-229.0.dev

Merge commit '435ebeb5a717dfeeba26b3307c220ace2f62d860' into 'dev'
diff --git a/DEPS b/DEPS
index eec5920..5cc60b6 100644
--- a/DEPS
+++ b/DEPS
@@ -601,7 +601,7 @@
     "packages": [
       {
       "package": "fuchsia/sdk/gn/mac-amd64",
-      "version": "git_revision:190502a955c482431c2edd0525e128423728b662"
+      "version": "git_revision:c9bdf5da65647923cb79c391824434125cb00bbe"
       }
     ],
     "condition": 'host_os == "mac" and host_cpu == "x64"',
@@ -611,7 +611,7 @@
     "packages": [
       {
       "package": "fuchsia/sdk/gn/linux-amd64",
-      "version": "git_revision:190502a955c482431c2edd0525e128423728b662"
+      "version": "git_revision:c9bdf5da65647923cb79c391824434125cb00bbe"
       }
     ],
     "condition": 'host_os == "linux" and host_cpu == "x64"',
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index 3037258..f178c40 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -77,10 +77,19 @@
   ///
   /// The [inferOmittedType] argument is used to get the inferred type for a
   /// given [OmittedTypeAnnotation].
+  ///
+  /// If [omittedTypes] is provided, [inferOmittedType] is allowed to return
+  /// `null` for types that have not yet been inferred. In this case a fresh
+  /// name will be used for the omitted type in the generated library code and
+  /// the omitted type will be mapped to the fresh name in [omittedTypes].
+  ///
+  /// The generated library files content must be deterministic, including the
+  /// generation of fresh names for import prefixes and omitted types.
   String buildAugmentationLibrary(
       Iterable<MacroExecutionResult> macroResults,
       ResolvedIdentifier Function(Identifier) resolveIdentifier,
-      TypeAnnotation Function(OmittedTypeAnnotation) inferOmittedType);
+      TypeAnnotation? Function(OmittedTypeAnnotation) inferOmittedType,
+      {Map<OmittedTypeAnnotation, String>? omittedTypes});
 
   /// Tell the executor to shut down and clean up any resources it may have
   /// allocated.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
index a795bc6..0ecb10f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
@@ -12,49 +12,82 @@
   String buildAugmentationLibrary(
       Iterable<MacroExecutionResult> macroResults,
       ResolvedIdentifier Function(Identifier) resolveIdentifier,
-      TypeAnnotation Function(OmittedTypeAnnotation) typeInferrer) {
-    StringBuffer importsBuffer = new StringBuffer();
-    StringBuffer directivesBuffer = new StringBuffer();
-    Map<Uri, String> importPrefixes = {};
-    int nextPrefix = 0;
+      TypeAnnotation? Function(OmittedTypeAnnotation) typeInferrer,
+      {Map<OmittedTypeAnnotation, String>? omittedTypes}) {
+    Map<Uri, _SynthesizedNamePart> importNames = {};
+    Map<OmittedTypeAnnotation, _SynthesizedNamePart> typeNames = {};
+    List<_Part> importParts = [];
+    List<_Part> directivesParts = [];
+    List<_StringPart> stringParts = [];
+    StringBuffer directivesStringPartBuffer = new StringBuffer();
+
+    void flushStringParts() {
+      if (directivesStringPartBuffer.isNotEmpty) {
+        _StringPart stringPart =
+            new _StringPart(directivesStringPartBuffer.toString());
+        directivesParts.add(stringPart);
+        stringParts.add(stringPart);
+        directivesStringPartBuffer = new StringBuffer();
+      }
+    }
 
     // Keeps track of the last part written in `lastDirectivePart`.
     String lastDirectivePart = '';
-    void writeDirectivePart(String part) {
+    void writeDirectiveStringPart(String part) {
       lastDirectivePart = part;
-      directivesBuffer.write(part);
+      directivesStringPartBuffer.write(part);
+    }
+
+    void writeDirectiveSynthesizedNamePart(_SynthesizedNamePart part) {
+      flushStringParts();
+      lastDirectivePart = '';
+      directivesParts.add(part);
     }
 
     void buildCode(Code code) {
       for (Object part in code.parts) {
         if (part is String) {
-          writeDirectivePart(part);
+          writeDirectiveStringPart(part);
         } else if (part is Code) {
           buildCode(part);
         } else if (part is Identifier) {
           ResolvedIdentifier resolved = resolveIdentifier(part);
-          String? prefix;
+          _SynthesizedNamePart? prefix;
           if (resolved.uri != null) {
-            prefix = importPrefixes.putIfAbsent(resolved.uri!, () {
-              String prefix = 'i${nextPrefix++}';
-              importsBuffer.writeln("import '${resolved.uri}' as $prefix;");
+            prefix = importNames.putIfAbsent(resolved.uri!, () {
+              _SynthesizedNamePart prefix = new _SynthesizedNamePart();
+              importParts.add(new _StringPart("import '${resolved.uri}' as "));
+              importParts.add(prefix);
+              importParts.add(new _StringPart(";\n"));
               return prefix;
             });
           }
           if (resolved.kind == IdentifierKind.instanceMember) {
             // Qualify with `this.` if we don't have a receiver.
             if (!lastDirectivePart.trimRight().endsWith('.')) {
-              writeDirectivePart('this.');
+              writeDirectiveStringPart('this.');
             }
           } else if (prefix != null) {
-            writeDirectivePart('${prefix}.');
+            writeDirectiveSynthesizedNamePart(prefix);
+            writeDirectiveStringPart('.');
           }
           if (resolved.kind == IdentifierKind.staticInstanceMember) {
-            writeDirectivePart('${resolved.staticScope!}.');
+            writeDirectiveStringPart('${resolved.staticScope!}.');
           }
-          writeDirectivePart('${part.name}');
+          writeDirectiveStringPart('${part.name}');
         } else if (part is OmittedTypeAnnotation) {
-          buildCode(typeInferrer(part).code);
+          TypeAnnotation? type = typeInferrer(part);
+          if (type == null) {
+            if (omittedTypes != null) {
+              _SynthesizedNamePart name =
+                  typeNames.putIfAbsent(part, () => new _SynthesizedNamePart());
+              writeDirectiveSynthesizedNamePart(name);
+            } else {
+              throw new ArgumentError("No type inferred for $part");
+            }
+          } else {
+            buildCode(type.code);
+          }
         } else {
           throw new ArgumentError(
               'Code objects only support String, Identifier, and Code '
@@ -67,7 +100,7 @@
     for (MacroExecutionResult result in macroResults) {
       for (DeclarationCode augmentation in result.libraryAugmentations) {
         buildCode(augmentation);
-        directivesBuffer.writeln();
+        writeDirectiveStringPart('\n');
       }
       for (MapEntry<String, Iterable<DeclarationCode>> entry
           in result.classAugmentations.entries) {
@@ -78,13 +111,79 @@
     }
     for (MapEntry<String, List<DeclarationCode>> entry
         in mergedClassResults.entries) {
-      directivesBuffer.writeln('augment class ${entry.key} {');
+      writeDirectiveStringPart('augment class ${entry.key} {\n');
       for (DeclarationCode augmentation in entry.value) {
         buildCode(augmentation);
-        directivesBuffer.writeln();
+        writeDirectiveStringPart('\n');
       }
-      directivesBuffer.writeln('}');
+      writeDirectiveStringPart('}\n');
     }
-    return '$importsBuffer\n\n$directivesBuffer';
+    flushStringParts();
+
+    if (importNames.isNotEmpty) {
+      String prefix = _computeFreshPrefix(stringParts, 'prefix');
+      int index = 0;
+      for (_SynthesizedNamePart part in importNames.values) {
+        part.text = '$prefix${index++}';
+      }
+    }
+    if (omittedTypes != null && typeNames.isNotEmpty) {
+      String prefix = _computeFreshPrefix(stringParts, 'OmittedType');
+      int index = 0;
+      typeNames.forEach(
+          (OmittedTypeAnnotation omittedType, _SynthesizedNamePart part) {
+        String name = '$prefix${index++}';
+        part.text = name;
+        omittedTypes[omittedType] = name;
+      });
+    }
+
+    StringBuffer sb = new StringBuffer();
+    for (_Part part in importParts) {
+      sb.write(part.text);
+    }
+    sb.write('\n');
+    for (_Part part in directivesParts) {
+      sb.write(part.text);
+    }
+
+    return sb.toString();
   }
 }
+
+abstract class _Part {
+  String get text;
+}
+
+class _SynthesizedNamePart implements _Part {
+  late String text;
+}
+
+class _StringPart implements _Part {
+  final String text;
+
+  _StringPart(this.text);
+}
+
+/// Computes a name starting with [name] that is unique with respect to the
+/// text in [stringParts].
+///
+/// This algorithm assumes that no two parts in [stringParts] occur in direct
+/// sequence where they are used, i.e. there is always at least one
+/// [_SynthesizedNamePart] between them.
+String _computeFreshPrefix(List<_StringPart> stringParts, String name) {
+  int index = -1;
+  String prefix = name;
+  for (_StringPart part in stringParts) {
+    while (part.text.contains(prefix)) {
+      index++;
+      prefix = '$name$index';
+    }
+  }
+  if (index > 0) {
+    // Add a separator when an index was needed. This is to ensure that
+    // suffixing number to [prefix] doesn't blend the digits.
+    prefix = '${prefix}_';
+  }
+  return prefix;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
index bbcea72..5609883 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/executor_base.dart
@@ -316,7 +316,8 @@
   String buildAugmentationLibrary(
           Iterable<MacroExecutionResult> macroResults,
           ResolvedIdentifier Function(Identifier) resolveIdentifier,
-          TypeAnnotation Function(OmittedTypeAnnotation) inferOmittedType) =>
+          TypeAnnotation? Function(OmittedTypeAnnotation) inferOmittedType,
+          {Map<OmittedTypeAnnotation, String>? omittedTypes}) =>
       throw new StateError('Unreachable');
 
   @override
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
index 78d960a..cc99e93 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
@@ -48,37 +48,37 @@
           (OmittedTypeAnnotation i) =>
               (i as TestOmittedTypeAnnotation).inferredType);
       expect(library, equalsIgnoringWhitespace('''
-        import 'dart:core' as i0;
+        import 'dart:core' as prefix0;
 
-        i0.int get i0j0 => 0;
-        i0.int get i0j1 => 1;
-        i0.int get i0j2 => 2;
-        i0.int get i1j0 => 1;
-        i0.int get i1j1 => 2;
-        i0.int get i1j2 => 3;
+        prefix0.int get i0j0 => 0;
+        prefix0.int get i0j1 => 1;
+        prefix0.int get i0j2 => 2;
+        prefix0.int get i1j0 => 1;
+        prefix0.int get i1j1 => 2;
+        prefix0.int get i1j2 => 3;
         augment class Foo00 {
-          i0.int get i => 0;
-          i0.int get j => 0;
+          prefix0.int get i => 0;
+          prefix0.int get j => 0;
         }
         augment class Foo01 {
-          i0.int get i => 0;
-          i0.int get j => 1;
+          prefix0.int get i => 0;
+          prefix0.int get j => 1;
         }
         augment class Foo02 {
-          i0.int get i => 0;
-          i0.int get j => 2;
+          prefix0.int get i => 0;
+          prefix0.int get j => 2;
         }
         augment class Foo10 {
-          i0.int get i => 1;
-          i0.int get j => 0;
+          prefix0.int get i => 1;
+          prefix0.int get j => 0;
         }
         augment class Foo11 {
-          i0.int get i => 1;
-          i0.int get j => 1;
+          prefix0.int get i => 1;
+          prefix0.int get j => 1;
         }
         augment class Foo12 {
-          i0.int get i => 1;
-          i0.int get j => 2;
+          prefix0.int get i => 1;
+          prefix0.int get j => 2;
         }
       '''));
     });
@@ -151,15 +151,15 @@
           (OmittedTypeAnnotation i) =>
               (i as TestOmittedTypeAnnotation).inferredType);
       expect(library, equalsIgnoringWhitespace('''
-        import 'package:foo/foo.dart' as i0;
-        import 'package:builder/builder.dart' as i1;
-        import 'package:bar/bar.dart' as i2;
-        import 'dart:core' as i3;
+        import 'package:foo/foo.dart' as prefix0;
+        import 'package:builder/builder.dart' as prefix1;
+        import 'package:bar/bar.dart' as prefix2;
+        import 'dart:core' as prefix3;
 
-        class FooBuilder<T extends i0.Foo> implements i1.Builder<i2.Bar<T>> {
-          late i3.int baz;
+        class FooBuilder<T extends prefix0.Foo> implements prefix1.Builder<prefix2.Bar<T>> {
+          late prefix3.int baz;
 
-          i2.Bar<T> build() => new i2.Bar()..baz = i2.Bar.zap;
+          prefix2.Bar<T> build() => new prefix2.Bar()..baz = prefix2.Bar.zap;
         }
       '''));
     });
@@ -185,11 +185,102 @@
           (OmittedTypeAnnotation i) =>
               (i as TestOmittedTypeAnnotation).inferredType);
       expect(library, equalsIgnoringWhitespace('''
-        import 'dart:core' as i0;
+        import 'dart:core' as prefix0;
 
-        i0.int x = 1;
+        prefix0.int x = 1;
       '''));
     });
+
+    test('can handle name conflicts', () {
+      var omittedType0 = TestOmittedTypeAnnotation();
+      var omittedType1 = TestOmittedTypeAnnotation();
+
+      var omittedTypeIdentifier = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'OmittedType',
+          kind: IdentifierKind.topLevelMember,
+          staticScope: null,
+          uri: Uri.parse('package:foo/foo.dart'));
+      var omittedTypeIdentifier0 = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'OmittedType0',
+          kind: IdentifierKind.topLevelMember,
+          staticScope: null,
+          uri: Uri.parse('package:bar/bar.dart'));
+      var prefixInstanceMember = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'prefix',
+          kind: IdentifierKind.instanceMember,
+          staticScope: null,
+          uri: Uri.parse('package:bar/bar.dart'));
+      var prefix0InstanceMember = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'prefix0',
+          kind: IdentifierKind.instanceMember,
+          staticScope: null,
+          uri: Uri.parse('package:bar/bar.dart'));
+      var prefix1StaticMember = TestIdentifier(
+          id: RemoteInstance.uniqueId,
+          name: 'prefix1',
+          kind: IdentifierKind.staticInstanceMember,
+          staticScope: 'OmittedType1',
+          uri: Uri.parse('package:bar/bar.dart'));
+      var results = [
+        MacroExecutionResultImpl(
+          classAugmentations: {},
+          libraryAugmentations: [
+            DeclarationCode.fromParts([
+              'class OmittedType {\n  ',
+              omittedType0.code,
+              ' method(',
+              omittedType1.code,
+              ' o) {\n    ',
+              intIdentifier,
+              ' ${prefixInstanceMember.name} = 0;\n    ',
+              omittedTypeIdentifier,
+              ' ${prefix0InstanceMember.name} = ',
+              'new ',
+              omittedTypeIdentifier,
+              '();\n    ',
+              'new ',
+              omittedTypeIdentifier0,
+              '()..',
+              prefixInstanceMember,
+              ' = ',
+              prefix1StaticMember,
+              ';',
+              '\n  }',
+              '\n}',
+            ]),
+          ],
+          newTypeNames: [
+            'OmittedType',
+          ],
+        )
+      ];
+      var omittedTypes = <OmittedTypeAnnotation, String>{};
+      var library = _TestExecutor().buildAugmentationLibrary(
+          results,
+          (Identifier i) => (i as TestIdentifier).resolved,
+          (OmittedTypeAnnotation i) =>
+              (i as TestOmittedTypeAnnotation).inferredType,
+          omittedTypes: omittedTypes);
+      expect(library, equalsIgnoringWhitespace('''
+        import 'dart:core' as prefix2_0;
+        import 'package:foo/foo.dart' as prefix2_1;
+        import 'package:bar/bar.dart' as prefix2_2;
+
+        class OmittedType {
+          OmittedType2_0 method(OmittedType2_1 o) {
+            prefix2_0.int prefix = 0;
+            prefix2_1.OmittedType prefix0 = new prefix2_1.OmittedType();
+            new prefix2_2.OmittedType0()..prefix = prefix2_2.OmittedType1.prefix1;
+          }
+        }
+      '''));
+      expect(omittedTypes[omittedType0], 'OmittedType2_0');
+      expect(omittedTypes[omittedType1], 'OmittedType2_1');
+    });
   });
 }
 
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index c1167f8..6049823 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -117,14 +117,14 @@
   @override
   Future<TypeAnnotation> inferType(
           TestOmittedTypeAnnotation omittedType) async =>
-      omittedType.inferredType;
+      omittedType.inferredType!;
 }
 
 /// Knows its inferred type ahead of time.
 class TestOmittedTypeAnnotation extends OmittedTypeAnnotationImpl {
-  final TypeAnnotation inferredType;
+  final TypeAnnotation? inferredType;
 
-  TestOmittedTypeAnnotation(this.inferredType)
+  TestOmittedTypeAnnotation([this.inferredType])
       : super(id: RemoteInstance.uniqueId);
 }
 
@@ -155,8 +155,12 @@
       } else if (part is IdentifierImpl) {
         buffer.write(part.name);
       } else if (part is TestOmittedTypeAnnotation) {
-        buffer.write('/*inferred*/');
-        part.inferredType.code.debugString(buffer);
+        if (part.inferredType != null) {
+          buffer.write('/*inferred*/');
+          part.inferredType!.code.debugString(buffer);
+        } else {
+          buffer.write('/*omitted*/');
+        }
       } else {
         buffer.write(part as String);
       }
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index 7d095d7..8475456 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -1605,3 +1605,81 @@
   @override
   String toString() => jsonEncoder.convert(toJson());
 }
+
+class ValidateRefactorResult implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ValidateRefactorResult.canParse, ValidateRefactorResult.fromJson);
+
+  ValidateRefactorResult({required this.valid, this.message});
+  static ValidateRefactorResult fromJson(Map<String, Object?> json) {
+    final validJson = json['valid'];
+    final valid = validJson as bool;
+    final messageJson = json['message'];
+    final message = messageJson as String?;
+    return ValidateRefactorResult(valid: valid, message: message);
+  }
+
+  final String? message;
+  final bool valid;
+
+  Map<String, Object?> toJson() {
+    var __result = <String, Object?>{};
+    __result['valid'] = valid;
+    if (message != null) {
+      __result['message'] = message;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object? obj, LspJsonReporter reporter) {
+    if (obj is Map<String, Object?>) {
+      reporter.push('valid');
+      try {
+        if (!obj.containsKey('valid')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        final valid = obj['valid'];
+        if (valid == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(valid is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('message');
+      try {
+        final message = obj['message'];
+        if (message != null && !(message is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ValidateRefactorResult');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ValidateRefactorResult &&
+        other.runtimeType == ValidateRefactorResult) {
+      return valid == other.valid && message == other.message && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(valid, message);
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 55257c6..cb2da70 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -67,6 +67,7 @@
   static const fixAll = 'edit.fixAll';
   static const sendWorkspaceEdit = 'edit.sendWorkspaceEdit';
   static const performRefactor = 'refactor.perform';
+  static const validateRefactor = 'refactor.validate';
 }
 
 abstract class CustomMethods {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/abstract_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/abstract_refactor.dart
new file mode 100644
index 0000000..cc504be
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/abstract_refactor.dart
@@ -0,0 +1,197 @@
+// 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';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+
+final _manager = LspRefactorManager._();
+
+/// A base class for refactoring commands that need to create Refactorings from
+/// client-supplied arguments.
+abstract class AbstractRefactorCommandHandler extends SimpleEditCommandHandler {
+  AbstractRefactorCommandHandler(LspAnalysisServer server) : super(server);
+
+  @override
+  String get commandName => 'Perform Refactor';
+
+  LspRefactorManager get manager => _manager;
+
+  FutureOr<ErrorOr<void>> execute(
+      String path,
+      String kind,
+      int offset,
+      int length,
+      Map<String, Object?>? options,
+      CancellationToken cancellationToken,
+      ProgressReporter reporter,
+      int? docVersion);
+
+  Future<ErrorOr<Refactoring>> getRefactoring(
+    RefactoringKind kind,
+    ResolvedUnitResult result,
+    int offset,
+    int length,
+    Map<String, dynamic>? options,
+  ) async {
+    switch (kind) {
+      case RefactoringKind.EXTRACT_METHOD:
+        final refactor = ExtractMethodRefactoring(
+            server.searchEngine, result, offset, length);
+
+        var preferredName = options != null ? options['name'] as String : null;
+        // checkInitialConditions will populate names with suggestions.
+        if (preferredName == null) {
+          await refactor.checkInitialConditions();
+          if (refactor.names.isNotEmpty) {
+            preferredName = refactor.names.first;
+          }
+        }
+        refactor.name = preferredName ?? 'newMethod';
+
+        // Defaults to true, but may be surprising if users didn't have an option
+        // to opt in.
+        refactor.extractAll = false;
+        return success(refactor);
+
+      case RefactoringKind.EXTRACT_LOCAL_VARIABLE:
+        final refactor = ExtractLocalRefactoring(result, offset, length);
+
+        var preferredName = options != null ? options['name'] as String : null;
+        // checkInitialConditions will populate names with suggestions.
+        if (preferredName == null) {
+          await refactor.checkInitialConditions();
+          if (refactor.names.isNotEmpty) {
+            preferredName = refactor.names.first;
+          }
+        }
+        refactor.name = preferredName ?? 'newVariable';
+
+        // Defaults to true, but may be surprising if users didn't have an option
+        // to opt in.
+        refactor.extractAll = false;
+        return success(refactor);
+
+      case RefactoringKind.EXTRACT_WIDGET:
+        final refactor = ExtractWidgetRefactoring(
+            server.searchEngine, result, offset, length);
+        // Provide a default name for clients that do not have any custom
+        // handling.
+        // Clients can use the information documented for refactor.perform to
+        // inject their own user-provided names until LSP has some native
+        // support:
+        // https://github.com/microsoft/language-server-protocol/issues/764
+        refactor.name =
+            options != null ? options['name'] as String : 'NewWidget';
+        return success(refactor);
+
+      case RefactoringKind.INLINE_LOCAL_VARIABLE:
+        final refactor =
+            InlineLocalRefactoring(server.searchEngine, result, offset);
+        return success(refactor);
+
+      case RefactoringKind.INLINE_METHOD:
+        final refactor =
+            InlineMethodRefactoring(server.searchEngine, result, offset);
+        return success(refactor);
+
+      case RefactoringKind.CONVERT_GETTER_TO_METHOD:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is PropertyAccessorElement) {
+            final refactor = ConvertGetterToMethodRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
+      case RefactoringKind.CONVERT_METHOD_TO_GETTER:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is ExecutableElement) {
+            final refactor = ConvertMethodToGetterRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
+      default:
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Unknown RefactoringKind $kind was supplied to $commandName');
+    }
+  }
+
+  @override
+  Future<ErrorOr<void>> handle(List<Object?>? arguments,
+      ProgressReporter reporter, CancellationToken cancellationToken) async {
+    if (arguments == null ||
+        arguments.length != 6 ||
+        arguments[0] is! String || // kind
+        arguments[1] is! String || // path
+        (arguments[2] != null && arguments[2] is! int) || // docVersion
+        arguments[3] is! int || // offset
+        arguments[4] is! int || // length
+        // options
+        // Important: This arguments position is documented in
+        // tool/lsp_spec/README.md to allow clients with custom code (such as
+        // VS Code) to intercept the request and inject options (such as a
+        // user-provided name). Any changes to these arguments must be backwards
+        // compatible, keeping the options in this position.
+        (arguments[5] != null && arguments[5] is! Map<String, Object?>)) {
+      return ErrorOr.error(ResponseError(
+        code: ServerErrorCodes.InvalidCommandArguments,
+        message:
+            '$commandName requires 6 parameters: RefactoringKind, docVersion, filePath, offset, length, options (optional)',
+      ));
+    }
+
+    final kind = arguments[0] as String;
+    final path = arguments[1] as String;
+    final docVersion = arguments[2] as int?;
+    final offset = arguments[3] as int;
+    final length = arguments[4] as int;
+    final options = arguments[5] as Map<String, Object?>?;
+
+    return execute(path, kind, offset, length, options, cancellationToken,
+        reporter, docVersion);
+  }
+}
+
+/// Manages a running refactor to help ensure only one refactor runs at a time.
+class LspRefactorManager {
+  /// The cancellation token for the current in-progress refactor (or null).
+  CancelableToken? _currentRefactoringCancellationToken;
+
+  LspRefactorManager._();
+
+  /// Begins a new refactor, cancelling any other in-progress refactors.
+  void begin(CancelableToken cancelToken) {
+    _currentRefactoringCancellationToken?.cancel();
+    _currentRefactoringCancellationToken = cancelToken;
+  }
+
+  /// Marks a refactor as no longer current.
+  void end(CancelableToken cancelToken) {
+    if (_currentRefactoringCancellationToken == cancelToken) {
+      _currentRefactoringCancellationToken = null;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index 5523d17..3690cf5 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -2,58 +2,38 @@
 // 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';
+
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
-import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/abstract_refactor.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
 import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analysis_server/src/services/refactoring/refactoring.dart';
-import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 
-final _manager = _RefactorManager();
-
-class PerformRefactorCommandHandler extends SimpleEditCommandHandler {
+class PerformRefactorCommandHandler extends AbstractRefactorCommandHandler {
   PerformRefactorCommandHandler(LspAnalysisServer server) : super(server);
 
   @override
   String get commandName => 'Perform Refactor';
 
   @override
-  Future<ErrorOr<void>> handle(List<Object?>? arguments,
-      ProgressReporter reporter, CancellationToken cancellationToken) async {
-    if (arguments == null ||
-        arguments.length != 6 ||
-        arguments[0] is! String || // kind
-        arguments[1] is! String || // path
-        (arguments[2] != null && arguments[2] is! int) || // docVersion
-        arguments[3] is! int || // offset
-        arguments[4] is! int || // length
-        // options
-        (arguments[5] != null && arguments[5] is! Map<String, dynamic>)) {
-      // length
-      return ErrorOr.error(ResponseError(
-        code: ServerErrorCodes.InvalidCommandArguments,
-        message:
-            '$commandName requires 6 parameters: RefactoringKind, docVersion, filePath, offset, length, options (optional)',
-      ));
-    }
-
-    final kind = arguments[0] as String;
-    final path = arguments[1] as String;
-    final docVersion = arguments[2] as int?;
-    final offset = arguments[3] as int;
-    final length = arguments[4] as int;
-    final options = arguments[5] as Map<String, Object?>?;
-
+  FutureOr<ErrorOr<void>> execute(
+    String path,
+    String kind,
+    int offset,
+    int length,
+    Map<String, Object?>? options,
+    CancellationToken cancellationToken,
+    ProgressReporter reporter,
+    int? docVersion,
+  ) async {
     final result = await requireResolvedUnit(path);
     return result.mapResult((result) async {
-      final refactoring = await _getRefactoring(
+      final refactoring = await getRefactoring(
           RefactoringKind(kind), result, offset, length, options);
       return refactoring.mapResult((refactoring) async {
         // If the token we were given is not cancellable, replace it with one that
@@ -63,7 +43,7 @@
         final cancelableToken = cancellationToken is CancelableToken
             ? cancellationToken
             : CancelableToken();
-        _manager.begin(cancelableToken);
+        manager.begin(cancelableToken);
 
         try {
           reporter.begin('Refactoring…');
@@ -98,128 +78,10 @@
           final edit = createWorkspaceEdit(server, change);
           return await sendWorkspaceEditToClient(edit);
         } finally {
-          _manager.end(cancelableToken);
+          manager.end(cancelableToken);
           reporter.end();
         }
       });
     });
   }
-
-  Future<ErrorOr<Refactoring>> _getRefactoring(
-    RefactoringKind kind,
-    ResolvedUnitResult result,
-    int offset,
-    int length,
-    Map<String, dynamic>? options,
-  ) async {
-    switch (kind) {
-      case RefactoringKind.EXTRACT_METHOD:
-        final refactor = ExtractMethodRefactoring(
-            server.searchEngine, result, offset, length);
-
-        var preferredName = options != null ? options['name'] as String : null;
-        // checkInitialConditions will populate names with suggestions.
-        if (preferredName == null) {
-          await refactor.checkInitialConditions();
-          if (refactor.names.isNotEmpty) {
-            preferredName = refactor.names.first;
-          }
-        }
-        refactor.name = preferredName ?? 'newMethod';
-
-        // Defaults to true, but may be surprising if users didn't have an option
-        // to opt in.
-        refactor.extractAll = false;
-        return success(refactor);
-
-      case RefactoringKind.EXTRACT_LOCAL_VARIABLE:
-        final refactor = ExtractLocalRefactoring(result, offset, length);
-
-        var preferredName = options != null ? options['name'] as String : null;
-        // checkInitialConditions will populate names with suggestions.
-        if (preferredName == null) {
-          await refactor.checkInitialConditions();
-          if (refactor.names.isNotEmpty) {
-            preferredName = refactor.names.first;
-          }
-        }
-        refactor.name = preferredName ?? 'newVariable';
-
-        // Defaults to true, but may be surprising if users didn't have an option
-        // to opt in.
-        refactor.extractAll = false;
-        return success(refactor);
-
-      case RefactoringKind.EXTRACT_WIDGET:
-        final refactor = ExtractWidgetRefactoring(
-            server.searchEngine, result, offset, length);
-        // TODO(dantup): For now we don't have a good way to prompt the user
-        // for a method name so we just use a placeholder and expect them to
-        // rename (this is what C#/Omnisharp does), but there's an open request
-        // to handle this better.
-        // https://github.com/microsoft/language-server-protocol/issues/764
-        refactor.name =
-            options != null ? options['name'] as String : 'NewWidget';
-        return success(refactor);
-
-      case RefactoringKind.INLINE_LOCAL_VARIABLE:
-        final refactor =
-            InlineLocalRefactoring(server.searchEngine, result, offset);
-        return success(refactor);
-
-      case RefactoringKind.INLINE_METHOD:
-        final refactor =
-            InlineMethodRefactoring(server.searchEngine, result, offset);
-        return success(refactor);
-
-      case RefactoringKind.CONVERT_GETTER_TO_METHOD:
-        final node = NodeLocator(offset).searchWithin(result.unit);
-        final element = server.getElementOfNode(node);
-        if (element != null) {
-          if (element is PropertyAccessorElement) {
-            final refactor = ConvertGetterToMethodRefactoring(
-                server.searchEngine, result.session, element);
-            return success(refactor);
-          }
-        }
-        return error(ServerErrorCodes.InvalidCommandArguments,
-            'Location supplied to $commandName $kind is not longer valid');
-
-      case RefactoringKind.CONVERT_METHOD_TO_GETTER:
-        final node = NodeLocator(offset).searchWithin(result.unit);
-        final element = server.getElementOfNode(node);
-        if (element != null) {
-          if (element is ExecutableElement) {
-            final refactor = ConvertMethodToGetterRefactoring(
-                server.searchEngine, result.session, element);
-            return success(refactor);
-          }
-        }
-        return error(ServerErrorCodes.InvalidCommandArguments,
-            'Location supplied to $commandName $kind is not longer valid');
-
-      default:
-        return error(ServerErrorCodes.InvalidCommandArguments,
-            'Unknown RefactoringKind $kind was supplied to $commandName');
-    }
-  }
-}
-
-/// Manages a running refactor to help ensure only one refactor runs at a time.
-class _RefactorManager {
-  /// The cancellation token for the current in-progress refactor (or null).
-  CancelableToken? _currentRefactoringCancellationToken;
-
-  /// Begins a new refactor, cancelling any other in-progress refactors.
-  void begin(CancelableToken cancelToken) {
-    _currentRefactoringCancellationToken?.cancel();
-    _currentRefactoringCancellationToken = cancelToken;
-  }
-
-  /// Marks a refactor as no longer current.
-  void end(CancelableToken cancelToken) {
-    if (_currentRefactoringCancellationToken == cancelToken) {
-      _currentRefactoringCancellationToken = null;
-    }
-  }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/validate_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/validate_refactor.dart
new file mode 100644
index 0000000..6c54c7c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/validate_refactor.dart
@@ -0,0 +1,75 @@
+// 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';
+
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/abstract_refactor.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+
+class ValidateRefactorCommandHandler extends AbstractRefactorCommandHandler {
+  ValidateRefactorCommandHandler(LspAnalysisServer server) : super(server);
+
+  @override
+  String get commandName => 'Validate Refactor';
+
+  @override
+  FutureOr<ErrorOr<ValidateRefactorResult>> execute(
+    String path,
+    String kind,
+    int offset,
+    int length,
+    Map<String, Object?>? options,
+    CancellationToken cancellationToken,
+    ProgressReporter reporter,
+    int? docVersion,
+  ) async {
+    // In order to prevent clients asking users for a method/widget name and
+    // then failing because of something like "Cannot extract closure as method"
+    // this command allows the client to call `checkInitialConditions()` after
+    // the user selects the action but before prompting for a name.
+    //
+    // We do not perform that check when building the code actions because there
+    // will be no visibility of the reason why the refactor is not available to
+    // the user.
+
+    final result = await requireResolvedUnit(path);
+    return result.mapResult((result) async {
+      final refactoring = await getRefactoring(
+          RefactoringKind(kind), result, offset, length, options);
+      return refactoring.mapResult((refactoring) async {
+        // If the token we were given is not cancellable, replace it with one that
+        // is for the rest of this request, as a future refactor may need to cancel
+        // this request.
+        // The original token should be kept and also checked for cancellation.
+        final cancelableToken = cancellationToken is CancelableToken
+            ? cancellationToken
+            : CancelableToken();
+        manager.begin(cancelableToken);
+
+        try {
+          reporter.begin('Preparing Refactor…');
+          final status = await refactoring.checkInitialConditions();
+
+          if (status.hasError) {
+            return success(
+                ValidateRefactorResult(valid: false, message: status.message!));
+          }
+
+          return success(ValidateRefactorResult(valid: true));
+        } on InconsistentAnalysisException {
+          return failure(fileModifiedError);
+        } finally {
+          manager.end(cancelableToken);
+          reporter.end();
+        }
+      });
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index 02c8a93..cdc6fa5 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/lsp/handlers/commands/perform_refactor.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/send_workspace_edit.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/sort_members.dart';
+import 'package:analysis_server/src/lsp/handlers/commands/validate_refactor.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/progress.dart';
@@ -25,6 +26,7 @@
           Commands.organizeImports: OrganizeImportsCommandHandler(server),
           Commands.fixAll: FixAllCommandHandler(server),
           Commands.performRefactor: PerformRefactorCommandHandler(server),
+          Commands.validateRefactor: ValidateRefactorCommandHandler(server),
           Commands.sendWorkspaceEdit: SendWorkspaceEditCommandHandler(server),
         },
         super(server);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
index 5f7e010..ac0df68 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
@@ -77,6 +77,7 @@
         var parameter = _parameterFor(parameterMap, argument.expression);
         if (parameter != null &&
             parameter.isNamed &&
+            parameter.element.name == argument.name.label.name &&
             !referencedParameters.contains(parameter.element)) {
           var data = _dataForParameter(
             parameter,
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index ac78b0d..10690ba 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/json_parsing.dart';
@@ -433,6 +434,82 @@
     await verifyCodeActionEdits(
         codeAction, withoutMarkers(content), expectedContent);
   }
+
+  Future<void> test_validLocation_failsInitialValidation() async {
+    const content = '''
+f() {
+  var a = 0;
+  doFoo([[() => print(a)]]);
+  print(a);
+}
+
+void doFoo(void Function() a) => a();
+
+    ''';
+    newFile2(mainFilePath, withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle)!;
+
+    final command = codeAction.map(
+      (command) => command,
+      (codeAction) => codeAction.command!,
+    );
+
+    // Call the `refactor.validate` command with the same arguments.
+    // Clients that want validation behaviour will need to implement this
+    // themselves (via middleware).
+    final response = await executeCommand(
+      Command(
+          title: command.title,
+          command: Commands.validateRefactor,
+          arguments: command.arguments),
+      decoder: ValidateRefactorResult.fromJson,
+    );
+
+    expect(response.valid, isFalse);
+    expect(response.message, contains('Cannot extract closure as method'));
+  }
+
+  Future<void> test_validLocation_passesInitialValidation() async {
+    const content = '''
+f() {
+  doFoo([[() => print(1)]]);
+}
+
+void doFoo(void Function() a) => a();
+
+    ''';
+    newFile2(mainFilePath, withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle)!;
+
+    final command = codeAction.map(
+      (command) => command,
+      (codeAction) => codeAction.command!,
+    );
+
+    // Call the `Commands.validateRefactor` command with the same arguments.
+    // Clients that want validation behaviour will need to implement this
+    // themselves (via middleware).
+    final response = await executeCommand(
+      Command(
+          title: command.title,
+          command: Commands.validateRefactor,
+          arguments: command.arguments),
+      decoder: ValidateRefactorResult.fromJson,
+    );
+
+    expect(response.valid, isTrue);
+    expect(response.message, isNull);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index fbfbeb1..c74663d 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -868,8 +868,11 @@
     return executeCommand(command);
   }
 
-  Future<Object?> executeCommand(Command command,
-      {Either2<int, String>? workDoneToken}) async {
+  Future<T> executeCommand<T>(
+    Command command, {
+    T Function(Map<String, Object?>)? decoder,
+    Either2<int, String>? workDoneToken,
+  }) async {
     final request = makeRequest(
       Method.workspace_executeCommand,
       ExecuteCommandParams(
@@ -878,7 +881,8 @@
         workDoneToken: workDoneToken,
       ),
     );
-    return expectSuccessfulResponseTo(request, (result) => result);
+    return expectSuccessfulResponseTo<T, Map<String, Object?>>(
+        request, decoder ?? (result) => result as T);
   }
 
   void expect(Object? actual, Matcher matcher, {String? reason}) =>
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart
index b8517d5..1b070d0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart
@@ -281,6 +281,25 @@
 ''');
   }
 
+  Future<void> test_named_oneWithNameChange() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({int? x, int? z}) : super(x: x, y: z);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({super.x, int? z}) : super(y: z);
+}
+''');
+  }
+
   Future<void> test_named_only() async {
     await resolveTestCode('''
 class A {
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 58a60e2..f050549 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -286,6 +286,14 @@
       ],
       baseType: 'TextEdit',
     ),
+    // Return type for refactor.validate command.
+    interface(
+      'ValidateRefactorResult',
+      [
+        field('valid', type: 'boolean'),
+        field('message', type: 'string', canBeUndefined: true),
+      ],
+    ),
     TypeAlias(
       null,
       Token.identifier('TextDocumentEditEdits'),
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
index 2a49b01..4003c68 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
@@ -53,5 +53,14 @@
   /// The file is expected to be a Dart file, reporting non-Dart files, such
   /// as configuration files `analysis_options.yaml`, `package_config.json`,
   /// etc will not re-create analysis contexts.
+  ///
+  /// This will invalidate any previously returned [AnalysisSession], to
+  /// get a new analysis session apply pending file changes:
+  /// ```dart
+  /// analysisContext.changeFile(...);
+  /// await analysisContext.applyPendingFileChanges();
+  /// var analysisSession = analysisContext.currentSession;
+  /// var resolvedUnit = analysisSession.getResolvedUnit(...);
+  /// ```
   void changeFile(String path);
 }
diff --git a/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart
index 5a90a29..3cc37c6 100644
--- a/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macros/application/data/pkgs/macro/lib/macro.dart
@@ -361,4 +361,41 @@
     return "${superClass?.identifier.name}";
   }'''));
   }
+}
+
+macro
+
+class ImportConflictMacro implements FunctionDefinitionMacro {
+  const ImportConflictMacro();
+
+  FutureOr<void> buildDefinitionForFunction(FunctionDeclaration function,
+      FunctionDefinitionBuilder builder) {
+    builder.augment(new FunctionBodyCode.fromParts([
+      '{\n  ',
+      'var ',
+      'prefix',
+      ' = ',
+      function.positionalParameters
+          .elementAt(0)
+          .type
+          .code,
+      ';\n  ',
+      'var prefix0',
+      ' = ',
+      function.positionalParameters
+          .elementAt(1)
+          .type
+          .code,
+      ';\n  ',
+      'var pre',
+      'fix',
+      '10 = ',
+      function.positionalParameters
+          .elementAt(2)
+          .type
+          .code,
+      ';\n',
+      '}',
+    ]));
+  }
 }
\ No newline at end of file
diff --git a/pkg/front_end/test/macros/application/data/tests/import_conflict.dart b/pkg/front_end/test/macros/application/data/tests/import_conflict.dart
new file mode 100644
index 0000000..44c42bb
--- /dev/null
+++ b/pkg/front_end/test/macros/application/data/tests/import_conflict.dart
@@ -0,0 +1,31 @@
+// 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.
+
+/*library: 
+Definitions:
+import 'dart:core' as prefix2_0;
+import 'dart:async' as prefix2_1;
+import 'dart:math' as prefix2_2;
+import 'dart:convert' as prefix2_3;
+
+augment void function(prefix2_0.int i, prefix2_1.FutureOr<prefix2_2.Random> f, prefix2_3.JsonCodec c, ) {
+  var prefix = prefix2_0.int;
+  var prefix0 = prefix2_1.FutureOr<prefix2_2.Random>;
+  var prefix10 = prefix2_3.JsonCodec;
+}
+*/
+
+import 'package:macro/macro.dart';
+import 'dart:async';
+import 'dart:math';
+import 'dart:convert';
+
+@ImportConflictMacro()
+/*member: function:
+augment void function(int i, FutureOr<Random> f, JsonCodec c, ) {
+  var prefix = int;
+  var prefix0 = FutureOr<Random>;
+  var prefix10 = JsonCodec;
+}*/
+external void function(int i, FutureOr<Random> f, JsonCodec c);
diff --git a/pkg/front_end/test/macros/application/data/tests/import_conflict.dart.expect b/pkg/front_end/test/macros/application/data/tests/import_conflict.dart.expect
new file mode 100644
index 0000000..f688800
--- /dev/null
+++ b/pkg/front_end/test/macros/application/data/tests/import_conflict.dart.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "package:macro/macro.dart" as mac;
+import "dart:core" as core;
+import "dart:math" as math;
+import "dart:convert" as con;
+
+import "package:macro/macro.dart";
+import "dart:async";
+import "dart:math";
+import "dart:convert";
+
+@#C1
+static method /* from org-dartlang-augmentation:/a/b/c/main.dart-0 */ function(core::int i, FutureOr<math::Random>f, con::JsonCodec c) → void {
+  core::Type prefix = #C2;
+  core::Type prefix0 = #C3;
+  core::Type prefix10 = #C4;
+}
+
+constants  {
+  #C1 = mac::ImportConflictMacro {}
+  #C2 = TypeLiteralConstant(core::int*)
+  #C3 = TypeLiteralConstant(FutureOr<math::Random*>*)
+  #C4 = TypeLiteralConstant(con::JsonCodec*)
+}
diff --git a/pkg/front_end/test/macros/application/data/tests/parameters.dart b/pkg/front_end/test/macros/application/data/tests/parameters.dart
index c71841a..dae087e 100644
--- a/pkg/front_end/test/macros/application/data/tests/parameters.dart
+++ b/pkg/front_end/test/macros/application/data/tests/parameters.dart
@@ -4,19 +4,18 @@
 
 /*library: 
 Definitions:
-import 'dart:core' as i0;
+import 'dart:core' as prefix0;
 
-
-augment void topLevelFunction1(i0.int a, ) {
+augment void topLevelFunction1(prefix0.int a, ) {
   throw 42;
 }
-augment void topLevelFunction2(i0.int a, i0.int b, ) {
+augment void topLevelFunction2(prefix0.int a, prefix0.int b, ) {
   throw 42;
 }
-augment void topLevelFunction3(i0.int a, [i0.int? b, ]) {
+augment void topLevelFunction3(prefix0.int a, [prefix0.int? b, ]) {
   throw 42;
 }
-augment void topLevelFunction4(i0.int a, {i0.int? b, i0.int? c, }) {
+augment void topLevelFunction4(prefix0.int a, {prefix0.int? b, prefix0.int? c, }) {
   throw 42;
 }
 */
diff --git a/pkg/front_end/test/macros/application/data/tests/subtypes.dart b/pkg/front_end/test/macros/application/data/tests/subtypes.dart
index b4028fd..b275017 100644
--- a/pkg/front_end/test/macros/application/data/tests/subtypes.dart
+++ b/pkg/front_end/test/macros/application/data/tests/subtypes.dart
@@ -4,25 +4,24 @@
 
 /*library: 
 Definitions:
-import 'org-dartlang-test:///a/b/c/main.dart' as i0;
+import 'org-dartlang-test:///a/b/c/main.dart' as prefix0;
 
-
-augment i0.A topLevelFunction1(i0.A a, ) {
+augment prefix0.A topLevelFunction1(prefix0.A a, ) {
   print('isExactly=true');
   print('isSubtype=true');
   throw 42;
 }
-augment i0.B2 topLevelFunction2(i0.B1 a, ) {
+augment prefix0.B2 topLevelFunction2(prefix0.B1 a, ) {
   print('isExactly=false');
   print('isSubtype=true');
   throw 42;
 }
-augment i0.C2 topLevelFunction3(i0.C1 a, ) {
+augment prefix0.C2 topLevelFunction3(prefix0.C1 a, ) {
   print('isExactly=false');
   print('isSubtype=false');
   throw 42;
 }
-augment i0.D2 topLevelFunction4(i0.D1 a, ) {
+augment prefix0.D2 topLevelFunction4(prefix0.D1 a, ) {
   print('isExactly=false');
   print('isSubtype=false');
   throw 42;
diff --git a/pkg/front_end/test/macros/application/data/tests/supertypes.dart b/pkg/front_end/test/macros/application/data/tests/supertypes.dart
index 37c4038..5bf8b9e 100644
--- a/pkg/front_end/test/macros/application/data/tests/supertypes.dart
+++ b/pkg/front_end/test/macros/application/data/tests/supertypes.dart
@@ -4,26 +4,25 @@
 
 /*library: 
 Definitions:
-import 'dart:core' as i0;
-
+import 'dart:core' as prefix0;
 
 augment class A {
-augment i0.String getSuperClass() {
+augment prefix0.String getSuperClass() {
     return "Object";
   }
 }
 augment class B {
-augment i0.String getSuperClass() {
+augment prefix0.String getSuperClass() {
     return "A";
   }
 }
 augment class M {
-augment i0.String getSuperClass() {
+augment prefix0.String getSuperClass() {
     return "Object";
   }
 }
 augment class C {
-augment i0.String getSuperClass() {
+augment prefix0.String getSuperClass() {
     return "A";
   }
 }
diff --git a/pkg/front_end/test/macros/application/data/tests/type_annotations.dart b/pkg/front_end/test/macros/application/data/tests/type_annotations.dart
index f61a9a2..0ad8e21 100644
--- a/pkg/front_end/test/macros/application/data/tests/type_annotations.dart
+++ b/pkg/front_end/test/macros/application/data/tests/type_annotations.dart
@@ -4,32 +4,31 @@
 
 /*library: 
 Definitions:
-import 'dart:core' as i0;
-import 'dart:math' as i1;
-
+import 'dart:core' as prefix0;
+import 'dart:math' as prefix1;
 
 augment void topLevelFunction1() {
   throw 42;
 }
-augment i0.dynamic topLevelFunction2() {
+augment prefix0.dynamic topLevelFunction2() {
   throw 42;
 }
-augment i0.int topLevelFunction3() {
+augment prefix0.int topLevelFunction3() {
   throw 42;
 }
-augment i0.dynamic topLevelFunction4() {
+augment prefix0.dynamic topLevelFunction4() {
   throw 42;
 }
-augment i1.Random topLevelFunction5() {
+augment prefix1.Random topLevelFunction5() {
   throw 42;
 }
-augment i0.List<i0.int> topLevelFunction6() {
+augment prefix0.List<prefix0.int> topLevelFunction6() {
   throw 42;
 }
-augment i0.Map<i1.Random, i0.List<i0.int>> topLevelFunction7() {
+augment prefix0.Map<prefix1.Random, prefix0.List<prefix0.int>> topLevelFunction7() {
   throw 42;
 }
-augment i0.Map<i0.int?, i0.String>? topLevelFunction8() {
+augment prefix0.Map<prefix0.int?, prefix0.String>? topLevelFunction8() {
   throw 42;
 }
 */
diff --git a/pkg/front_end/test/macros/application/data/tests/types.dart b/pkg/front_end/test/macros/application/data/tests/types.dart
index 5da560d..6e3dacf 100644
--- a/pkg/front_end/test/macros/application/data/tests/types.dart
+++ b/pkg/front_end/test/macros/application/data/tests/types.dart
@@ -4,24 +4,23 @@
 
 /*library: 
 Types:
-import 'dart:core' as i0;
-import 'package:macro/macro.dart' as i1;
-
+import 'dart:core' as prefix0;
+import 'package:macro/macro.dart' as prefix1;
 
 class topLevelFunction1GeneratedClass {
   external void method();
 }
 class topLevelFunction2GeneratedClass {
-  external i0.dynamic method();
+  external prefix0.dynamic method();
 }
 class topLevelFunction3GeneratedClass {
-  external i0.int method();
+  external prefix0.int method();
 }
 class topLevelFunction4GeneratedClass {
-  external i1.FunctionTypesMacro1? method();
+  external prefix1.FunctionTypesMacro1? method();
 }
 class topLevelFunction5GeneratedClass {
-  external i0.dynamic method();
+  external prefix0.dynamic method();
 }*/
 
 import 'package:macro/macro.dart';
diff --git a/pkg/front_end/test/macros/application/data/tests/types.dart.expect b/pkg/front_end/test/macros/application/data/tests/types.dart.expect
index e36ef4f..ed9d33c 100644
--- a/pkg/front_end/test/macros/application/data/tests/types.dart.expect
+++ b/pkg/front_end/test/macros/application/data/tests/types.dart.expect
@@ -3,8 +3,8 @@
 import "dart:core" as core;
 import "package:macro/macro.dart" as mac;
 
-import "dart:core" as i0;
-import "package:macro/macro.dart" as i1;
+import "dart:core" as prefix0;
+import "package:macro/macro.dart" as prefix1;
 import "package:macro/macro.dart";
 
 class topLevelFunction1GeneratedClass extends core::Object { // from org-dartlang-augmentation:/a/b/c/main.dart-0
diff --git a/pkg/front_end/test/macros/declaration/macro_declaration_test.dart b/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
index a3486a1..d1e3f3b 100644
--- a/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
+++ b/pkg/front_end/test/macros/declaration/macro_declaration_test.dart
@@ -297,7 +297,8 @@
   String buildAugmentationLibrary(
       Iterable<MacroExecutionResult> macroResults,
       ResolvedIdentifier Function(Identifier) resolveIdentifier,
-      TypeAnnotation Function(OmittedTypeAnnotation) inferOmittedType) {
+      TypeAnnotation? Function(OmittedTypeAnnotation) inferOmittedType,
+      {Map<OmittedTypeAnnotation, String>? omittedTypes}) {
     return '';
   }
 
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index ac64436..9c7b439 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -122,6 +122,7 @@
 binds
 bj
 bk
+blend
 blindly
 blob
 blobs
@@ -1249,6 +1250,7 @@
 substed
 substitutes
 substitutor
+suffixing
 suggests
 suite
 sum
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index 6b546ad..4a4067b 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -1133,11 +1133,11 @@
 }
 
 intptr_t PassAsPointerAndValue(void* ptr, intptr_t value) {
-  return reinterpret_cast<intptr_t>(value);
+  return value;
 }
 
 intptr_t PassAsValueAndPointer(intptr_t value, void* ptr) {
-  return reinterpret_cast<intptr_t>(value);
+  return value;
 }
 
 intptr_t* AllocateResource(intptr_t value) {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 6cb8860..8bac5cf 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -304,6 +304,11 @@
 
 class StringRAII {
  public:
+  explicit StringRAII(StringRAII& origin) {
+    own_ = origin.own_;
+    s_ = origin.release();
+  }
+
   explicit StringRAII(const char* s) : s_(s), own_(false) {}
   explicit StringRAII(char* s) : s_(s), own_(true) {}
   ~StringRAII() {
@@ -385,9 +390,10 @@
 
   // Long relative path have to be converted to absolute path before prefixing.
   bool is_ok = true;
-  StringRAII absolute_path_raii = File::IsAbsolutePath(path)
-                                      ? StringRAII(path)
-                                      : ConvertToAbsolutePath(path, &is_ok);
+  StringRAII absolute_path_raii(
+      File::IsAbsolutePath(path)
+          ? StringRAII(path)
+          : StringRAII(ConvertToAbsolutePath(path, &is_ok)));
   if (!is_ok) {
     return StringRAII(path);
   }
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 11b0ead..243fac3 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -26,9 +26,8 @@
 static const int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
 static const int64_t kAppSnapshotPageSize = 16 * KB;
 
-static const char kMachOAppSnapshotSegmentName[] __attribute__((unused)) =
-    "__CUSTOM";
-static const char kMachOAppSnapshotSectionName[] __attribute__((unused)) =
+static const char kMachOAppSnapshotSegmentName[] DART_UNUSED = "__CUSTOM";
+static const char kMachOAppSnapshotSectionName[] DART_UNUSED =
     "__dart_app_snap";
 
 class MappedAppSnapshot : public AppSnapshot {
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index 174ed7f..1c542f2 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -50,7 +50,8 @@
 
 FILETIME GetFiletimeFromMillis(int64_t millis) {
   static const int64_t kTimeScaler = 10000;  // 100 ns to ms.
-  TimeStamp t = {.t_ = millis * kTimeScaler + kFileTimeEpoch};
+  TimeStamp t;
+  t.t_ = millis * kTimeScaler + kFileTimeEpoch;
   return t.ft_;
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
index ca7fcc2..c3682ed 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -326,7 +326,7 @@
 
   ILMatcher cursor(flow_graph, entry, true);
   // clang-format off
-  RELEASE_ASSERT(cursor.TryMatch({
+  std::initializer_list<MatchCode> expected = {
     kMatchAndMoveFunctionEntry,
     kMatchAndMoveCheckStackOverflow,
     kMoveDebugStepChecks,
@@ -339,7 +339,8 @@
     kMatchAndMoveClosureCall,
     kMoveDebugStepChecks,
     kMatchReturn,
-  }));
+  };
+  RELEASE_ASSERT(cursor.TryMatch(expected));
   // clang-format on
 }
 
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index 22de126..cc40ebb 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -26,28 +26,50 @@
 
 namespace dart {
 
-static Dart_CObject cobj_null = {.type = Dart_CObject_kNull,
-                                 .value = {.as_int64 = 0}};
-static Dart_CObject cobj_sentinel = {.type = Dart_CObject_kUnsupported};
-static Dart_CObject cobj_transition_sentinel = {.type =
-                                                    Dart_CObject_kUnsupported};
-static Dart_CObject cobj_empty_array = {
-    .type = Dart_CObject_kArray,
-    .value = {.as_array = {.length = 0, .values = nullptr}}};
-static Dart_CObject cobj_zero_array_element = {.type = Dart_CObject_kInt32,
-                                               .value = {.as_int32 = 0}};
-static Dart_CObject* cobj_zero_array_values[1] = {&cobj_zero_array_element};
-static Dart_CObject cobj_zero_array = {
-    .type = Dart_CObject_kArray,
-    .value = {.as_array = {.length = 1, .values = &cobj_zero_array_values[0]}}};
-static Dart_CObject cobj_dynamic_type = {.type = Dart_CObject_kUnsupported};
-static Dart_CObject cobj_void_type = {.type = Dart_CObject_kUnsupported};
-static Dart_CObject cobj_empty_type_arguments = {.type =
-                                                     Dart_CObject_kUnsupported};
-static Dart_CObject cobj_true = {.type = Dart_CObject_kBool,
-                                 .value = {.as_bool = true}};
-static Dart_CObject cobj_false = {.type = Dart_CObject_kBool,
-                                  .value = {.as_bool = false}};
+
+static Dart_CObject cobj_sentinel = {Dart_CObject_kUnsupported, {false}};
+static Dart_CObject cobj_transition_sentinel = {Dart_CObject_kUnsupported,
+                                                {false}};
+static Dart_CObject cobj_dynamic_type = {Dart_CObject_kUnsupported, {false}};
+static Dart_CObject cobj_void_type = {Dart_CObject_kUnsupported, {false}};
+static Dart_CObject cobj_empty_type_arguments = {Dart_CObject_kUnsupported,
+                                                 {false}};
+static Dart_CObject cobj_true = {Dart_CObject_kBool, {true}};
+static Dart_CObject cobj_false = {Dart_CObject_kBool, {false}};
+
+// Workaround for lack of designated initializers until we adopt c++20
+class PredefinedCObjects {
+ public:
+  static PredefinedCObjects& getInstance() {
+    static PredefinedCObjects instance;
+    return instance;
+  }
+
+  static Dart_CObject* cobj_null() { return &getInstance().cobj_null_; }
+  static Dart_CObject* cobj_empty_array() { return &getInstance().cobj_empty_array_; }
+  static Dart_CObject* cobj_zero_array() { return &getInstance().cobj_zero_array_; }
+
+ private:
+  PredefinedCObjects() {
+    cobj_null_.type = Dart_CObject_kNull;
+    cobj_null_.value.as_int64 = 0;
+    cobj_empty_array_.type = Dart_CObject_kArray;
+    cobj_empty_array_.value.as_array = {0, nullptr};
+    cobj_zero_array_element.type = Dart_CObject_kInt32;
+    cobj_zero_array_element.value.as_int32 = 0;
+    cobj_zero_array_values[0] = {&cobj_zero_array_element};
+    cobj_zero_array_.type = Dart_CObject_kArray;
+    cobj_zero_array_.value.as_array = {1, &cobj_zero_array_values[0]};
+  }
+
+  Dart_CObject cobj_null_;
+  Dart_CObject cobj_empty_array_;
+  Dart_CObject* cobj_zero_array_values[1];
+  Dart_CObject cobj_zero_array_element;
+  Dart_CObject cobj_zero_array_;
+
+  DISALLOW_COPY_AND_ASSIGN(PredefinedCObjects);
+};
 
 enum class MessagePhase {
   kBeforeTypes = 0,
@@ -2801,7 +2823,7 @@
     for (intptr_t i = 0; i < count; i++) {
       Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
       intptr_t length = array->value.as_array.length;
-      s->WriteRef(&cobj_null);  // TypeArguments
+      s->WriteRef(PredefinedCObjects::cobj_null());  // TypeArguments
       for (intptr_t j = 0; j < length; j++) {
         s->WriteRef(array->value.as_array.values[j]);
       }
@@ -3242,7 +3264,7 @@
   intptr_t cid;
   switch (object->type) {
     case Dart_CObject_kNull:
-      ForwardRef(object, &cobj_null);
+      ForwardRef(object, PredefinedCObjects::cobj_null());
       return true;
     case Dart_CObject_kBool:
       ForwardRef(object, object->value.as_bool ? &cobj_true : &cobj_false);
@@ -3640,11 +3662,11 @@
 }
 
 void ApiMessageSerializer::AddBaseObjects() {
-  AddBaseObject(&cobj_null);
+  AddBaseObject(PredefinedCObjects::cobj_null());
   AddBaseObject(&cobj_sentinel);
   AddBaseObject(&cobj_transition_sentinel);
-  AddBaseObject(&cobj_empty_array);
-  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(PredefinedCObjects::cobj_empty_array());
+  AddBaseObject(PredefinedCObjects::cobj_zero_array());
   AddBaseObject(&cobj_dynamic_type);
   AddBaseObject(&cobj_void_type);
   AddBaseObject(&cobj_empty_type_arguments);
@@ -3653,11 +3675,11 @@
 }
 
 void ApiMessageDeserializer::AddBaseObjects() {
-  AddBaseObject(&cobj_null);
+  AddBaseObject(PredefinedCObjects::cobj_null());
   AddBaseObject(&cobj_sentinel);
   AddBaseObject(&cobj_transition_sentinel);
-  AddBaseObject(&cobj_empty_array);
-  AddBaseObject(&cobj_zero_array);
+  AddBaseObject(PredefinedCObjects::cobj_empty_array());
+  AddBaseObject(PredefinedCObjects::cobj_zero_array());
   AddBaseObject(&cobj_dynamic_type);
   AddBaseObject(&cobj_void_type);
   AddBaseObject(&cobj_empty_type_arguments);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index fe33347..9c49a86 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -10455,12 +10455,14 @@
   // code (in which case the caller might get different answers if it obtains
   // the guarded cid multiple times).
   Thread* thread = Thread::Current();
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(!thread->IsInsideCompiler() || is_static());
+#else
   ASSERT(!thread->IsInsideCompiler() ||
-#if !defined(DART_PRECOMPILED_RUNTIME)
          ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
-#endif
          is_static());
 #endif
+#endif
   return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
       &untag()->guarded_cid_);
 }
@@ -10470,12 +10472,14 @@
   // Same assert as guarded_cid(), because is_nullable() also needs to be
   // consistent for the background compiler.
   Thread* thread = Thread::Current();
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(!thread->IsInsideCompiler() || is_static());
+#else
   ASSERT(!thread->IsInsideCompiler() ||
-#if !defined(DART_PRECOMPILED_RUNTIME)
          ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
-#endif
          is_static());
 #endif
+#endif
   return is_nullable_unsafe();
 }
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 8c352db..64209d3 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -269,7 +269,12 @@
   // exceptions. This allows triggering the normal TSAN shadow stack unwinding
   // implementation.
   // -> See https://dartbug.com/47472#issuecomment-948235479 for details.
+#if defined(USING_THREAD_SANITIZER)
   void* setjmp_function = reinterpret_cast<void*>(&setjmp);
+#else
+  // MSVC (on Windows) is not happy with getting address of purely intrinsic.
+  void* setjmp_function = nullptr;
+#endif
   jmp_buf* setjmp_buffer = nullptr;
   uword exception_pc = 0;
   uword exception_sp = 0;
diff --git a/tools/VERSION b/tools/VERSION
index 3c727f4..d901ea1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 228
+PRERELEASE 229
 PRERELEASE_PATCH 0
\ No newline at end of file