Version 3.9.0-328.0.dev

Merge 1afbc518744af66c854086351322524225eb9fc3 into dev
diff --git a/DEPS b/DEPS
index 777926e..1803e30 100644
--- a/DEPS
+++ b/DEPS
@@ -140,7 +140,7 @@
   "i18n_rev": "42c49328f8c040b663c2a2d94be9b6ddd80a70bd",
   "leak_tracker_rev": "f5620600a5ce1c44f65ddaa02001e200b096e14c", # rolled manually
   "material_color_utilities_rev": "799b6ba2f3f1c28c67cc7e0b4f18e0c7d7f3c03e",
-  "native_rev": "7944c5a0d26f3948273096239c9c2a8d6f0cda54", # rolled manually while native assets are experimental
+  "native_rev": "723cd56a5edc89699db32bca1b5bf91aa0bcf0cf", # rolled manually while native assets are experimental
   "protobuf_rev": "bce362dec347ae3cca085bd28db2aa2649f754e5",
   "pub_rev": "f6457fd20c9a9734a747262b1bcc2200c8357efb", # rolled manually
   "shelf_rev": "082d3ac2d13a98700d8148e8fad8f3e12a6fd0e1",
diff --git a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
index dae3828..5dc0d5a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
@@ -32,7 +32,7 @@
 @AnalyzerPublicApi(message: 'exported by package:analyzer/error/error.dart')
 abstract class DiagnosticCode {
   /// Regular expression for identifying positional arguments in error messages.
-  static final RegExp _positionalArgumentRegExp = new RegExp(r'{(\d+)\}');
+  static final RegExp _positionalArgumentRegExp = new RegExp(r'\{(\d+)\}');
 
   /**
    * The name of the error code.
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
index 39ad136..c59cbf8 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
@@ -65,6 +65,7 @@
     'constructor': EmptyProducer(),
     'enum': EmptyProducer(),
     'extension': EmptyProducer(),
+    'extensionType': EmptyProducer(),
     'field': EmptyProducer(),
     'function': EmptyProducer(),
     'getter': EmptyProducer(),
@@ -76,6 +77,7 @@
     'inClass': EmptyProducer(),
     'inEnum': EmptyProducer(),
     'inExtension': EmptyProducer(),
+    'inExtensionType': EmptyProducer(),
     'inMixin': EmptyProducer(),
   });
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 7ace4c3..cf216b6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -47,19 +47,16 @@
     // TODO(brianwilkerson): Check the resolved element, if one exists, for more
     //  accurate results.
     return switch (kind) {
-      ElementKind.classKind =>
-        // TODO(brianwilkerson): Handle this case.
-        false,
+      ElementKind.classKind => _matchesType(node),
       ElementKind.constantKind =>
         // TODO(brianwilkerson): Handle this case.
         false,
       ElementKind.constructorKind => _matchesConstructor(node),
-      ElementKind.enumKind =>
-        // TODO(brianwilkerson): Handle this case.
-        false,
+      ElementKind.enumKind => _matchesType(node),
       ElementKind.extensionKind =>
         // TODO(brianwilkerson): Handle this case.
         false,
+      ElementKind.extensionTypeKind => _matchesType(node),
       ElementKind.fieldKind =>
         // TODO(brianwilkerson): Handle this case.
         false,
@@ -68,15 +65,11 @@
         // TODO(brianwilkerson): Handle this case.
         false,
       ElementKind.methodKind => _matchesMethod(node),
-      ElementKind.mixinKind =>
-        // TODO(brianwilkerson): Handle this case.
-        false,
+      ElementKind.mixinKind => _matchesType(node),
       ElementKind.setterKind =>
         // TODO(brianwilkerson): Handle this case.
         false,
-      ElementKind.typedefKind =>
-        // TODO(brianwilkerson): Handle this case.
-        false,
+      ElementKind.typedefKind => _matchesType(node),
       ElementKind.variableKind =>
         // TODO(brianwilkerson): Handle this case.
         false,
@@ -167,6 +160,22 @@
     return false;
   }
 
+  bool _matchesType(AstNode node) {
+    if (components.length > 1) {
+      return false;
+    }
+    var name = components[0];
+    if (node is Identifier) {
+      // A plain or prefixed identifier with the correct name.
+      var typeName = _nameFromIdentifier(node);
+      return name == typeName;
+    }
+    if (node is NamedType) {
+      return name == node.name.lexeme;
+    }
+    return false;
+  }
+
   String _nameFromIdentifier(Identifier identifier) {
     if (identifier is SimpleIdentifier) {
       return identifier.name;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
index 6479a1c..4511470 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
@@ -4,45 +4,29 @@
 
 /// An indication of the kind of an element.
 enum ElementKind {
-  classKind,
-  constantKind,
-  constructorKind,
-  enumKind,
-  extensionKind,
-  fieldKind,
-  functionKind,
-  getterKind,
-  methodKind,
-  mixinKind,
-  setterKind,
-  typedefKind,
-  variableKind,
-}
+  classKind('class'),
+  constantKind('constant'),
+  constructorKind('constructor'),
+  enumKind('enum'),
+  extensionKind('extension'),
+  extensionTypeKind('extensionType'),
+  fieldKind('field'),
+  functionKind('function'),
+  getterKind('getter'),
+  methodKind('method'),
+  mixinKind('mixin'),
+  setterKind('setter'),
+  typedefKind('typedef'),
+  variableKind('variable');
 
-extension ElementKindUtilities on ElementKind {
-  /// Return a human readable name for the kind.
-  String get displayName {
-    return switch (this) {
-      ElementKind.classKind => 'class',
-      ElementKind.constantKind => 'constant',
-      ElementKind.constructorKind => 'constructor',
-      ElementKind.enumKind => 'enum',
-      ElementKind.extensionKind => 'extension',
-      ElementKind.fieldKind => 'field',
-      ElementKind.functionKind => 'function',
-      ElementKind.getterKind => 'getter',
-      ElementKind.methodKind => 'method',
-      ElementKind.mixinKind => 'mixin',
-      ElementKind.setterKind => 'setter',
-      ElementKind.typedefKind => 'typedef',
-      ElementKind.variableKind => 'variable',
-    };
-  }
+  /// A human readable name for the kind.
+  final String displayName;
+  const ElementKind(this.displayName);
 
-  /// Return the element kind corresponding to the given [name].
+  /// The element kind corresponding to the given [name].
   static ElementKind? fromName(String name) {
-    for (var kind in ElementKind.values) {
-      if (kind.toString() == 'ElementKind.${name}Kind') {
+    for (var kind in values) {
+      if (kind.displayName == name) {
         return kind;
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index cd3f11e..67c2e86 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -28,7 +28,7 @@
   final List<String> components;
 
   /// A list of the kinds of elements that are appropriate for some given
-  /// location in the code An empty list represents all kinds rather than no
+  /// location in the code. An empty list represents all kinds rather than no
   /// kinds.
   final List<ElementKind> validKinds;
 
@@ -291,12 +291,21 @@
     //  get a more exact matcher.
     // TODO(brianwilkerson): Use 'new' for the name of the unnamed constructor.
     var constructorName = node.name?.name ?? ''; // ?? 'new';
-    var className = node.type.name.lexeme;
+    var typeName = node.type.name.lexeme;
     _addMatcher(
-      components: [constructorName, className],
+      components: [constructorName, typeName],
       kinds: const [ElementKind.constructorKind],
     );
-    _addMatcher(components: [className], kinds: const [ElementKind.classKind]);
+    _addMatcher(
+      components: [typeName],
+      kinds: const [
+        ElementKind.classKind,
+        ElementKind.enumKind,
+        ElementKind.extensionTypeKind,
+        ElementKind.typedefKind,
+        ElementKind.mixinKind, // Can't *yet* have factory constructors.
+      ],
+    );
   }
 
   /// Build a matcher for the extension.
@@ -369,10 +378,14 @@
         kinds: [
           ElementKind.classKind,
           ElementKind.constructorKind,
+          ElementKind.enumKind,
           ElementKind.extensionKind,
+          ElementKind.extensionTypeKind,
           ElementKind.functionKind,
           ElementKind.getterKind,
           ElementKind.methodKind,
+          ElementKind.mixinKind,
+          ElementKind.typedefKind,
         ],
       );
     }
@@ -391,6 +404,7 @@
       kinds: const [
         ElementKind.classKind,
         ElementKind.enumKind,
+        ElementKind.extensionTypeKind,
         ElementKind.mixinKind,
         ElementKind.typedefKind,
       ],
@@ -413,20 +427,17 @@
     //  get a more exact matcher.
     var prefix = node.prefix;
     if (prefix.element is PrefixElement) {
-      var parent = node.parent;
-      if ((parent is NamedType && parent.parent is! ConstructorName) ||
-          (parent is PropertyAccess && parent.target == node)) {
-        _addMatcher(
-          components: [node.identifier.name],
-          kinds: const [
-            ElementKind.classKind,
-            ElementKind.enumKind,
-            ElementKind.extensionKind,
-            ElementKind.mixinKind,
-            ElementKind.typedefKind,
-          ],
-        );
-      }
+      _addMatcher(
+        components: [node.identifier.name],
+        kinds: const [
+          ElementKind.classKind,
+          ElementKind.enumKind,
+          ElementKind.extensionKind,
+          ElementKind.extensionTypeKind,
+          ElementKind.mixinKind,
+          ElementKind.typedefKind,
+        ],
+      );
       _addMatcher(
         components: [node.identifier.name],
         kinds: const [
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
index 3622581..d724053 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/replaced_by.dart
@@ -43,33 +43,46 @@
   // ignore: library_private_types_in_public_api
   void apply(DartFileEditBuilder builder, DataDrivenFix fix, _Data data) {
     var referenceRange = data.referenceRange;
+    ImportLibraryElementResult? importElement;
+    var libraryUris = newElement.libraryUris;
+    if (libraryUris.isNotEmpty) {
+      // A library URI from `libraryUris`, either one already imported,
+      // or the first one in the list.
+      var libraryUri = _selectImportUri(builder, libraryUris);
+      importElement = builder.importLibraryElement(libraryUri);
+    }
     builder.addReplacement(referenceRange, (builder) {
-      if (data.replacement != null) {
-        builder.write(data.replacement!);
+      var components = newElement.components;
+      if (data.isInstanceMember && !replaceTarget) {
+        // Just replace the member on the same type.
+        builder.write(components.first);
       } else {
-        var templateContext = TemplateContext(fix.node, fix.utils);
-        var components = newElement.components;
+        // Replaces a static access, including any prefix and static scope.
+        if (importElement?.prefix case var prefix?) {
+          builder
+            ..write(prefix)
+            ..write('.');
+        }
         if (components[0].isEmpty) {
+          // An unnamed constructor, always directly inside top-level declaration.
           builder.write(components[1]);
         } else {
           builder.write(components.reversed.join('.'));
         }
-        if (arguments.isNotEmpty) {
-          builder.write('(');
-          arguments.first.writeOn(builder, templateContext);
-          for (int i = 1; i < arguments.length; i++) {
-            builder.write(',');
-            arguments[i].writeOn(builder, templateContext);
-          }
-          builder.write(')');
+      }
+      if (arguments.isNotEmpty) {
+        var templateContext = TemplateContext(fix.node, fix.utils);
+        builder.write('(');
+        arguments.first.writeOn(builder, templateContext);
+        for (int i = 1; i < arguments.length; i++) {
+          builder.write(',');
+          arguments[i].writeOn(builder, templateContext);
         }
+        builder.write(')');
+      } else if (data.suffix case var suffix?) {
+        builder.write(suffix);
       }
     });
-    var libraryUris = newElement.libraryUris;
-    if (libraryUris.isEmpty) return;
-    if (!libraryUris.any((uri) => builder.importsLibrary(uri))) {
-      builder.importLibraryElement(libraryUris.first);
-    }
   }
 
   @override
@@ -78,180 +91,213 @@
   // ignore: library_private_types_in_public_api
   _Data? validate(DataDrivenFix fix) {
     var node = fix.node;
-    if (replaceTarget) {
-      // This does not work if the element to be replaced is cascaded.
-      var parent = node.parent;
-      if (parent != null) {
-        var target = switch (parent) {
-          MethodInvocation() => parent.target,
-          PropertyAccess() => parent.target,
-          PrefixedIdentifier() => parent,
-          _ => null,
-        };
-        if (target == null ||
-            // replacing method with getter is not allowed
-            (parent is MethodInvocation &&
-                newElement.kind == ElementKind.getterKind)) {
-          return null;
-        }
-        return _Data(range.startEnd(target, node));
-      } else {
-        return null;
+    // Replaces all targets of static accesses, including prefixes.
+    // If [replaceTarget] is `true`, also replace targets of instance
+    // accesses.
+    if (node is SimpleIdentifier) {
+      // Include prefix if prefixed.
+      var element = node.element;
+      if (element is ExecutableElement &&
+          !element.isStatic &&
+          element is! ConstructorElement) {
+        var result = _instanceInvocation(fix, node, element, replaceTarget);
+        return result;
       }
     }
-    if (node is SimpleIdentifier) {
-      var element = node.element;
-      if (element is ExecutableElement && !element.isStatic) {
-        return _instance(node, element);
-      }
-
-      var components = fix.element.components;
-      if (components.isEmpty) {
-        return null;
-      } else if (components.length == 1) {
-        if (components[0] != node.name) {
-          return null;
-        }
-        // We have an '<element>' pattern, so we replace the name.
-        return _Data(range.node(node));
-      }
-      // The element being replaced is a member in a top-level element.
-      var containerName = components[1];
-      if (components[0].isEmpty && containerName == node.name) {
-        // We have a '<className>()' pattern, so we replace the class name.
-        return _Data(range.node(node));
-      }
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        var target = parent.target;
-        if (target == null) {
-          // We have a '<member>()' pattern, so we replace the member name.
-          return _Data(range.node(node));
-        } else if (target is SimpleIdentifier && target.name == containerName) {
-          // We have a '<container>.<member>()' pattern, so we replace both parts.
-          return _Data(range.startEnd(target, node));
-        } else if (target is PrefixedIdentifier) {
-          if (target.prefix.element is PrefixElement &&
-              target.identifier.name == containerName) {
-            // We have a '<prefix>.<container>.<member>()' pattern so we leave
-            // the prefix while replacing the rest.
-            return _Data(range.startEnd(target.identifier, node));
-          }
-          // We shouldn't get here.
-          return null;
-        }
-      } else if (parent is NamedType) {
-        var grandparent = parent.parent;
-        if (grandparent is ConstructorName &&
-            grandparent.name?.name == components[0]) {
-          // TODO(brianwilkerson): This doesn't correctly handle constructor
-          //  invocations with type arguments. We really need to replace the
-          //  class and constructor names separately.
-          return _Data(range.node(grandparent));
-        }
-      } else if (parent is PrefixedIdentifier) {
-        if (parent.prefix.element is PrefixElement) {
-          // We have a '<prefix>.<topLevel>' pattern so we leave the prefix
-          // while replacing the rest.
-          return _Data(range.node(node));
-        }
-        // We have a '<container>.<member>' pattern so we replace both parts.
-        return _Data(range.node(parent));
-      } else if (parent is PropertyAccess) {
-        var target = parent.target;
-        if (target is PrefixedIdentifier) {
-          // We have a '<prefix>.<container>.<member>' pattern so we leave the
-          // prefix while replacing the rest.
-          return _Data(range.startEnd(target.identifier, node));
-        }
-        // We have a '<container>.<member>' pattern so we replace both parts.
-        return _Data(range.node(parent));
-      }
-      // We have a '<member>' pattern so we replace the member name.
-      return _Data(range.node(node));
-    } else if (node is PrefixedIdentifier) {
-      var parent = node.parent;
-      if (parent is NamedType) {
-        var identifier = node.identifier;
-        var components = fix.element.components;
-        if (components.length > 1 &&
-            components[0].isEmpty &&
-            components[1] == identifier.name) {
-          // We have a '<prefix>.<className>' pattern, so we replace only the
-          // class name.
-          return _Data(range.node(identifier));
-        }
-      }
-    } else if (node is NamedType) {
-      var identifier = node.name;
-      var components = fix.element.components;
-      if (components.length > 1 &&
-          components[0].isEmpty &&
-          components[1] == identifier.lexeme) {
-        // We have a '<prefix>.<className>' pattern, so we replace only the
-        // class name.
-        return _Data(range.token(identifier));
-      }
-      var parent = node.parent;
-      if (parent is ConstructorName) {
-        var classNameToken = parent.type.name;
-        var constructorNameNode = parent.name;
-        var constructorName = constructorNameNode?.name ?? '';
-        var components = fix.element.components;
-        if (components.length == 2 &&
-            constructorName == components[0] &&
-            classNameToken.lexeme == components[1]) {
-          if (constructorNameNode != null) {
-            return _Data(range.startEnd(classNameToken, constructorNameNode));
-          }
-          return _Data(range.token(classNameToken));
-        }
-      }
-    } else if (node is ConstructorName) {
-      var classNameToken = node.type.name;
-      var constructorNameNode = node.name;
-      var constructorName = constructorNameNode?.name ?? '';
-      var components = fix.element.components;
-      if (components.length == 2 &&
-          constructorName == components[0] &&
-          classNameToken.lexeme == components[1]) {
-        if (constructorNameNode != null) {
-          return _Data(range.startEnd(classNameToken, constructorNameNode));
-        }
-        return _Data(range.token(classNameToken));
-      }
+    var sourceRange = _rangeWithTarget(node, fix);
+    if (sourceRange != null) {
+      return _Data(sourceRange);
     }
     return null;
   }
 
-  /// Returns a replacement of an instance member.
-  _Data? _instance(AstNode node, ExecutableElement element) {
-    var newComponents = newElement.components;
+  /// Replacement range of a function, getter or setter invocation.
+  ///
+  /// If [replaceTarget] is true, the target is also replaced.
+  /// That should always be the case for static functions, and is true
+  /// for instance functions if the fix is set to replace the target.
+  ///
+  // TODO(brianwilkinson): Maybe also handle setters<->one parameter functions
+  // switching between `(target.)setter = e` and `(target.)method(e)`.
+  _Data? _instanceInvocation(
+    DataDrivenFix fix,
+    SimpleIdentifier node,
+    ExecutableElement element,
+    bool replaceTarget,
+  ) {
     var newKind = newElement.kind;
-    var suffix = '';
+    String? suffix;
     SourceRange? referenceRange;
     if (newKind == ElementKind.methodKind && element is GetterElement) {
+      // Convert from getter to method with no type arguments or arguments.
       suffix = '()';
-      referenceRange = range.node(node);
+      AstNode rangeStart;
+      if (replaceTarget) {
+        rangeStart = _simpleIdentifierRangeStartWithTarget(node);
+      } else {
+        rangeStart = node;
+      }
+      referenceRange = range.startEnd(rangeStart, node);
     } else if (newKind == ElementKind.getterKind) {
+      // Convert from function call to getter,
+      // only if no arguments or type arguments.
       var parent = node.parent;
       if (parent is MethodInvocation) {
         var argumentList = parent.argumentList;
         if (argumentList.arguments.isNotEmpty) {
           return null;
         }
-        referenceRange = range.startEnd(node, argumentList);
+        var argumentTypes = parent.typeArgumentTypes;
+        if (argumentTypes != null && argumentTypes.isNotEmpty) {
+          return null;
+        }
+        if (replaceTarget) {
+          var rangeStart = _simpleIdentifierRangeStartWithTarget(node);
+          referenceRange = range.startEnd(rangeStart, argumentList);
+        } else {
+          referenceRange = range.startEnd(node, argumentList);
+        }
       }
     }
-    if (referenceRange == null) return null;
-    return _Data(referenceRange, replacement: '${newComponents[0]}$suffix');
+
+    if (referenceRange == null) {
+      if (replaceTarget) {
+        var rangeStart = _simpleIdentifierRangeStartWithTarget(node);
+        referenceRange = range.startEnd(rangeStart, node);
+      } else {
+        return null;
+      }
+    }
+    return _Data(referenceRange, suffix: suffix, isInstanceMember: true);
+  }
+
+  /// Finds a range for a node that includes its target.
+  ///
+  /// For a [NamedType], it does not include type arguments or `?`.
+  SourceRange? _rangeWithTarget(AstNode node, DataDrivenFix fix) {
+    var elements = fix.element.components;
+    if (elements.isEmpty) return null;
+    var simpleName = elements[0];
+    if (node is SimpleIdentifier) {
+      if (node.name != (simpleName.isNotEmpty ? simpleName : elements[1])) {
+        return null;
+      }
+      var rangeStart = _simpleIdentifierRangeStartWithTarget(node);
+      return range.startEnd(rangeStart, node);
+    } else if (node is PrefixedIdentifier) {
+      return range.startEnd(node.prefix, node);
+    } else if (node is ConstructorName) {
+      // TODO(brianwilkinson): Remember the type arguments, so they can be retained when
+      // replacing a named constructor, or placed correctly if replacing with
+      // a named constructor.
+      if (node.name != null) {
+        return range.node(node);
+      } else {
+        // Return the type's names only (omit/retain type arguments).
+        return range.node(node.type);
+      }
+    } else if (node is NamedType) {
+      var typeName = node.name.lexeme;
+      if (elements.length == 1 && simpleName == typeName ||
+          elements.length == 2 &&
+              simpleName.isEmpty &&
+              elements[1] == typeName) {
+        // Omit trailing type parameters and/or `?`,
+        // only include import prefix and type name.
+        return range.startEnd(node, node.name);
+      } else {
+        // Check if it's a static member or constructor of a deprecated type.
+        if (elements.length == 2 && elements[1] == typeName) {
+          // And elements[0] is not empty.
+
+          // Static accesses on a deprecated type.
+          var parent = node.parent;
+          if (parent is ConstructorName && parent.name?.name == simpleName) {
+            // TODO(brianwilkinson): Retain type arguments.
+            return range.node(parent);
+          }
+          if (parent is MethodInvocation &&
+              parent.methodName.name == simpleName) {
+            return range.startEnd(node, parent.methodName);
+          }
+          if (parent is PropertyAccess &&
+              parent.propertyName.name == simpleName) {
+            return range.startEnd(node, parent.propertyName);
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  /// The start of any target of a static name, or the name itself.
+  ///
+  /// If the name has a static target or prefix, it should be included in the
+  /// range, otherwise just start at the node itself.
+  /// This checks any parent node which can contain a [SimpleIdentifier],
+  /// where that identifier can be the target of a static access,
+  /// and it then includes all prior tokens of the expression.
+  /// Some nodes may contain more than one [SimpleIdentifier],
+  /// but they can all be handled by finding the start of the expression.
+  /// (Can't just use the start of the parent node, since that can include
+  /// metadata.)
+  ///
+  AstNode _simpleIdentifierRangeStartWithTarget(SimpleIdentifier node) {
+    var parent = node.parent;
+    if (parent is MethodInvocation) {
+      // Correct whether `node` is `parent.target` or `parent.methodName`.
+      // The `target` can be `null` if the access is a cascade selector.
+      // In that case, we cannot replace the target.
+      // Also, `parent.operator` must be `.` for a static access.
+      return parent.target ?? node;
+    } else if (parent is PropertyAccess) {
+      // Correct whether `node` is `parent.target` or `parent.propertyName`.
+      // The `target` can be `null` if the access is a cascade selector.
+      // Also, `parent.operator` must be `.` for a static access.
+      return parent.target ?? node;
+    } else if (parent is PrefixedIdentifier) {
+      // Correct whether `node` is `parent.prefix` or `parent.identifier`.
+      return parent.prefix;
+    } else if (parent is ConstructorName) {
+      // Correct whether `node` is `parent.type` or `parent.name`.
+      // TODO(brianwilkinson): When replacing a named constructor, retain the type arguments.
+      return parent.type;
+    } else if (parent is Annotation) {
+      // Correct whether `node` is `parent.prefix` or `parent.constructorName`.
+      return parent.name;
+    } else if (parent is DotShorthandConstructorInvocation ||
+        parent is DotShorthandInvocation ||
+        parent is DotShorthandPropertyAccess) {
+      // Will insert a non-dot-shorthand reference to the new value.
+      return parent!;
+    }
+    // Nothing before the node.
+    return node;
+  }
+
+  // Find the import element of `libraryUri`.
+  static Uri _selectImportUri(
+    DartFileEditBuilder builder,
+    List<Uri> libraryUris,
+  ) {
+    assert(libraryUris.isNotEmpty);
+    for (var uri in libraryUris) {
+      if (builder.importsLibrary(uri)) return uri;
+    }
+    return libraryUris.first;
   }
 }
 
 /// The data about a reference to an element that's been replaced.
 class _Data {
   final SourceRange referenceRange;
-  final String? replacement;
 
-  _Data(this.referenceRange, {this.replacement});
+  /// Written after the reference, if not `null`.
+  ///
+  /// Used to add `()` when replacing a getter with a function.
+  final String? suffix;
+
+  final bool isInstanceMember;
+
+  _Data(this.referenceRange, {this.suffix, this.isInstanceMember = false});
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index 386b5d7..068796f 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -57,6 +57,7 @@
   static const String _expressionKey = 'expression';
   static const String _extendsKey = 'extends';
   static const String _extensionKey = 'extension';
+  static const String _extensionTypeKey = 'extensionType';
   static const String _fieldKey = 'field';
   static const String _functionKey = 'function';
   static const String _getterKey = 'getter';
@@ -64,6 +65,7 @@
   static const String _inClassKey = 'inClass';
   static const String _inEnumKey = 'inEnum';
   static const String _inExtensionKey = 'inExtension';
+  static const String _inExtensionTypeKey = 'inExtensionType';
   static const String _indexKey = 'index';
   static const String _inMixinKey = 'inMixin';
   static const String _kindKey = 'kind';
@@ -92,12 +94,27 @@
   /// A table mapping top-level keys for member elements to the list of keys for
   /// the possible containers of that element.
   static const Map<String, Set<String>> _containerKeyMap = {
-    _constructorKey: {_inClassKey},
+    _constructorKey: {_inClassKey, _inExtensionTypeKey},
     _constantKey: {_inEnumKey},
-    _fieldKey: {_inClassKey, _inExtensionKey, _inMixinKey},
-    _getterKey: {_inClassKey, _inExtensionKey, _inMixinKey},
-    _methodKey: {_inClassKey, _inExtensionKey, _inMixinKey},
-    _setterKey: {_inClassKey, _inExtensionKey, _inMixinKey},
+    _fieldKey: {_inClassKey, _inExtensionKey, _inExtensionTypeKey, _inMixinKey},
+    _getterKey: {
+      _inClassKey,
+      _inExtensionKey,
+      _inExtensionTypeKey,
+      _inMixinKey,
+    },
+    _methodKey: {
+      _inClassKey,
+      _inExtensionKey,
+      _inExtensionTypeKey,
+      _inMixinKey,
+    },
+    _setterKey: {
+      _inClassKey,
+      _inExtensionKey,
+      _inExtensionTypeKey,
+      _inMixinKey,
+    },
   };
 
   static const String _addParameterKind = 'addParameter';
@@ -844,12 +861,13 @@
       var elementPair = _singleKey(
         map: node,
         translators: {
-          {
+          const {
             _classKey,
             _constantKey,
             _constructorKey,
             _enumKey,
             _extensionKey,
+            _extensionTypeKey,
             _fieldKey,
             _functionKey,
             _getterKey,
@@ -946,7 +964,7 @@
       }
       return ElementDescriptor(
         libraryUris: uris,
-        kind: ElementKindUtilities.fromName(elementKey)!,
+        kind: ElementKind.fromName(elementKey)!,
         isStatic: isStatic,
         components: components,
       );
@@ -1160,13 +1178,12 @@
     bool? replaceTarget;
     var replaceTargetNode = node.valueAt(_replaceTarget);
     replaceTarget =
-        replaceTargetNode == null
-            ? false
-            : _translateBool(
-                  replaceTargetNode,
-                  ErrorContext(key: _replaceTarget, parentNode: node),
-                ) ??
-                false;
+        replaceTargetNode != null &&
+        (_translateBool(
+              replaceTargetNode,
+              ErrorContext(key: _replaceTarget, parentNode: node),
+            ) ??
+            false);
     var argumentsNode = node.valueAt(_arguments);
     var argumentList =
         argumentsNode == null
@@ -1474,6 +1491,14 @@
       ElementKind.setterKind,
       ElementKind.variableKind,
     });
+    // Type declarations can replace each other.
+    addSet({
+      ElementKind.classKind,
+      ElementKind.enumKind,
+      ElementKind.extensionTypeKind,
+      ElementKind.mixinKind,
+      ElementKind.typedefKind,
+    });
     return types;
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index 96d553f..259739a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -487,7 +487,7 @@
     date: DateTime.now(),
     element: ElementDescriptor(
       libraryUris: [Uri.parse(importUri)],
-      kind: ElementKindUtilities.fromName(_kind)!,
+      kind: ElementKind.fromName(_kind)!,
       isStatic: isStatic,
       components: components ?? ['m', 'C'],
     ),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
index a930feb..62048c7 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
@@ -13,18 +13,26 @@
 import 'package:analyzer/utilities/package_config_file_builder.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
+import '../../../../../abstract_single_unit.dart';
 import '../fix_processor.dart';
 
 /// A base class defining support for writing fix processor tests for
 /// data-driven fixes.
-abstract class DataDrivenFixProcessorTest extends FixProcessorTest {
-  /// Return the URI used to import the library created by [setPackageContent].
+abstract class DataDrivenBulkFixProcessorTest extends BulkFixProcessorTest
+    with DataDrivenFixProcessorTestMixin {}
+
+/// A base class defining support for writing fix processor tests for
+/// data-driven fixes.
+abstract class DataDrivenFixProcessorTest extends FixProcessorTest
+    with DataDrivenFixProcessorTestMixin {}
+
+mixin DataDrivenFixProcessorTestMixin on AbstractSingleUnitTest {
+  /// Returns the URI used to import the library created by [setPackageContent].
   String get importUri => 'package:p/lib.dart';
 
-  @override
   FixKind get kind => DartFixKind.DATA_DRIVEN;
 
-  /// Add the file containing the data used by the data-driven fix with the
+  /// Adds the file containing the data used by the data-driven fix with the
   /// given [content].
   void addPackageDataFile(String content) {
     newFile(
@@ -33,7 +41,7 @@
     );
   }
 
-  /// Add the file in the SDK containing the data used by the data-driven fix
+  /// Adds the file in the SDK containing the data used by the data-driven fix
   /// with the given [content].
   void addSdkDataFile(String content) {
     newFile(
@@ -42,7 +50,7 @@
     );
   }
 
-  /// Return a code template that will produce the given [text].
+  /// Returns a code template that will produce the given [text].
   CodeTemplate codeTemplate(String text) {
     return CodeTemplate(CodeTemplateKind.expression, [
       TemplateText(text),
@@ -54,7 +62,7 @@
   bool ignoreUnusedImport(Diagnostic diagnostic) =>
       diagnostic.diagnosticCode != WarningCode.UNUSED_IMPORT;
 
-  /// Set the content of the library that defines the element referenced by the
+  /// Sets the content of the library that defines the element referenced by the
   /// data on which this test is based.
   void setPackageContent(String content) {
     newFile('$workspaceRootPath/p/lib/lib.dart', content);
@@ -65,7 +73,7 @@
     );
   }
 
-  /// Set the data on which this test is based.
+  /// Sets the data on which this test is based.
   void setPackageData(Transform transform) {
     DataDriven.transformSetsForTests = [
       TransformSet()..addTransform(transform),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_change_for_kind_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_change_for_kind_test.dart
index 67e58b8..03565b3 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_change_for_kind_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_change_for_kind_test.dart
@@ -24,14 +24,14 @@
   date: 2021-11-30
   element:
     uris: ['test.dart']
-    class: 'C'
+    extension: 'E'
   changes:
     - kind: 'replacedBy'
       newElement:
         uris: ['test.dart']
-        class: 'D'
+        extension: 'F'
 ''',
-      [error(TransformSetErrorCode.invalidChangeForKind, 173, 39)],
+      [error(TransformSetErrorCode.invalidChangeForKind, 177, 43)],
     );
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
index e3a72ae..7174b6f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
@@ -60,10 +60,14 @@
   static List<ElementKind> invocationKinds = [
     ElementKind.classKind,
     ElementKind.constructorKind,
+    ElementKind.enumKind,
     ElementKind.extensionKind,
+    ElementKind.extensionTypeKind,
     ElementKind.functionKind,
     ElementKind.getterKind,
     ElementKind.methodKind,
+    ElementKind.mixinKind,
+    ElementKind.typedefKind,
   ];
 
   /// The kinds that are expected where a method or constructor is allowed.
@@ -76,6 +80,7 @@
   static List<ElementKind> typeKinds = [
     ElementKind.classKind,
     ElementKind.enumKind,
+    ElementKind.extensionTypeKind,
     ElementKind.mixinKind,
     ElementKind.typedefKind,
   ];
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
index 1c66e23..5dea2ef 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
@@ -1177,7 +1177,7 @@
     date: DateTime.now(),
     element: ElementDescriptor(
       libraryUris: [Uri.parse(importUri)],
-      kind: ElementKindUtilities.fromName(_kind)!,
+      kind: ElementKind.fromName(_kind)!,
       isStatic: isStatic,
       components: originalComponents,
     ),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
index 0637843..56d11f4 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
@@ -507,7 +507,7 @@
     date: DateTime.now(),
     element: ElementDescriptor(
       libraryUris: [Uri.parse(importUri)],
-      kind: ElementKindUtilities.fromName(_kind)!,
+      kind: ElementKind.fromName(_kind)!,
       isStatic: isStatic,
       components: components,
     ),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 367cafe..6c10515 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -16,6 +16,7 @@
     defineReflectiveTests(RenameClassTest);
     defineReflectiveTests(RenameConstructorTest);
     defineReflectiveTests(RenameExtensionTest);
+    defineReflectiveTests(RenameExtensionTypeTest);
     defineReflectiveTests(RenameFieldTest);
     defineReflectiveTests(RenameGetterTest);
     defineReflectiveTests(RenameSetterTest);
@@ -759,6 +760,115 @@
 }
 
 @reflectiveTest
+class RenameExtensionTypeTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'extensionType';
+
+  Future<void> test_override_deprecated() async {
+    setPackageContent('''
+@deprecated
+extension type Old(String _) implements String {
+  int get double => length * 2;
+}
+extension type New(String _) implements String {
+  int get double => length * 2;
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestCode('''
+import '$importUri';
+
+var l = Old('a').double;
+''');
+    await assertHasFix('''
+import '$importUri';
+
+var l = New('a').double;
+''');
+  }
+
+  Future<void> test_override_removed() async {
+    setPackageContent('''
+extension type New(String _) implements String {
+  int get double => length * 2;
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestCode('''
+import '$importUri';
+
+var l = Old('a').double;
+''');
+    await assertHasFix('''
+import '$importUri';
+
+var l = New('a').double;
+''');
+  }
+
+  Future<void> test_staticField_deprecated() async {
+    setPackageContent('''
+@deprecated
+extension type Old(String _) implements String {
+  static String empty = '';
+}
+extension type New(String _) implements String {
+  static String empty = '';
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestCode('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+    await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''');
+  }
+
+  Future<void> test_staticField_removed() async {
+    setPackageContent('''
+extension type New(String _) implements String {
+  static String empty = '';
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestCode('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+    await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''');
+  }
+
+  Future<void> test_staticField_removed_prefixed() async {
+    setPackageContent('''
+extension type New(String _) implements String {
+  static String empty = '';
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestCode('''
+import '$importUri' as p;
+
+var s = p.Old.empty;
+''');
+    await assertHasFix('''
+import '$importUri' as p;
+
+var s = p.New.empty;
+''');
+  }
+}
+
+@reflectiveTest
 class RenameFieldTest extends _AbstractRenameTest {
   @override
   String get _kind => 'field';
@@ -1695,7 +1805,7 @@
     date: DateTime.now(),
     element: ElementDescriptor(
       libraryUris: [Uri.parse(importUri)],
-      kind: ElementKindUtilities.fromName(_kind)!,
+      kind: ElementKind.fromName(_kind)!,
       isStatic: isStatic,
       components: components,
     ),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_test.dart
index 51a0735..44378f7 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_test.dart
@@ -20,6 +20,41 @@
 
 @reflectiveTest
 class ReplacedByTest extends DataDrivenFixProcessorTest {
+  Future<void> test_class_class() async {
+    await _assertReplacement(
+      _Element.class_(isDeprecated: true, isOld: true),
+      _Element.class_(),
+    );
+  }
+
+  Future<void> test_class_enum() async {
+    await _assertReplacement(
+      _Element.class_(isDeprecated: true, isOld: true),
+      _Element.enum_(),
+    );
+  }
+
+  Future<void> test_class_extensionType() async {
+    await _assertReplacement(
+      _Element.class_(isDeprecated: true, isOld: true),
+      _Element.extensionType(),
+    );
+  }
+
+  Future<void> test_class_mixin() async {
+    await _assertReplacement(
+      _Element.class_(isDeprecated: true, isOld: true),
+      _Element.mixin(),
+    );
+  }
+
+  Future<void> test_class_typedef() async {
+    await _assertReplacement(
+      _Element.class_(isDeprecated: true, isOld: true),
+      _Element.typedef(aliasedType: 'int'),
+    );
+  }
+
   Future<void> test_defaultConstructor_defaultConstructor() async {
     await _assertReplacement(
       _Element.defaultConstructor(isDeprecated: true, isOld: true),
@@ -63,6 +98,41 @@
     );
   }
 
+  Future<void> test_enum_class() async {
+    await _assertReplacement(
+      _Element.enum_(isDeprecated: true, isOld: true),
+      _Element.class_(),
+    );
+  }
+
+  Future<void> test_enum_enum() async {
+    await _assertReplacement(
+      _Element.enum_(isDeprecated: true, isOld: true),
+      _Element.enum_(),
+    );
+  }
+
+  Future<void> test_enum_extensionType() async {
+    await _assertReplacement(
+      _Element.enum_(isDeprecated: true, isOld: true),
+      _Element.extensionType(),
+    );
+  }
+
+  Future<void> test_enum_mixin() async {
+    await _assertReplacement(
+      _Element.enum_(isDeprecated: true, isOld: true),
+      _Element.mixin(),
+    );
+  }
+
+  Future<void> test_enum_typedef() async {
+    await _assertReplacement(
+      _Element.enum_(isDeprecated: true, isOld: true),
+      _Element.typedef(aliasedType: 'int'),
+    );
+  }
+
   Future<void> test_enumConstant_enumConstant() async {
     await _assertReplacement(
       _Element.constant(isDeprecated: true, isOld: true),
@@ -138,6 +208,41 @@
     );
   }
 
+  Future<void> test_extensionType_class() async {
+    await _assertReplacement(
+      _Element.extensionType(isDeprecated: true, isOld: true),
+      _Element.class_(),
+    );
+  }
+
+  Future<void> test_extensionType_enum() async {
+    await _assertReplacement(
+      _Element.extensionType(isDeprecated: true, isOld: true),
+      _Element.enum_(),
+    );
+  }
+
+  Future<void> test_extensionType_extensionType() async {
+    await _assertReplacement(
+      _Element.extensionType(isDeprecated: true, isOld: true),
+      _Element.extensionType(),
+    );
+  }
+
+  Future<void> test_extensionType_mixin() async {
+    await _assertReplacement(
+      _Element.extensionType(isDeprecated: true, isOld: true),
+      _Element.mixin(),
+    );
+  }
+
+  Future<void> test_extensionType_typedef() async {
+    await _assertReplacement(
+      _Element.extensionType(isDeprecated: true, isOld: true),
+      _Element.typedef(aliasedType: 'int'),
+    );
+  }
+
   Future<void> test_function_function_invocation() async {
     await _assertReplacement(
       _Element.topLevelFunction(isDeprecated: true, isOld: true),
@@ -309,6 +414,41 @@
     await assertNoFix();
   }
 
+  Future<void> test_mixin_class() async {
+    await _assertReplacement(
+      _Element.mixin(isDeprecated: true, isOld: true),
+      _Element.class_(),
+    );
+  }
+
+  Future<void> test_mixin_enum() async {
+    await _assertReplacement(
+      _Element.mixin(isDeprecated: true, isOld: true),
+      _Element.enum_(),
+    );
+  }
+
+  Future<void> test_mixin_extensionType() async {
+    await _assertReplacement(
+      _Element.mixin(isDeprecated: true, isOld: true),
+      _Element.extensionType(),
+    );
+  }
+
+  Future<void> test_mixin_mixin() async {
+    await _assertReplacement(
+      _Element.mixin(isDeprecated: true, isOld: true),
+      _Element.mixin(),
+    );
+  }
+
+  Future<void> test_mixin_typedef() async {
+    await _assertReplacement(
+      _Element.mixin(isDeprecated: true, isOld: true),
+      _Element.typedef(aliasedType: 'int'),
+    );
+  }
+
   Future<void> test_namedConstructor_defaultConstructor() async {
     await _assertReplacement(
       _Element.namedConstructor(isDeprecated: true, isOld: true),
@@ -911,6 +1051,41 @@
     );
   }
 
+  Future<void> test_typedef_class() async {
+    await _assertReplacement(
+      _Element.typedef(isDeprecated: true, isOld: true, aliasedType: 'int'),
+      _Element.class_(),
+    );
+  }
+
+  Future<void> test_typedef_enum() async {
+    await _assertReplacement(
+      _Element.typedef(isDeprecated: true, isOld: true, aliasedType: 'int'),
+      _Element.enum_(),
+    );
+  }
+
+  Future<void> test_typedef_extensionType() async {
+    await _assertReplacement(
+      _Element.typedef(isDeprecated: true, isOld: true, aliasedType: 'int'),
+      _Element.extensionType(),
+    );
+  }
+
+  Future<void> test_typedef_mixin() async {
+    await _assertReplacement(
+      _Element.typedef(isDeprecated: true, isOld: true, aliasedType: 'int'),
+      _Element.mixin(),
+    );
+  }
+
+  Future<void> test_typedef_typedef() async {
+    await _assertReplacement(
+      _Element.typedef(isDeprecated: true, isOld: true, aliasedType: 'int'),
+      _Element.typedef(aliasedType: 'int'),
+    );
+  }
+
   Future<void> _assertReplacement(
     _Element oldElement,
     _Element newElement, {
@@ -1083,6 +1258,48 @@
 ''');
   }
 
+  Future<void> test_new_element_uris_prefixed() async {
+    setPackageContent('''
+@deprecated
+void expect(Object? v1, Object? v2) {}
+''');
+    newFile('$workspaceRootPath/p/lib/lib2.dart', '''
+void expect(Object? v1, Object? v2) {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+  - title: 'Replace expect'
+    date: 2022-05-12
+    bulkApply: false
+    element:
+      uris: ['$importUri']
+      function: 'expect'
+    changes:
+      - kind: 'replacedBy'
+        newElement:
+          uris: ['package:p/lib2.dart']
+          function: 'expect'
+''');
+
+    /// Uses the unprefixed name from the new unprefixed import.
+    await resolveTestCode('''
+import '$importUri' as prefix;
+
+main() {
+  prefix.expect(true, true);
+}
+''');
+    await assertHasFix('''
+import '$importUri' as prefix;
+import 'package:p/lib2.dart';
+
+main() {
+  expect(true, true);
+}
+''');
+  }
+
   Future<void> test_new_element_uris_single() async {
     setPackageContent('');
     addPackageDataFile('''
@@ -1116,6 +1333,48 @@
 }
 ''');
   }
+
+  Future<void> test_new_element_uris_to_prefixed() async {
+    setPackageContent('''
+@deprecated
+void expect(Object? v1, Object? v2) {}
+''');
+    newFile('$workspaceRootPath/p/lib/lib2.dart', '''
+void expect(Object? v1, Object? v2) {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+  - title: 'Replace expect'
+    date: 2022-05-12
+    bulkApply: false
+    element:
+      uris: ['$importUri']
+      function: 'expect'
+    changes:
+      - kind: 'replacedBy'
+        newElement:
+          uris: ['package:p/lib2.dart']
+          function: 'expect'
+''');
+    // Use the prefix of the existing prefixed import.
+    await resolveTestCode('''
+import '$importUri';
+import 'package:p/lib2.dart' as prefix; // ignore: unused_import
+
+main() {
+  expect(true, true);
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+import 'package:p/lib2.dart' as prefix; // ignore: unused_import
+
+main() {
+  prefix.expect(true, true);
+}
+''');
+  }
 }
 
 class _Element {
@@ -1125,7 +1384,6 @@
 
   _Element(this.kind, this.components, this.declaration);
 
-  // ignore: unused_element
   factory _Element.class_({bool isDeprecated = false, bool isOld = false}) {
     var name = isOld ? 'C_old' : 'C_new';
     var annotation = _annotation(isDeprecated: isDeprecated, isTopLevel: true);
@@ -1167,7 +1425,6 @@
     );
   }
 
-  // ignore: unused_element
   factory _Element.enum_({bool isDeprecated = false, bool isOld = false}) {
     var enumName = isOld ? 'E_old' : 'E_new';
     var constantName = isOld ? 'c_old' : 'c_new';
@@ -1180,6 +1437,28 @@
     );
   }
 
+  factory _Element.extensionType({
+    bool isDeprecated = false,
+    bool isOld = false,
+    String representationType = 'int',
+    String representationVariable = '_',
+    String? constructorName,
+    bool isConst = false,
+  }) {
+    var name = isOld ? 'X_old' : 'X_new';
+    var annotation = _annotation(isDeprecated: isDeprecated, isTopLevel: true);
+    var constructorPart =
+        '${constructorName == null ? '' : '.$constructorName'}'
+        '($representationType $representationVariable)';
+    var constPrefix = isConst ? 'const ' : '';
+    return _Element(
+      ElementKind.extensionTypeKind,
+      [name],
+      '''
+${annotation}extension type $constPrefix$name$constructorPart {}''',
+    );
+  }
+
   factory _Element.field({
     bool isDeprecated = false,
     bool isOld = false,
@@ -1237,6 +1516,17 @@
     );
   }
 
+  factory _Element.mixin({bool isDeprecated = false, bool isOld = false}) {
+    var name = isOld ? 'M_old' : 'M_new';
+    var annotation = _annotation(isDeprecated: isDeprecated, isTopLevel: true);
+    return _Element(
+      ElementKind.mixinKind,
+      [name],
+      '''
+${annotation}mixin $name {}''',
+    );
+  }
+
   factory _Element.namedConstructor({
     bool isDeprecated = false,
     bool isOld = false,
@@ -1329,15 +1619,18 @@
     );
   }
 
-  // ignore: unused_element
-  factory _Element.typedef({bool isDeprecated = false, bool isOld = false}) {
+  factory _Element.typedef({
+    bool isDeprecated = false,
+    bool isOld = false,
+    String aliasedType = 'int Function()',
+  }) {
     var name = isOld ? 'T_old' : 'T_new';
     var annotation = _annotation(isDeprecated: isDeprecated);
     return _Element(
       ElementKind.typedefKind,
       [name],
       '''
-${annotation}typedef $name = int Function();''',
+${annotation}typedef $name = $aliasedType;''',
     );
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_type_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_type_test.dart
new file mode 100644
index 0000000..9d9e206
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/replaced_by_type_test.dart
@@ -0,0 +1,543 @@
+// Copyright (c) 2025, 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.
+
+@Timeout.none
+library;
+
+import 'dart:io';
+
+import 'package:test/test.dart' show Timeout;
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'data_driven_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplacedByTypeTest);
+  });
+}
+
+const String fixFileHeader = '''
+version: 1
+transforms:
+''';
+
+@reflectiveTest
+class ReplacedByTypeTest extends DataDrivenBulkFixProcessorTest {
+  /// Data shared by all tests, computed once.
+  static (
+    String lib1,
+    String lib2,
+    String fixData,
+    String fixTemplate,
+    Map<String, String> newNameOf,
+  )?
+  sharedData;
+
+  static final _templateEntryRE = RegExp(r'%(\w+)%');
+
+  Future<void> test_no_prefix_no_import() async {
+    await _assertTemplatedFixes('', null);
+  }
+
+  Future<void> test_no_prefix_no_prefix() async {
+    await _assertTemplatedFixes('', '');
+  }
+
+  Future<void> test_no_prefix_prefix() async {
+    await _assertTemplatedFixes('', 'q');
+  }
+
+  Future<void> test_prefix_no_import() async {
+    await _assertTemplatedFixes('p', null);
+  }
+
+  Future<void> test_prefix_no_prefix() async {
+    await _assertTemplatedFixes('p', '');
+  }
+
+  Future<void> test_prefix_other_prefix() async {
+    await _assertTemplatedFixes('p', 'q');
+  }
+
+  Future<void> test_prefix_same_prefix() async {
+    await _assertTemplatedFixes('p', 'p');
+  }
+
+  void writeFix(
+    StringBuffer buffer,
+    TypeKind oldKind,
+    TypeKind newKind,
+    String oldName,
+    String newName,
+    bool otherLibrary,
+  ) {
+    if (buffer.isEmpty) buffer.write(fixFileHeader);
+    var lib1Uri = importUri;
+    const lib2Uri = 'package:p/lib2.dart';
+    buffer.write('''
+  - title: 'Replace with different type - ${oldKind.name}-${newKind.name} - $newName'
+    date: 2022-09-28
+    element:
+      uris: ['$lib1Uri']
+      ${oldKind.name}: '$oldName'
+    changes:
+      - kind: 'replacedBy'
+        newElement:
+          uris: ['${otherLibrary ? lib2Uri : lib1Uri}']
+          ${newKind.name}: '$newName'
+''');
+  }
+
+  void writeTemplatesFor(
+    StringBuffer buffer,
+    TypeKind oldKind,
+    TypeKind newKind,
+    String oldName,
+    bool generic,
+    bool removed,
+  ) {
+    /// There is a number of cases where a removed type is not recognized
+    /// by the fix. Only correct for unprefixed names.
+    const typeParams = '<T>';
+    const typeArguments = '<int>';
+    for (var nullable in [false, true]) {
+      var isNull = nullable('Nullable');
+      var q = nullable('?');
+      var type = '%$oldName%${generic(typeArguments)}$q';
+      buffer.write('''
+// Global variable type${nullable(', nullable')}.
+$type value$oldName$isNull = 0 as dynamic;
+
+// Parameter type${nullable(', nullable')}.
+void func$oldName$isNull($type input) {
+  // Local variable type${nullable(', nullable')}.
+  $type value = input as dynamic;
+  print(value);
+}
+
+/// Type argument${nullable(', nullable')}.
+List<$type> list$oldName$isNull = [];
+
+/// Type bound${nullable(', nullable')}.
+class GenericClass$oldName$isNull<T extends $type> {}
+
+/// Cast${nullable(', nullable')}.
+Object? exprCast$oldName$isNull = 0 as $type;
+
+${removed ? '' : '''
+/// Type check${nullable(', nullable')}.
+bool exprCheck$oldName$isNull = 0 is $type;
+'''}
+bool casePatternCast$oldName$isNull(Object o) {
+  switch (o) {
+    // Case cast${nullable(', nullable')}.
+    case _ as $type: return false;
+  }
+}
+bool casePatternVar$oldName$isNull(Object? o) {
+  switch (o) {
+    // Case variable pattern${nullable(', nullable')}.
+    case $type _: return false;
+    case _: return true;
+  }
+}
+
+void declPatterCast$oldName$isNull(Object? o) {
+  // Declaration pattern cast${nullable(', nullable')}.
+  var (value as $type,) = o as dynamic;
+  print(value);
+}
+
+void declPatternVar$oldName$isNull(Object? o) {
+  // Declaration pattern type annotation${nullable(', nullable')}.
+  var ($type value,) = 0 as dynamic;
+  print(value);
+}
+${(oldKind.canBeExtensionOnType && newKind.canBeExtensionOnType)('''
+// Extension on-type${nullable(', nullable')}.
+extension Ext$oldName$isNull${generic(typeParams)} on $type {}
+''')}
+// Extension type representation type${nullable(', nullable')}.
+extension type ExtType$oldName$isNull($type _) {}
+
+''');
+    }
+    // Uses where the reference cannot be explicitly nullable (not used as type,
+    // or must be non-nullable.)
+
+    var type = '%$oldName%${generic(typeArguments)}';
+    buffer.write('''
+${removed ? '' : '''
+void tryOn$oldName(Object o) {
+  try {
+    throw o;
+  } on $type {}
+}
+'''}
+// As type literal.
+Type typeLiteral$oldName = $type;
+// As const type literal.
+const Type constTypeLiteral$oldName = $type;
+
+bool caseConst$oldName(Object o) {
+  switch (o) {
+    case const ($type): return false;
+    case _: return true;
+  }
+}
+
+bool caseObjectPattern$oldName(Object o) {
+  // Object pattern check.
+  switch (o) {
+    case $type(): return false;
+    case _: return true;
+  }
+}
+
+void declObjectPattern$oldName(Object? o) {
+  var ($type(runtimeType: value),) = 0 as dynamic;
+  print(value);
+}
+${(oldKind.canBeClassSuper && newKind.canBeClassSuper)('''
+class ClassExtends$oldName extends $type {}
+''')}
+${(oldKind.canBeClassMixin && newKind.canBeClassMixin)('''
+class ClassWith$oldName with $type {}
+enum EnumWith$oldName with $type { e }
+''')}
+${(oldKind.canBeClassInterface && newKind.canBeClassInterface)('''
+abstract class ClassImplements$oldName implements $type {}
+enum EnumImplements$oldName implements $type { e }
+mixin MixinImplements$oldName implements $type {}
+''')}
+${(oldKind.canBeExtensionTypeInterface && newKind.canBeExtensionTypeInterface && !removed)('''
+extension type ExtensionTypeImplements$oldName($type _) implements $type {}
+''')}
+${(oldKind.canBeMixinOnType && newKind.canBeMixinOnType)('''
+mixin MixinOn$oldName on $type {}
+''')}
+''');
+    // Static/constructor Member access
+    buffer.writeln('var staticAccess$oldName = <Object?>[');
+    // Constructors, for anything but mixins.
+    if (oldKind.hasConstructors && newKind.hasConstructors) {
+      for (var name in ['', '.new', '.named']) {
+        for (var op in ['', 'new ', 'const ']) {
+          if (!removed || op == '' && name == '') {
+            buffer.writeln('  $op$type$name(),');
+          }
+        }
+        if (name.isNotEmpty) {
+          buffer.writeln('  $type$name, // Tearoff');
+        }
+      }
+    }
+
+    // Static member access, no generics.
+    // Same code for generic and non-generic types, so only do it for one.
+    if (!generic) {
+      type = '%$oldName%';
+      buffer.write('''
+    $type.constValue, // static constant
+    $type.value, // Static getter
+    $type.method(), // Static method
+    $type.method, // Static method tear-off,
+  ];
+
+  void staticSetter$oldName(dynamic value) {
+    $type.value = value;
+  }
+  ''');
+    } else {
+      buffer.write('  ];\n');
+    }
+  }
+
+  void writeTypeDeclaration(
+    StringBuffer buffer,
+    TypeKind kind,
+    String name, {
+    bool deprecated = false,
+    bool generic = false,
+  }) {
+    const typeParameters = '<T>';
+    const typeArguments = '<int>';
+    if (deprecated) buffer.writeln('@deprecated');
+    switch (kind) {
+      // Type aliases have a helper class that they alias.
+      case TypeKind.typedefKind:
+        buffer.write('''
+typedef $name${generic(typeParameters)} = _T$name${generic(typeParameters)};
+''');
+        writeTypeDeclaration(
+          buffer,
+          TypeKind.classKind,
+          '_T$name',
+          deprecated: deprecated,
+          generic: generic,
+        );
+      case TypeKind.classKind:
+        buffer.write('''
+mixin class $name${generic(typeParameters)} {
+  static const Object? constValue = $name${generic('<Never>')}();
+  static int value = 0;
+  static int method() => 0;
+  const $name();
+  const $name.named();
+}
+''');
+      // Enums use a helper extension type to implement factory constructors.
+      case TypeKind.enumKind:
+        buffer.write('''
+enum $name${generic(typeParameters)} {
+  constValue${generic(typeArguments)}._();
+  const $name._();
+  static int value = 0;
+  static int method() => 0;
+  const factory $name() = _${name}Helper${generic(typeParameters)};
+  const factory $name.named() = _${name}Helper${generic(typeParameters)};
+}${deprecated('\n@deprecated')}
+extension type const _${name}Helper${generic(typeParameters)}._($name${generic(typeParameters)} _)
+    implements $name${generic(typeParameters)} {
+  const _${name}Helper() : this._($name.constValue as dynamic);
+}
+''');
+      case TypeKind.mixinKind:
+        buffer.write('''
+mixin $name${generic(typeParameters)} {
+  static const Object? constValue = 0;
+  static int value = 0;
+  static int method() => 0;
+}
+''');
+      case TypeKind.extensionTypeKind:
+        buffer.write('''
+extension type const $name${generic(typeParameters)}._(int _) implements Object {
+  static const Object? constValue = 0;
+  static int value = 0;
+  static int method() => 0;
+  const $name() : this._(0);
+  const $name.named() : this._(0);
+}
+''');
+    }
+  }
+
+  Future<void> _assertExpectedFixes(String source, String expected) async {
+    var (lib1, lib2, fixData, _, _) = (sharedData ??= _generateFiles());
+    setPackageContent(lib1);
+    newFile('$workspaceRootPath/p/lib/lib2.dart', lib2);
+    addPackageDataFile(fixData);
+    await resolveTestCode(source);
+    await assertHasFix(expected);
+  }
+
+  /// Checks that code in the template gets fixed.
+  ///
+  /// If [lib1Prefix] is non-empty, `lib1` is imported with that prefix.
+  /// If it's empty, `lib1` is imported with no prefix.
+  ///
+  /// If [lib2Prefix] is `null`, `lib2` is not pre-imported.
+  /// If non-`null`, it's imported with no prefix if empty,
+  /// or that prefix if not.
+  Future<void> _assertTemplatedFixes(
+    String lib1Prefix,
+    String? lib2Prefix,
+  ) async {
+    var (_, _, _, template, newNameOf) = (sharedData ??= _generateFiles());
+    var lib1Import =
+        '''import '$importUri'${lib1Prefix.isNotEmpty(' as $lib1Prefix')};\n''';
+    var lib1PrefixDot = lib1Prefix.isEmpty ? '' : '$lib1Prefix.';
+    // Lib2 import in post-fix library.
+    var lib2Import =
+        '''import 'package:p/lib2.dart'${(lib2Prefix != null && lib2Prefix.isNotEmpty)(' as $lib2Prefix')};\n''';
+    var lib2PrefixDot = '';
+    var lib2Usage = '';
+    var lib2OldImport = ''; // Import in pre-fix library.
+    if (lib2Prefix != null) {
+      // Lib2 was imported in original.
+      if (lib2Prefix.isNotEmpty) lib2PrefixDot = '$lib2Prefix.';
+      lib2OldImport = lib2Import;
+      // Inserted to avoid a pre-imported lib 2 being unused.
+      lib2Usage = '${lib2PrefixDot}Lib2Use? dummyDeclaration;\n';
+    }
+
+    var source =
+        '$lib1Import$lib2OldImport$lib2Usage${_replaceInTemplate(template, lib1PrefixDot, lib2PrefixDot, null)}';
+    var expected =
+        '$lib1Import$lib2Import$lib2Usage${_replaceInTemplate(template, lib1PrefixDot, lib2PrefixDot, newNameOf)}';
+
+    File(
+      'gen_old_$lib1Prefix${lib2Prefix ?? 'n'}.dart',
+    ).writeAsStringSync(source.toString().replaceAll('package:p/', 'gen_'));
+    File(
+      'gen_new_$lib1Prefix${lib2Prefix ?? 'n'}.dart',
+    ).writeAsStringSync(expected.toString().replaceAll('package:p/', 'gen_'));
+
+    await _assertExpectedFixes(source, expected);
+  }
+
+  /// Creates the types referenced by the files to be fixed,
+  /// and a template for all the occurrences of those types.
+  ///
+  /// * `lib1`: The primary library containing all the deprecated classes,
+  ///   and some of the classes they should be replaced by.
+  /// * `lib2`: Secondary library for replacing a deprecated type with
+  ///   a type in another library.
+  /// * `fixTemplate` is a template containing `%oldName%` where a type
+  ///   to replace should go. Inserting a deprecated type and fixing
+  ///   should give the corresponding name from `newNameOf`.
+  /// * `fixData` the data-driven fixes mapping all deprecated types in `lib1`
+  ///   to new types in `lib1` or `lib2`.
+  /// * Mapping from deprecated type names to their replacement type name.
+  (
+    String lib1,
+    String lib2,
+    String fixData,
+    String fixTemplate,
+    Map<String, String> newNameOf,
+  )
+  _generateFiles() {
+    var lib1Buffer = StringBuffer();
+    var lib2Buffer = StringBuffer('''
+class Lib2Use {} // Can be referred to avoid unused import warnings.
+''');
+    var fixDataBuffer = StringBuffer();
+
+    // Contains code templates for code to fix.
+    // A character sequence of `%ABCDE%` represents an occurrence of the old
+    // type `ABCDE`. It will be replaced in both before source (to add prefixes
+    // in some cases), and in output to insert the expected replacement.
+    var templateBuffer = StringBuffer();
+
+    /// Mapping from old deprecated name to new replacement name.
+    var newNameOf = <String, String>{};
+
+    // Go through all the combinations of kinds of type declarations, and
+    // whether the replacement is in the same or another library.
+    for (var newKind in TypeKind.values) {
+      for (var otherLibrary in [false, true]) {
+        for (var generic in [false, true]) {
+          var newName = '${generic('G')}${otherLibrary('O')}$newKind';
+          writeTypeDeclaration(
+            otherLibrary ? lib2Buffer : lib1Buffer,
+            newKind,
+            newName,
+            generic: generic,
+          );
+          for (var oldKind in TypeKind.values) {
+            for (var removed in [false /*true*/]) {
+              // Should also work when original type declaration is removed
+              // Does not yet, not in all cases.
+              var oldName = '${removed ? 'R' : 'D'}$oldKind$newName';
+              assert(!newNameOf.containsKey(oldName));
+              if (!removed) {
+                writeTypeDeclaration(
+                  lib1Buffer,
+                  oldKind,
+                  oldName,
+                  deprecated: true,
+                  generic: generic,
+                );
+              }
+              writeFix(
+                fixDataBuffer,
+                oldKind,
+                newKind,
+                oldName,
+                newName,
+                otherLibrary,
+              );
+              newNameOf[oldName] = newName;
+
+              writeTemplatesFor(
+                templateBuffer,
+                oldKind,
+                newKind,
+                oldName,
+                generic,
+                removed,
+              );
+            }
+          }
+        }
+      }
+    }
+    File('gen_lib.dart').writeAsStringSync(lib1Buffer.toString());
+    File('gen_lib2.dart').writeAsStringSync(lib2Buffer.toString());
+    File('gen_fix_data.yaml').writeAsStringSync(fixDataBuffer.toString());
+    return (
+      lib1Buffer.toString(),
+      lib2Buffer.toString(),
+      fixDataBuffer.toString(),
+      templateBuffer.toString(),
+      newNameOf,
+    );
+  }
+
+  /// Replaces `%oldName%` with either` `(prefix.)?oldName`
+  /// or `(prefix.)?newName`.
+  static String _replaceInTemplate(
+    String template,
+    String lib1PrefixDot,
+    String lib2PrefixDot,
+    Map<String, String>? newNameOf,
+  ) {
+    if (newNameOf == null) {
+      // Old name, just prefix with prefix-dot if needed.
+      return template.replaceAllMapped(
+        _templateEntryRE,
+        (m) => '$lib1PrefixDot${m[1]}',
+      );
+    }
+    var cache = <String, String>{};
+    return template.replaceAllMapped(_templateEntryRE, (m) {
+      var oldName = m[1]!;
+
+      String? newName = cache[oldName];
+      if (newName != null) return newName;
+      newName = newNameOf[oldName]!;
+      var prefix = newName.contains('O') ? lib2PrefixDot : lib1PrefixDot;
+      return cache[oldName] = '$prefix$newName';
+    });
+  }
+}
+
+enum TypeKind {
+  classKind('class', 'C'),
+  enumKind('enum', 'E'),
+  extensionTypeKind('extensionType', 'X'),
+  mixinKind('mixin', 'M'),
+  typedefKind('typedef', 'A');
+
+  // String used to represent kind in fix-data and pretty names.
+  final String name;
+  // Single character used to represent the type in constructed names.
+  final String char;
+
+  const TypeKind(this.name, this.char);
+
+  bool get canBeClassInterface =>
+      this == classKind || this == mixinKind || this == typedefKind;
+  // Because class declarations here are all mixin classes.
+  bool get canBeClassMixin =>
+      this == classKind || this == mixinKind || this == typedefKind;
+  bool get canBeClassSuper => this == classKind || this == typedefKind;
+  bool get canBeExtensionOnType => true;
+  bool get canBeExtensionTypeInterface =>
+      canBeClassInterface || this == extensionTypeKind;
+  bool get canBeMixinOnType =>
+      this == classKind || this == mixinKind || this == typedefKind;
+  // Mixin declarations can't declare constructors, not even factory ones. Yet.
+  bool get hasConstructors => this != mixinKind;
+
+  @override
+  String toString() => char;
+}
+
+extension on bool {
+  /// Choose a string based on the boolean value.
+  String call(String ifTrue, [String ifFalse = '']) => this ? ifTrue : ifFalse;
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
index 4ee3821..fe6201b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
@@ -18,6 +18,7 @@
 import 'rename_parameter_test.dart' as rename_parameter;
 import 'rename_test.dart' as rename;
 import 'replaced_by_test.dart' as replaced_by;
+import 'replaced_by_type_test.dart' as replaced_by_type;
 import 'sdk_fix_test.dart' as sdk_fix;
 import 'test_use_case_test.dart' as test_use_case;
 import 'transform_set_manager_test.dart' as transform_set_manager;
@@ -39,6 +40,7 @@
     rename_parameter.main();
     rename.main();
     replaced_by.main();
+    replaced_by_type.main();
     sdk_fix.main();
     test_use_case.main();
     transform_set_manager.main();
diff --git a/pkg/analysis_server_plugin/lib/src/correction/fix_processor.dart b/pkg/analysis_server_plugin/lib/src/correction/fix_processor.dart
index 762c4de..9fe82b6 100644
--- a/pkg/analysis_server_plugin/lib/src/correction/fix_processor.dart
+++ b/pkg/analysis_server_plugin/lib/src/correction/fix_processor.dart
@@ -47,7 +47,7 @@
   /// If passing [alreadyCalculated] for calculations where we know the output
   /// will be the same, a result will only be calculated if one hasn't been
   /// calculated already (for a similar situation). If calculating the Set will
-  /// be ammended with this information.
+  /// be amended with this information.
   /// If not passing [alreadyCalculated] the calculation will always be
   /// performed.
   FixProcessor(
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 6077a3a..fafb150 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -16464,7 +16464,7 @@
   /// there's no target.
   ///
   /// In an ordinary method invocation this is either a period (`.`) or a
-  /// null-aware opertator (`?.`). In a cascade section this is the cascade
+  /// null-aware operator (`?.`). In a cascade section this is the cascade
   /// operator ('..').
   Token? get operator;
 
diff --git a/pubspec.yaml b/pubspec.yaml
index 120d380..6f994c2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -212,6 +212,8 @@
     path: third_party/pkg/leak_tracker/pkgs/memory_usage
   mime:
     path: third_party/pkg/tools/pkgs/mime
+  native_test_helpers:
+    path: third_party/pkg/native/pkgs/native_test_helpers
   native_toolchain_c:
     path: third_party/pkg/native/pkgs/native_toolchain_c
   oauth2:
@@ -272,8 +274,6 @@
     path: third_party/pkg/tools/pkgs/string_scanner
   swift2objc:
     path: third_party/pkg/native/pkgs/swift2objc
-  swiftgen:
-    path: third_party/pkg/native/pkgs/swiftgen
   sync_http:
     path: third_party/pkg/sync_http
   tar:
diff --git a/third_party/pkg/native_toolchain_c.status b/third_party/pkg/native_toolchain_c.status
index ac2c6a2..6cf3328 100644
--- a/third_party/pkg/native_toolchain_c.status
+++ b/third_party/pkg/native_toolchain_c.status
@@ -10,6 +10,7 @@
 test/clinker/treeshake_cross_android_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
 test/clinker/treeshake_cross_ios_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
 test/clinker/treeshake_cross_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
+test/clinker/windows_module_definition_cross_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
 test/native_toolchain/gcc_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
 test/native_toolchain/ndk_test: SkipByDesign # Cross compilation is not tested on the Dart CI.
 
diff --git a/tools/VERSION b/tools/VERSION
index df6c089..6caf1039 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 9
 PATCH 0
-PRERELEASE 327
+PRERELEASE 328
 PRERELEASE_PATCH 0