Add quick fix for `UNNECESSARY_FINAL`
Fixes #48778
Change-Id: I86b0b8344768db9653c16507a88d4f454dc86ed6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240840
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart
new file mode 100644
index 0000000..73078a5
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_final.dart
@@ -0,0 +1,41 @@
+// 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/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.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 RemoveUnnecessaryFinal extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_FINAL;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_FINAL_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var node = this.node;
+ Token? keyword;
+ if (node is FieldFormalParameter) {
+ keyword = node.keyword;
+ } else if (node is SuperFormalParameter) {
+ keyword = node.keyword;
+ }
+ if (keyword == null) return;
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addDeletion(range.startStart(keyword!, keyword.next!));
+ });
+ }
+}
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 5adb652..cba9147 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
@@ -1456,7 +1456,7 @@
HintCode.UNNECESSARY_CAST:
status: hasFix
HintCode.UNNECESSARY_FINAL:
- status: needsEvaluation
+ status: hasFix
HintCode.UNNECESSARY_IGNORE:
status: needsEvaluation
HintCode.UNNECESSARY_IMPORT:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index ed8f791..e5e3585 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1128,6 +1128,16 @@
DartFixKindPriority.IN_FILE,
'Remove all unnecessary casts in file',
);
+ static const REMOVE_UNNECESSARY_FINAL = FixKind(
+ 'dart.fix.remove.unnecessaryFinal',
+ DartFixKindPriority.DEFAULT,
+ "Remove unnecessary 'final'",
+ );
+ static const REMOVE_UNNECESSARY_FINAL_MULTI = FixKind(
+ 'dart.fix.remove.unnecessaryFinal.multi',
+ DartFixKindPriority.IN_FILE,
+ "Remove all unnecessary 'final's in file",
+ );
static const REMOVE_UNNECESSARY_CONST = FixKind(
'dart.fix.remove.unnecessaryConst',
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 c79ab5f..61583a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -139,6 +139,7 @@
import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_final.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
@@ -1326,6 +1327,9 @@
HintCode.UNNECESSARY_CAST: [
RemoveUnnecessaryCast.new,
],
+ HintCode.UNNECESSARY_FINAL: [
+ RemoveUnnecessaryFinal.new,
+ ],
HintCode.UNNECESSARY_IMPORT: [
RemoveUnusedImport.new,
],
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart
new file mode 100644
index 0000000..70f9035f
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_final_test.dart
@@ -0,0 +1,122 @@
+// 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:analyzer/src/error/codes.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(RemoveUnnecessaryFinalBulkTest);
+ defineReflectiveTests(RemoveUnnecessaryFinalMultiTest);
+ defineReflectiveTests(RemoveUnnecessaryFinalTest);
+ });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalBulkTest extends BulkFixProcessorTest {
+ Future<void> test_assignment() async {
+ await resolveTestCode('''
+class A {
+ A(final this.value);
+ int value;
+}
+class B extends A {
+ B(final super.value);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(this.value);
+ int value;
+}
+class B extends A {
+ B(super.value);
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalMultiTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_FINAL_MULTI;
+
+ Future<void> test_multi() async {
+ await resolveTestCode('''
+class A {
+ A(final this.v1, final this.v2);
+ int v1;
+ int v2;
+}
+''');
+ await assertHasFixAllFix(HintCode.UNNECESSARY_FINAL, '''
+class A {
+ A(this.v1, this.v2);
+ int v1;
+ int v2;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryFinalTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_FINAL;
+
+ Future<void> test_positional() async {
+ await resolveTestCode('''
+class C {
+ C([final this.value = 0]);
+ int value;
+}
+''');
+ await assertHasFix('''
+class C {
+ C([this.value = 0]);
+ int value;
+}
+''');
+ }
+
+ Future<void> test_super() async {
+ await resolveTestCode('''
+class A {
+ A(this.value);
+ int value;
+}
+class B extends A {
+ B(final super.value);
+}
+''');
+ await assertHasFix('''
+class A {
+ A(this.value);
+ int value;
+}
+class B extends A {
+ B(super.value);
+}
+''');
+ }
+
+ Future<void> test_this() async {
+ await resolveTestCode('''
+class C {
+ C(final this.value);
+ int value;
+}
+''');
+ await assertHasFix('''
+class C {
+ C(this.value);
+ int value;
+}
+''');
+ }
+}
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 768c4c6..291306b 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
@@ -169,6 +169,7 @@
import 'remove_type_arguments_test.dart' as remove_type_arguments;
import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
+import 'remove_unnecessary_final_test.dart' as remove_unnecessary_final;
import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
import 'remove_unnecessary_parentheses_test.dart'
@@ -383,6 +384,7 @@
remove_type_arguments.main();
remove_unnecessary_cast.main();
remove_unnecessary_const.main();
+ remove_unnecessary_final.main();
remove_unnecessary_late.main();
remove_unnecessary_new.main();
remove_unnecessary_parentheses.main();