Version 3.9.0-222.0.dev

Merge 74250e5fd8c39879ef02c8816b93ea37a1671e99 into dev
diff --git a/DEPS b/DEPS
index aa3369b..bfbab4b 100644
--- a/DEPS
+++ b/DEPS
@@ -130,7 +130,7 @@
   # 'tools/rev_sdk_deps.dart' will rev pkg dependencies to their latest; put an
   # EOL comment after a dependency to instead pin at the current revision.
   "ai_rev": "f2b48c6bf688e27f41b0b73ee3ff0164a05da157",
-  "core_rev": "635dfa32c261ba078438b74de397f2207904ca78",
+  "core_rev": "af37fe54c320b0f76f76da01acbbfc0c0118e613",
   "dartdoc_rev": "4ceea6b8240bf1dd9694a170368264e40c67d66b",
   "ecosystem_rev": "64aac3a9c4606950bcf6c8729f01ed8548b9ed87",
   "flute_rev": "e4ea0459a7debae5e9592c85141707b01fac86c9",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_await.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_await.dart
index f23044d..57a7cb0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_await.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_await.dart
@@ -118,7 +118,7 @@
         );
       }
       builder.addSimpleInsertion(
-        offset ?? errorOffset ?? node.offset,
+        offset ?? diagnosticOffset ?? node.offset,
         'await ',
       );
     });
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
index d027595..101de89 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
@@ -216,7 +216,7 @@
 
     // Create fixes only when its the first diagnostic.
     if (propertyDiagnostics.isNotEmpty &&
-        errorOffset != propertyDiagnostics.first.offset) {
+        diagnosticOffset != propertyDiagnostics.first.offset) {
       return;
     }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
index 4529609..f4824d6 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_type_annotation.dart
@@ -62,7 +62,7 @@
       return;
     }
 
