fix: Fix avoid_renaming_method_parameters to not consider wildcards as renames

Closes https://github.com/dart-lang/sdk/pull/56252

GitOrigin-RevId: 49905dc8100ec3074bde57f1162b36b8a5ec2a6a
Change-Id: I2df68a273258e47e3dad97b649c8975cbdc14edd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375900
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/linter/CHANGELOG.md b/pkg/linter/CHANGELOG.md
index 114d632..94ea5c5 100644
--- a/pkg/linter/CHANGELOG.md
+++ b/pkg/linter/CHANGELOG.md
@@ -22,6 +22,7 @@
       'b';
       '';
   ```
+- update `avoid_renaming_method_parameters` to ignore wildcard renames
 
 # 3.4.0
 
diff --git a/pkg/linter/lib/src/rules/avoid_renaming_method_parameters.dart b/pkg/linter/lib/src/rules/avoid_renaming_method_parameters.dart
index 571abb5..5506fcd 100644
--- a/pkg/linter/lib/src/rules/avoid_renaming_method_parameters.dart
+++ b/pkg/linter/lib/src/rules/avoid_renaming_method_parameters.dart
@@ -4,6 +4,7 @@
 
 import 'dart:math' as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -68,15 +69,20 @@
       NodeLintRegistry registry, LinterContext context) {
     if (!context.isInLibDir) return;
 
-    var visitor = _Visitor(this);
+    var visitor = _Visitor(this, context.libraryElement);
     registry.addMethodDeclaration(this, visitor);
   }
 }
 
 class _Visitor extends SimpleAstVisitor<void> {
+  /// Whether the `wildcard_variables` feature is enabled.
+  final bool _wildCardVariablesEnabled;
+
   final LintRule rule;
 
-  _Visitor(this.rule);
+  _Visitor(this.rule, LibraryElement? library)
+      : _wildCardVariablesEnabled =
+            library?.featureSet.isEnabled(Feature.wildcard_variables) ?? false;
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
@@ -124,9 +130,18 @@
     var count = math.min(parameters.length, parentParameters.length);
     for (var i = 0; i < count; i++) {
       if (parentParameters.length <= i) break;
+
       var paramIdentifier = parameters[i].name;
-      if (paramIdentifier != null &&
-          paramIdentifier.lexeme != parentParameters[i].name) {
+      if (paramIdentifier == null) {
+        continue;
+      }
+
+      var paramLexeme = paramIdentifier.lexeme;
+      if (_wildCardVariablesEnabled && paramLexeme == '_') {
+        continue; // wildcard identifier
+      }
+
+      if (paramLexeme != parentParameters[i].name) {
         rule.reportLintForToken(paramIdentifier,
             arguments: [paramIdentifier.lexeme, parentParameters[i].name]);
       }
diff --git a/pkg/linter/test/rules/avoid_renaming_method_parameters_test.dart b/pkg/linter/test/rules/avoid_renaming_method_parameters_test.dart
index 5ce2fb7..47c0b39 100644
--- a/pkg/linter/test/rules/avoid_renaming_method_parameters_test.dart
+++ b/pkg/linter/test/rules/avoid_renaming_method_parameters_test.dart
@@ -156,6 +156,94 @@
 ''');
   }
 
+  test_wildcard_allowed() async {
+    await assertNoDiagnostics(r'''
+class A {
+  void m(int p) {}
+}
+class B extends A {
+  void m(_) {}
+}
+''');
+  }
+
+  test_wildcard_featureDisabledFails() async {
+    await assertDiagnostics(r'''
+// @dart = 3.4
+// (pre wildcard-variables)
+
+class A {
+  void m(int p) {}
+}
+class B extends A {
+  void m(_) {}
+}
+''', [
+      lint(104, 1),
+    ]);
+  }
+
+  test_wildcard_mixed() async {
+    await assertNoDiagnostics(r'''
+class A {
+  void m(int a, int b, int c) {}
+}
+class B extends A {
+  void m(_, b, _) {}
+}
+''');
+  }
+
+  test_wildcard_mixedFails() async {
+    await assertDiagnostics(r'''
+class A {
+  void m(int a, int b, int c) {}
+}
+class B extends A {
+  void m(_, c, _) {}
+}
+''', [
+      lint(77, 1),
+    ]);
+  }
+
+  test_wildcard_multipleWildcards() async {
+    await assertNoDiagnostics(r'''
+class A {
+  void m(int a, int b) {}
+}
+class B extends A {
+  void m(_, _) {}
+}
+''');
+  }
+
+  test_wildcard_nonWildcardButUnderscoreBefore() async {
+    await assertDiagnostics(r'''
+class A {
+  void m(int a, int b) {}
+}
+class B extends A {
+  void m(_, _b) {}
+}
+''', [
+      lint(70, 2),
+    ]);
+  }
+
+  test_wildcard_nonWildcardButUnderscoresAround() async {
+    await assertDiagnostics(r'''
+class A {
+  void m(int p) {}
+}
+class B extends A {
+  void m(_p_) {}
+}
+''', [
+      lint(60, 3),
+    ]);
+  }
+
   test_zeroParameters() async {
     await assertNoDiagnostics(r'''
 class A {