Fix for use_key_in_widget_constructors to add key at the end

Fixes #48917

Change-Id: Ie9a1e06188ad958ba89cd7b37081878211b3e90b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243905
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Ahmed Ashour 2022-05-10 14:15:43 +00:00 committed by Commit Bot
parent 542aee1e51
commit a67c07c40f
2 changed files with 150 additions and 11 deletions

View file

@ -175,15 +175,26 @@ class AddKeyToConstructors extends CorrectionProducer {
argument is NamedExpression && argument.name.label.name == 'key');
if (existing == null) {
// There is no 'key' argument, so add it.
if (arguments.isEmpty) {
builder.addSimpleInsertion(
argumentList.leftParenthesis.end, 'key: key');
} else {
// This case should never happen because 'key' is the only parameter
// in the constructors for both `StatelessWidget` and `StatefulWidget`.
builder.addSimpleInsertion(
argumentList.leftParenthesis.end, 'key: key, ');
}
var namedArguments = arguments.whereType<NamedExpression>();
var firstNamed = namedArguments.firstOrNull;
var token = firstNamed?.beginToken ?? argumentList.endToken;
var comma = token.previous?.type == TokenType.COMMA;
builder.addInsertion(token.offset, (builder) {
if (arguments.length != namedArguments.length) {
// there are unnamed arguments
if (!comma) {
builder.write(',');
}
builder.write(' ');
}
builder.write('key: key');
if (firstNamed != null) {
builder.write(', ');
} else if (comma) {
builder.write(',');
}
});
} else {
// There is an existing 'key' argument, so we leave it alone.
}

View file

@ -13,6 +13,8 @@ import 'fix_processor.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(AddKeyToConstructorsTest);
defineReflectiveTests(
AddKeyToConstructorsWithoutNamedArgumentsAnywhereTest);
});
}
@ -169,19 +171,93 @@ class MyWidget extends StatelessWidget {
await resolveTestCode('''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
class A extends StatelessWidget {
const A({required this.text, Key? key}) : super(key: key);
final String text;
}
class MyWidget extends A {
MyWidget() : super(text: '');
}
''');
await assertHasFix('''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
class A extends StatelessWidget {
const A({required this.text, Key? key}) : super(key: key);
final String text;
}
class MyWidget extends A {
MyWidget({Key? key}) : super(key: key, text: '');
}
''', errorFilter: (error) => error.errorCode is LintCode);
}
Future<void>
test_constructor_noParameters_withSuper_nonEmpty_tailingComma() async {
await resolveTestCode('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A({required this.text, Key? key}) : super(key: key);
final String text;
}
class MyWidget extends A {
MyWidget() : super(text: '',);
}
''');
await assertHasFix('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A({required this.text, Key? key}) : super(key: key);
final String text;
}
class MyWidget extends A {
MyWidget({Key? key}) : super(key: key, text: '',);
}
''', errorFilter: (error) => error.errorCode is LintCode);
}
Future<void>
test_constructor_noParameters_withSuper_nonNamed_trailingComma() async {
await resolveTestCode('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A(this.widget, {Key? key}) : super(key: key);
final Widget widget;
}
class B extends A {
B() : super(const Text(''),);
}
''');
await assertHasFix('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A(this.widget, {Key? key}) : super(key: key);
final Widget widget;
}
class B extends A {
B({Key? key}) : super(const Text(''), key: key,);
}
''',
//TODO(asashour) there should be no other errors
errorFilter: (error) => error.errorCode is LintCode);
}
Future<void> test_initializer_final_constant() async {
await resolveTestCode('''
import 'package:flutter/material.dart';
@ -311,3 +387,55 @@ class MyWidget extends ParentWidget {
''', errorFilter: (error) => error.errorCode is LintCode);
}
}
@reflectiveTest
class AddKeyToConstructorsWithoutNamedArgumentsAnywhereTest
extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.ADD_KEY_TO_CONSTRUCTORS;
@override
String get lintCode => LintNames.use_key_in_widget_constructors;
@override
String get testPackageLanguageVersion => '2.16';
@override
void setUp() {
super.setUp();
writeTestPackageConfig(
flutter: true,
);
}
Future<void> test_constructor_noParameters_withSuper_nonEmpty() async {
await resolveTestCode('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A(this.widget, {Key? key}) : super(key: key);
final Widget widget;
}
class B extends A {
B() : super(const Text(''));
}
''');
await assertHasFix('''
import 'package:flutter/material.dart';
class A extends StatelessWidget {
const A(this.widget, {Key? key}) : super(key: key);
final Widget widget;
}
class B extends A {
B({Key? key}) : super(const Text(''), key: key);
}
''',
//TODO(asashour) there should be no other errors
errorFilter: (error) => error.errorCode is LintCode);
}
}