Add a quick fix for convert_to_super_parameters

Change-Id: Ied50bcd6af6e0cf4871c8810c5b8466fa268bd86
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237460
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
index 7f84f01..4fe011b 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_super_parameters.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/utilities/extensions/range_factory.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -11,6 +12,7 @@
 import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 
 class ConvertToSuperParameters extends CorrectionProducer {
@@ -18,6 +20,18 @@
   AssistKind get assistKind => DartAssistKind.CONVERT_TO_SUPER_PARAMETERS;
 
   @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.CONVERT_TO_SUPER_PARAMETERS;
+
+  @override
+  FixKind? get multiFixKind => DartFixKind.CONVERT_TO_SUPER_PARAMETERS_MULTI;
+
+  @override
   Future<void> compute(ChangeBuilder builder) async {
     if (!libraryElement.featureSet.isEnabled(Feature.super_parameters)) {
       // If the library doesn't support super_parameters then the change isn't
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index ba2c26d..c3c7bc1 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1843,7 +1843,7 @@
 LintCode.use_string_buffers:
   status: needsEvaluation
 LintCode.use_super_parameters:
-  status: needsFix
+  status: hasFix
 LintCode.use_test_throws_matchers:
   status: needsEvaluation
 LintCode.use_to_and_as_if_applicable:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index d5879e9..f55d3ca 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -568,6 +568,16 @@
     DartFixKindPriority.IN_FILE,
     'Convert to spreads everywhere in file',
   );
+  static const CONVERT_TO_SUPER_PARAMETERS = FixKind(
+    'dart.fix.convert.toSuperParameters',
+    30,
+    'Convert to using super parameters',
+  );
+  static const CONVERT_TO_SUPER_PARAMETERS_MULTI = FixKind(
+    'dart.fix.convert.toSuperParameters.multi',
+    30,
+    'Convert to using super parameters everywhere in file',
+  );
   static const CONVERT_TO_WHERE_TYPE = FixKind(
     'dart.fix.convert.toWhereType',
     DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 50e70815..10fc9e5 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -65,6 +65,7 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_raw_string.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_super_parameters.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
 import 'package:analysis_server/src/services/correction/dart/create_class.dart';
 import 'package:analysis_server/src/services/correction/dart/create_constructor.dart';
@@ -674,6 +675,9 @@
     LintNames.use_rethrow_when_possible: [
       UseRethrow.newInstance,
     ],
+    LintNames.use_super_parameters: [
+      ConvertToSuperParameters.newInstance,
+    ],
   };
 
   /// A map from error codes to a list of generators used to create multiple
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 108dde5..60448e7 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -158,4 +158,5 @@
       'use_key_in_widget_constructors';
   static const String use_raw_strings = 'use_raw_strings';
   static const String use_rethrow_when_possible = 'use_rethrow_when_possible';
+  static const String use_super_parameters = 'use_super_parameters';
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart
new file mode 100644
index 0000000..b8517d5
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_super_parameters_test.dart
@@ -0,0 +1,492 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToSuperParametersBulkTest);
+    defineReflectiveTests(ConvertToSuperParametersTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToSuperParametersBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.use_super_parameters;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+class A {
+  A.m({int? x});
+  A.n(int x);
+}
+class B extends A {
+  B.m({int? x}) : super.m(x: x);
+  B.n(int x) : super.n(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A.m({int? x});
+  A.n(int x);
+}
+class B extends A {
+  B.m({super.x}) : super.m();
+  B.n(super.x) : super.n();
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ConvertToSuperParametersTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.CONVERT_TO_SUPER_PARAMETERS;
+
+  @override
+  String get lintCode => LintNames.use_super_parameters;
+
+  Future<void> test_defaultValue_different_named() async {
+    await resolveTestCode('''
+class A {
+  A({int x = 0});
+}
+class B extends A {
+  B({int x = 2}) : super(x: x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int x = 0});
+}
+class B extends A {
+  B({super.x = 2});
+}
+''');
+  }
+
+  Future<void> test_defaultValue_different_positional() async {
+    await resolveTestCode('''
+class A {
+  A([int x = 0]);
+}
+class B extends A {
+  B([int x = 2]) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A([int x = 0]);
+}
+class B extends A {
+  B([super.x = 2]);
+}
+''');
+  }
+
+  Future<void> test_defaultValue_equal_named() async {
+    await resolveTestCode('''
+class A {
+  A({int x = 0});
+}
+class B extends A {
+  B({int x = 0}) : super(x: x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int x = 0});
+}
+class B extends A {
+  B({super.x});
+}
+''');
+  }
+
+  Future<void> test_defaultValue_equal_positional() async {
+    await resolveTestCode('''
+class A {
+  A([int x = 0]);
+}
+class B extends A {
+  B([int x = 0]) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A([int x = 0]);
+}
+class B extends A {
+  B([super.x]);
+}
+''');
+  }
+
+  Future<void> test_mixed_first() async {
+    await resolveTestCode('''
+class A {
+  A(int x, {int? y});
+}
+class B extends A {
+  B(int x, int y) : super(x, y: y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x, {int? y});
+}
+class B extends A {
+  B(super.x, int y) : super(y: y);
+}
+''');
+  }
+
+  Future<void> test_mixed_last() async {
+    await resolveTestCode('''
+class A {
+  A(int x, {int? y});
+}
+class B extends A {
+  B(int y, int x) : super(x, y: y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x, {int? y});
+}
+class B extends A {
+  B(int y, super.x) : super(y: y);
+}
+''');
+  }
+
+  Future<void> test_mixed_middle() async {
+    await resolveTestCode('''
+class A {
+  A(int y, {int? z});
+}
+class B extends A {
+  B(int x, int y, int z) : super(y, z: z);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int y, {int? z});
+}
+class B extends A {
+  B(int x, super.y, int z) : super(z: z);
+}
+''');
+  }
+
+  Future<void> test_named_all_reversedOrder() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({int? y, int? x}) : super(x: x, y: y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({super.y, super.x});
+}
+''');
+  }
+
+  Future<void> test_named_all_sameOrder() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({int? x, int? y}) : super(x: x, y: y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({super.x, super.y});
+}
+''');
+  }
+
+  Future<void> test_named_first() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({int? x, required int y}) : super(x: x, y: y + 1);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({super.x, required int y}) : super(y: y + 1);
+}
+''');
+  }
+
+  Future<void> test_named_last() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({required int x, int? y}) : super(x: x + 1, y: y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y});
+}
+class B extends A {
+  B({required int x, super.y}) : super(x: x + 1);
+}
+''');
+  }
+
+  Future<void> test_named_middle() async {
+    await resolveTestCode('''
+class A {
+  A({int? x, int? y, int? z});
+}
+class B extends A {
+  B({required int x, int? y, required int z}) : super(x: x + 1, y: y, z: z + 1);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x, int? y, int? z});
+}
+class B extends A {
+  B({required int x, super.y, required int z}) : super(x: x + 1, z: z + 1);
+}
+''');
+  }
+
+  Future<void> test_named_only() async {
+    await resolveTestCode('''
+class A {
+  A({int? x});
+}
+class B extends A {
+  B({int? x}) : super(x: x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A({int? x});
+}
+class B extends A {
+  B({super.x});
+}
+''');
+  }
+
+  Future<void> test_positional_first() async {
+    await resolveTestCode('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x, int y) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(super.x, int y);
+}
+''');
+  }
+
+  Future<void> test_positional_functionTypedFormalParameter() async {
+    await resolveTestCode('''
+class A {
+  A(int x(int));
+}
+class B extends A {
+  B(int x(int)) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x(int));
+}
+class B extends A {
+  B(super.x);
+}
+''');
+  }
+
+  Future<void> test_positional_last() async {
+    await resolveTestCode('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x, int y) : super(y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x, super.y);
+}
+''');
+  }
+
+  Future<void> test_positional_middle() async {
+    await resolveTestCode('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x, int y, int z) : super(y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x, super.y, int z);
+}
+''');
+  }
+
+  Future<void> test_positional_multiple_optional() async {
+    await resolveTestCode('''
+class A {
+  A([int? x, int? y]);
+}
+class B extends A {
+  B([int? x, int? y]) : super(x, y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A([int? x, int? y]);
+}
+class B extends A {
+  B([super.x, super.y]);
+}
+''');
+  }
+
+  Future<void> test_positional_multiple_required() async {
+    await resolveTestCode('''
+class A {
+  A(int x, int y);
+}
+class B extends A {
+  B(int x, int y) : super(x, y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x, int y);
+}
+class B extends A {
+  B(super.x, super.y);
+}
+''');
+  }
+
+  Future<void> test_positional_multiple_requiredAndOptional() async {
+    await resolveTestCode('''
+class A {
+  A(int x, [int? y]);
+}
+class B extends A {
+  B(int x, [int? y]) : super(x, y);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x, [int? y]);
+}
+class B extends A {
+  B(super.x, [super.y]);
+}
+''');
+  }
+
+  Future<void> test_positional_only() async {
+    await resolveTestCode('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(int x) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B(super.x);
+}
+''');
+  }
+
+  Future<void> test_positional_only_optional() async {
+    await resolveTestCode('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B([int x = 0]) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x);
+}
+class B extends A {
+  B([super.x = 0]);
+}
+''');
+  }
+
+  Future<void> test_positional_unpassedOptionalPositional() async {
+    await resolveTestCode('''
+class A {
+  A(int x, [int y = 0]);
+}
+class B extends A {
+  B(int x) : super(x);
+}
+''');
+    await assertHasFix('''
+class A {
+  A(int x, [int y = 0]);
+}
+class B extends A {
+  B(super.x);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 9478bc2..8bd5f64 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -82,6 +82,7 @@
 import 'convert_to_single_quoted_string_test.dart'
     as convert_to_single_quoted_string;
 import 'convert_to_spread_test.dart' as convert_to_spread;
+import 'convert_to_super_parameters_test.dart' as convert_to_super_parameters;
 import 'convert_to_where_type_test.dart' as convert_to_where_type;
 import 'create_class_test.dart' as create_class;
 import 'create_constructor_for_final_fields_test.dart'
@@ -293,6 +294,7 @@
     convert_to_set_literal.main();
     convert_to_single_quoted_string.main();
     convert_to_spread.main();
+    convert_to_super_parameters.main();
     convert_to_where_type.main();
     create_class.main();
     create_constructor_for_final_field.main();