Introduce a quick fix for prefer_final_parameters

Change-Id: I63bd7b37325a44fbb6066d19ac4e358b675c58e9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206160
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Parker Lougheed 2021-07-08 14:30:24 +00:00 committed by commit-bot@chromium.org
parent f709bf12f0
commit 7e21736935
5 changed files with 232 additions and 0 deletions

View file

@ -43,6 +43,35 @@ class MakeFinal extends CorrectionProducer {
return;
}
if (node is SimpleFormalParameter) {
await builder.addDartFileEdit(file, (builder) {
final keyword = node.keyword;
if (keyword != null && keyword.keyword == Keyword.VAR) {
builder.addSimpleReplacement(range.token(keyword), 'final');
} else {
final type = node.type;
if (type != null) {
builder.addSimpleInsertion(type.offset, 'final ');
return;
}
final identifier = node.identifier;
if (identifier != null) {
builder.addSimpleInsertion(identifier.offset, 'final ');
} else {
builder.addSimpleInsertion(node.offset, 'final ');
}
}
});
return;
}
if (node is SimpleIdentifier && parent is SimpleFormalParameter) {
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleInsertion(node.offset, 'final ');
});
return;
}
VariableDeclarationList list;
if (node is SimpleIdentifier &&
parent is VariableDeclaration &&

View file

@ -96,6 +96,7 @@ bool hasFix(ErrorCode errorCode) =>
errorCode.name == LintNames.prefer_equal_for_default_values ||
errorCode.name == LintNames.prefer_final_fields ||
errorCode.name == LintNames.prefer_final_locals ||
errorCode.name == LintNames.prefer_final_parameters ||
errorCode.name == LintNames.prefer_is_not_empty ||
errorCode.name == LintNames.type_init_formals ||
errorCode.name == LintNames.unawaited_futures ||

View file

@ -456,6 +456,9 @@ class FixProcessor extends BaseProcessor {
LintNames.prefer_final_locals: [
MakeFinal.newInstance,
],
LintNames.prefer_final_parameters: [
MakeFinal.newInstance,
],
LintNames.prefer_for_elements_to_map_fromIterable: [
ConvertMapFromIterableToForLiteral.newInstance,
],

View file

@ -68,6 +68,7 @@ class LintNames {
static const String prefer_final_fields = 'prefer_final_fields';
static const String prefer_final_in_for_each = 'prefer_final_in_for_each';
static const String prefer_final_locals = 'prefer_final_locals';
static const String prefer_final_parameters = 'prefer_final_parameters';
static const String prefer_for_elements_to_map_fromIterable =
'prefer_for_elements_to_map_fromIterable';
static const String prefer_generic_function_type_aliases =

View file

@ -16,6 +16,8 @@ void main() {
defineReflectiveTests(PreferFinalFieldsWithNullSafetyTest);
defineReflectiveTests(PreferFinalInForEachTest);
defineReflectiveTests(PreferFinalLocalsBulkTest);
defineReflectiveTests(PreferFinalParametersTest);
defineReflectiveTests(PreferFinalParametersBulkTest);
});
}
@ -186,3 +188,199 @@ f() {
''');
}
}
@reflectiveTest
class PreferFinalParametersBulkTest extends BulkFixProcessorTest {
@override
String get lintCode => LintNames.prefer_final_parameters;
Future<void> test_singleFile() async {
await resolveTestCode('''
void fn(String test, int other) {
print(test);
print(other);
}
''');
await assertHasFix('''
void fn(final String test, final int other) {
print(test);
print(other);
}
''');
}
}
@reflectiveTest
class PreferFinalParametersTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.MAKE_FINAL;
@override
String get lintCode => LintNames.prefer_final_parameters;
Future<void> test_class_constructor() async {
await resolveTestCode('''
class C {
C(String content) {
print(content);
}
}
''');
await assertHasFix('''
class C {
C(final String content) {
print(content);
}
}
''');
}
Future<void> test_class_requiredCovariant() async {
await resolveTestCode('''
class C {
void fn({required covariant String test}) {
print(test);
}
}
''');
await assertHasFix('''
class C {
void fn({required covariant final String test}) {
print(test);
}
}
''');
}
Future<void> test_closure_hasType() async {
await resolveTestCode('''
void fn() {
['1', '2', '3'].forEach((String string) => print(string));
}
''');
await assertHasFix('''
void fn() {
['1', '2', '3'].forEach((final String string) => print(string));
}
''');
}
Future<void> test_closure_noType() async {
await resolveTestCode('''
void fn() {
['1', '2', '3'].forEach((string) => print(string));
}
''');
await assertHasFix('''
void fn() {
['1', '2', '3'].forEach((final string) => print(string));
}
''');
}
Future<void> test_functionLiteral() async {
await resolveTestCode('''
var fn = (String test) {
print(test);
};
''');
await assertHasFix('''
var fn = (final String test) {
print(test);
};
''');
}
Future<void> test_named_optional() async {
await resolveTestCode('''
void fn({String? test}) {
print(test);
}
''');
await assertHasFix('''
void fn({final String? test}) {
print(test);
}
''');
}
Future<void> test_named_required() async {
await resolveTestCode('''
void fn({required String test}) {
print(test);
}
''');
await assertHasFix('''
void fn({required final String test}) {
print(test);
}
''');
}
Future<void> test_positional_optional() async {
await resolveTestCode('''
void fn([String? test]) {
print(test);
}
''');
await assertHasFix('''
void fn([final String? test]) {
print(test);
}
''');
}
Future<void> test_simple_hasType() async {
await resolveTestCode('''
void fn(String test) {
print(test);
}
''');
await assertHasFix('''
void fn(final String test) {
print(test);
}
''');
}
Future<void> test_simple_noType() async {
await resolveTestCode('''
void fn(test) {
print(test);
}
''');
await assertHasFix('''
void fn(final test) {
print(test);
}
''');
}
Future<void> test_simple_second() async {
await resolveTestCode('''
void fn(final String test, String other) {
print(test);
print(other);
}
''');
await assertHasFix('''
void fn(final String test, final String other) {
print(test);
print(other);
}
''');
}
Future<void> test_simple_var() async {
await resolveTestCode('''
void fn(var test) {
print(test);
}
''');
await assertHasFix('''
void fn(final test) {
print(test);
}
''');
}
}