-    for (var node in this.node.withParents) {
+    for (var node in this.node.withAncestors) {
       if (node is VariableDeclarationList) {
         await _forVariableDeclaration(builder, node);
         return;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart b/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
index 00c77d8..c1b3afd 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
@@ -37,7 +37,7 @@
   Future<void> compute(ChangeBuilder builder) async {
     // prepare enclosing ExpressionStatement
     ExpressionStatement? expressionStatement;
-    for (var node in this.node.withParents) {
+    for (var node in this.node.withAncestors) {
       if (node is ExpressionStatement) {
         expressionStatement = node;
         break;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_final_field.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_final_field.dart
index b125f80..23cdc9d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_final_field.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_final_field.dart
@@ -27,7 +27,7 @@
   Future<void> compute(ChangeBuilder builder) async {
     // Find the enclosing getter.
     MethodDeclaration? getter;
-    for (var n in node.withParents) {
+    for (var n in node.withAncestors) {
       if (n is MethodDeclaration) {
         getter = n;
         break;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_getter.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_getter.dart
index bf050da..7ba439e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_getter.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_getter.dart
@@ -45,7 +45,7 @@
     if (_type == _Type.implicitThis) {
       fieldDeclaration = node.thisOrAncestorOfType();
     } else {
-      for (var n in node.withParents) {
+      for (var n in node.withAncestors) {
         if (n is FieldDeclaration) {
           fieldDeclaration = n;
           break;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_generic_function_syntax.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_generic_function_syntax.dart
index f26478c..d25c6f1 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_generic_function_syntax.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_generic_function_syntax.dart
@@ -32,7 +32,7 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    for (var node in this.node.withParents) {
+    for (var node in this.node.withAncestors) {
       if (node is FunctionTypeAlias) {
         return _convertFunctionTypeAlias(builder, node);
       } else if (node is FunctionTypedFormalParameter) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
index f1b1a59..8cda353 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
@@ -44,8 +44,8 @@
   Future<void> _preferIfNull(ChangeBuilder builder) async {
     var node = this.node;
     if (node is ConditionalExpression &&
-        node.offset == errorOffset &&
-        node.length == errorLength) {
+        node.offset == diagnosticOffset &&
+        node.length == diagnosticLength) {
       var condition = node.condition as BinaryExpression;
       Expression nullableExpression;
       Expression defaultExpression;
@@ -87,8 +87,8 @@
   Future<void> _useToConvertNullsToBools(ChangeBuilder builder) async {
     var node = this.node;
     if (node is BinaryExpression &&
-        node.offset == errorOffset &&
-        node.length == errorLength &&
+        node.offset == diagnosticOffset &&
+        node.length == diagnosticLength &&
         (node.operator.type == TokenType.EQ_EQ ||
             node.operator.type == TokenType.BANG_EQ)) {
       var left = node.leftOperand;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_const.dart
index ca168ab..f6d966f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_const.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_const.dart
@@ -126,7 +126,7 @@
   }
 
   bool _containsExcluded(AstNode node) {
-    return {for (var e in excluded) ...e.withParents}.contains(node);
+    return {for (var e in excluded) ...e.withAncestors}.contains(node);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_constructor.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_constructor.dart
index 5daa619..31906de 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_constructor.dart
@@ -48,16 +48,13 @@
   }
 
   ConstructorDeclaration? _findConstructor() {
-    var errorOffset = this.errorOffset;
-    if (errorOffset == null) {
-      return null;
-    }
-
-    var invalidNodes = (unit as CompilationUnitImpl).invalidNodes;
-    for (var constructor in invalidNodes) {
-      if (constructor is ConstructorDeclarationImpl) {
-        if (range.node(constructor).contains(errorOffset)) {
-          return constructor;
+    if (diagnosticOffset case var diagnosticOffset?) {
+      var invalidNodes = (unit as CompilationUnitImpl).invalidNodes;
+      for (var constructor in invalidNodes) {
+        if (constructor is ConstructorDeclarationImpl) {
+          if (range.node(constructor).contains(diagnosticOffset)) {
+            return constructor;
+          }
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
index 5acc8e3..084ff40 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
@@ -54,7 +54,7 @@
       );
       return;
     }
-    if (node.offset == errorOffset) {
+    if (node.offset == diagnosticOffset) {
       // The dead code warning starts at the beginning of `node`. Use this node
       // as the starting point for dead code removal, or, if there is a larger
       // AST node that is fully contained in the dead code range, use it as the
@@ -98,7 +98,7 @@
   Future<void> _handleDeadAtEndOfNode(AstNode node) async {
     switch (node) {
       case BinaryExpression(:var leftOperand, :var operator)
-          when operator.offset == errorOffset &&
+          when operator.offset == diagnosticOffset &&
               const [
                 TokenType.AMPERSAND_AMPERSAND,
                 TokenType.BAR_BAR,
@@ -109,12 +109,13 @@
         await _addEdit((builder) {
           builder.addDeletion(range.endEnd(leftOperand, node));
         });
-      case Block(:var rightBracket) when rightBracket.offset == errorOffset:
+      case Block(:var rightBracket)
+          when rightBracket.offset == diagnosticOffset:
         // Dead code starts at the `}` of a block. It's not possible to remove
         // the `}`, but if any dead code follows the block, it may be removed.
         await _removeDeadCodeAfter(partiallyDeadNode: node);
       case DoStatement(:var body, :var whileKeyword)
-          when whileKeyword.offset == errorOffset:
+          when whileKeyword.offset == diagnosticOffset:
         // Dead code starts at the `while` keyword of a `do` loop. This means
         // the body of the loop is partially dead, so the situation is handled
         // by `_removeDeadCodeAfter`.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_type_annotation.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_type_annotation.dart
index b3bb7e8..ed4f207 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_type_annotation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_type_annotation.dart
@@ -41,7 +41,7 @@
       return _varAndType(builder);
     }
 
-    for (var node in this.node.withParents) {
+    for (var node in this.node.withAncestors) {
       if (node is DeclaredIdentifier) {
         return _removeFromDeclaredIdentifier(builder, node);
       }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart
index 00a43ba..a602734 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart
@@ -25,9 +25,11 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    for (var n in node.withParents) {
+    for (var n in node.withAncestors) {
       if (n is! MethodInvocation) continue;
-      if (n.offset != errorOffset && n.length != errorLength) continue;
+      if (n.offset != diagnosticOffset && n.length != diagnosticLength) {
+        continue;
+      }
 
       var target = n.target;
       if (target != null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 8a746d1..b79ea69 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -104,7 +104,7 @@
 /// Returns a class or an unit member enclosing the given [input].
 AstNode? getEnclosingClassOrUnitMember(AstNode input) {
   var member = input;
-  for (var node in input.withParents) {
+  for (var node in input.withAncestors) {
     switch (node) {
       case ClassDeclaration _:
       case CompilationUnit _:
@@ -121,7 +121,7 @@
 
 /// Return the enclosing executable [AstNode].
 AstNode? getEnclosingExecutableNode(AstNode input) {
-  for (var node in input.withParents) {
+  for (var node in input.withAncestors) {
     if (node is FunctionDeclaration) {
       return node;
     }
@@ -253,7 +253,7 @@
 /// Return parent [AstNode]s from compilation unit (at index "0") to the given
 /// [node].
 List<AstNode> getParents(AstNode node) {
-  return node.withParents.toList().reversed.toList();
+  return node.withAncestors.toList().reversed.toList();
 }
 
 /// If given [node] is name of qualified property extraction, returns target
diff --git a/pkg/analysis_server/lib/src/services/refactoring/legacy/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/legacy/extract_method.dart
index fa97407..f8599fa 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/legacy/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/legacy/extract_method.dart
@@ -1376,7 +1376,7 @@
 
   void _checkParent(AstNode node) {
     var firstParent = firstSelectedNode!.parent;
-    for (var parent in node.withParents) {
+    for (var parent in node.withAncestors) {
       if (identical(parent, firstParent)) {
         return;
       }
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
index 33650a5..1a9ee21 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
@@ -76,7 +76,7 @@
 extension AstNodeExtension on AstNode {
   /// Return the [IfStatement] associated with `this`.
   IfStatement? get enclosingIfStatement {
-    for (var node in withParents) {
+    for (var node in withAncestors) {
       if (node is IfStatement) {
         return node;
       } else if (node is! Expression) {
diff --git a/pkg/analysis_server_plugin/api.txt b/pkg/analysis_server_plugin/api.txt
index 9289d45..f7b3c03 100644
--- a/pkg/analysis_server_plugin/api.txt
+++ b/pkg/analysis_server_plugin/api.txt
@@ -56,8 +56,10 @@
     canBeAppliedAcrossSingleFile (getter: bool)
     canBeAppliedAutomatically (getter: bool)
     coveringNode (getter: AstNode?)
-    errorLength (getter: int?)
-    errorOffset (getter: int?)
+    diagnosticLength (getter: int?)
+    diagnosticOffset (getter: int?)
+    errorLength (getter: int?, deprecated)
+    errorOffset (getter: int?, deprecated)
     fixArguments (getter: List<String>?)
     fixKind (getter: FixKind?)
     multiFixArguments (getter: List<String>?)
diff --git a/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart b/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart
index bb5105e..27cd709 100644
--- a/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart
+++ b/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart
@@ -174,13 +174,17 @@
 
   /// The length of the source range associated with the diagnostic being
   /// fixed, or `null` if there is no diagnostic.
-  // TODO(srawlins): Rename to 'diagnosticLength'.
-  int? get errorLength => diagnostic?.problemMessage.length;
+  int? get diagnosticLength => diagnostic?.problemMessage.length;
 
   /// The offset of the source range associated with the diagnostic being
   /// fixed, or `null` if there is no diagnostic.
-  // TODO(srawlins): Rename to 'diagnosticOffset'.
-  int? get errorOffset => diagnostic?.problemMessage.offset;
+  int? get diagnosticOffset => diagnostic?.problemMessage.offset;
+
+  @Deprecated("Use 'diagnosticLength' instead")
+  int? get errorLength => diagnosticLength;
+
+  @Deprecated("Use 'diagnosticOffset' instead")
+  int? get errorOffset => diagnosticOffset;
 
   /// The arguments that should be used when composing the message for a fix, or
   /// `null` if the fix message has no parameters or if this producer doesn't
diff --git a/pkg/analyzer/lib/src/utilities/extensions/ast.dart b/pkg/analyzer/lib/src/utilities/extensions/ast.dart
index b5e1f16..4cfde99 100644
--- a/pkg/analyzer/lib/src/utilities/extensions/ast.dart
+++ b/pkg/analyzer/lib/src/utilities/extensions/ast.dart
@@ -31,7 +31,7 @@
   /// The [FunctionExpression] that encloses this node directly or `null` if
   /// there is another enclosing executable element.
   FunctionExpression? get enclosingClosure {
-    for (var node in withParents) {
+    for (var node in withAncestors) {
       switch (node) {
         case FunctionExpression(:var parent)
             when parent is! FunctionDeclaration:
@@ -47,7 +47,7 @@
 
   /// The [ExecutableElement] of the enclosing executable [AstNode].
   ExecutableElement? get enclosingExecutableElement {
-    for (var node in withParents) {
+    for (var node in withAncestors) {
       if (node is FunctionDeclaration) {
         return node.declaredFragment?.element;
       }
@@ -63,7 +63,7 @@
 
   /// The [InstanceElement] of the enclosing executable [AstNode].
   InstanceElement? get enclosingInstanceElement {
-    for (var node in withParents) {
+    for (var node in withAncestors) {
       var element = switch (node) {
         ClassDeclaration(:var declaredFragment?) => declaredFragment.element,
         EnumDeclaration(:var declaredFragment?) => declaredFragment.element,
@@ -85,7 +85,7 @@
       enclosingInstanceElement.ifTypeOrNull();
 
   AstNode? get enclosingUnitChild {
-    for (var node in withParents) {
+    for (var node in withAncestors) {
       if (node.parent is CompilationUnit) {
         return node;
       }
@@ -93,16 +93,12 @@
     return null;
   }
 
-  /// This node and all its parents.
-  Iterable<AstNode> get withParents sync* {
-    var current = this;
-    while (true) {
+  /// This node and all of its ancestors.
+  Iterable<AstNode> get withAncestors sync* {
+    AstNode? current = this;
+    while (current != null) {
       yield current;
-      var parent = current.parent;
-      if (parent == null) {
-        break;
-      }
-      current = parent;
+      current = current.parent;
     }
   }
 
diff --git a/pkg/linter/lib/src/util/obvious_types.dart b/pkg/linter/lib/src/util/obvious_types.dart
index b659055..1d3efb2 100644
--- a/pkg/linter/lib/src/util/obvious_types.dart
+++ b/pkg/linter/lib/src/util/obvious_types.dart
@@ -164,8 +164,13 @@
       case SimpleIdentifier():
         if (self.isQualified) return false;
         var declaration = self.element;
-        if (declaration is! LocalVariableElement) return false;
-        return self.staticType == declaration.type;
+        if (declaration is LocalVariableElement) {
+          return self.staticType == declaration.type;
+        }
+        if (declaration is FormalParameterElement) {
+          return self.staticType == declaration.type;
+        }
+        return false;
       case InstanceCreationExpression():
         var createdType = self.constructorName.type;
         if (createdType.typeArguments != null) {
diff --git a/pkg/linter/test/rules/omit_obvious_local_variable_types_test.dart b/pkg/linter/test/rules/omit_obvious_local_variable_types_test.dart
index 6b80a66..d931632 100644
--- a/pkg/linter/test/rules/omit_obvious_local_variable_types_test.dart
+++ b/pkg/linter/test/rules/omit_obvious_local_variable_types_test.dart
@@ -344,6 +344,30 @@
 ''');
   }
 
+  test_parameter() async {
+    await assertDiagnostics(
+      r'''
+void f(int parameter) {
+  int i = parameter;
+}
+''',
+      [lint(26, 3)],
+    );
+  }
+
+  test_parameter_of_literal() async {
+    await assertDiagnostics(
+      r'''
+Function f() {
+  return (int parameter) {
+    int i = parameter;
+  };
+}
+''',
+      [lint(46, 3)],
+    );
+  }
+
   /// Types are considered an important part of the pattern so we
   /// intentionally do not lint on declared variable patterns.
   test_pattern_list_destructured() async {
diff --git a/tools/VERSION b/tools/VERSION
index e62cfdc..84e9cc1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 9
 PATCH 0
-PRERELEASE 221
+PRERELEASE 222
 PRERELEASE_PATCH 0