Enhance CreateConstructorForFinalFields to suggest also required named formal parameters. Change-Id: I64db6eb4ced756e7b261abaa0c8b058c98fdd5d1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/308522 Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart index 865b790..406e801 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart
@@ -15,8 +15,16 @@ import 'package:collection/collection.dart'; class CreateConstructorForFinalFields extends CorrectionProducer { + final _Style _style; + + CreateConstructorForFinalFields.requiredNamed() + : _style = _Style.requiredNamed; + + CreateConstructorForFinalFields.requiredPositional() + : _style = _Style.requiredPositional; + @override - FixKind get fixKind => DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS; + FixKind get fixKind => _style.fixKind; FieldDeclaration? get _errorFieldDeclaration { if (node is VariableDeclaration) { @@ -219,13 +227,26 @@ } builder.write(fixContext.containerName); builder.write('('); - fields.forEachIndexed((index, field) { - if (index > 0) { - builder.write(', '); - } - builder.write('this.'); - builder.write(field.name); - }); + switch (_style) { + case _Style.requiredNamed: + builder.write('{'); + fields.forEachIndexed((index, field) { + if (index > 0) { + builder.write(', '); + } + builder.write('required this.'); + builder.write(field.name); + }); + builder.write('}'); + case _Style.requiredPositional: + fields.forEachIndexed((index, field) { + if (index > 0) { + builder.write(', '); + } + builder.write('this.'); + builder.write(field.name); + }); + } builder.write(');'); builder.write(location.suffix); }); @@ -290,3 +311,18 @@ required this.variableLists, }); } + +enum _Style { + requiredNamed( + fixKind: DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS_REQUIRED_NAMED, + ), + requiredPositional( + fixKind: DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, + ); + + final FixKind fixKind; + + const _Style({ + required this.fixKind, + }); +}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart index 4b28c47..8598cb4 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -694,6 +694,11 @@ DartFixKindPriority.DEFAULT, 'Create constructor for final fields', ); + static const CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS_REQUIRED_NAMED = FixKind( + 'dart.fix.create.constructorForFinalFields.requiredNamed', + DartFixKindPriority.DEFAULT, + 'Create constructor for final fields, required named', + ); static const CREATE_CONSTRUCTOR_SUPER = FixKind( 'dart.fix.create.constructorSuper', 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 02f6931..4bd39f9 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1081,7 +1081,8 @@ ], CompileTimeErrorCode.FINAL_NOT_INITIALIZED: [ AddLate.new, - CreateConstructorForFinalFields.new, + CreateConstructorForFinalFields.requiredNamed, + CreateConstructorForFinalFields.requiredPositional, ], CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1: [ AddFieldFormalParameters.new,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart index 463e778..b83fd01 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_for_final_fields_test.dart
@@ -11,7 +11,9 @@ void main() { defineReflectiveSuite(() { - defineReflectiveTests(CreateConstructorForFinalFieldsTest); + defineReflectiveTests( + CreateConstructorForFinalFieldsRequiredPositionalTest); + defineReflectiveTests(CreateConstructorForFinalFieldsRequiredNamedTest); defineReflectiveTests(CreateConstructorForFinalFieldsWithoutNullSafetyTest); defineReflectiveTests( CreateConstructorForFinalFieldsWithoutSuperParametersTest); @@ -19,7 +21,99 @@ } @reflectiveTest -class CreateConstructorForFinalFieldsTest extends FixProcessorTest { +class CreateConstructorForFinalFieldsRequiredNamedTest + extends FixProcessorTest { + @override + FixKind get kind => + DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS_REQUIRED_NAMED; + + Future<void> test_class_excludesLate() async { + await resolveTestCode(''' +class Test { + final int a; + late final int b; +} +'''); + await assertHasFix(''' +class Test { + final int a; + late final int b; + + Test({required this.a}); +} +'''); + } + + Future<void> test_class_lint_sortConstructorsFirst() async { + createAnalysisOptionsFile(lints: [LintNames.sort_constructors_first]); + await resolveTestCode(''' +class Test { + final int a; + final int b = 2; + final int c; +} +'''); + await assertHasFix(''' +class Test { + Test({required this.a, required this.c}); + + final int a; + final int b = 2; + final int c; +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + Future<void> test_class_simple() async { + await resolveTestCode(''' +class Test { + final int a; + final int b = 2; + final int c; +} +'''); + await assertHasFix(''' +class Test { + final int a; + final int b = 2; + final int c; + + Test({required this.a, required this.c}); +} +''', errorFilter: (error) { + return error.message.contains("'a'"); + }); + } + + Future<void> test_enum_simple() async { + await resolveTestCode(''' +enum E { + v(a: 0, c: 2); + final int a; + final int b = 1; + final int c; +} +'''); + await assertHasFix(''' +enum E { + v(a: 0, c: 2); + final int a; + final int b = 1; + final int c; + + const E({required this.a, required this.c}); +} +''', errorFilter: (error) { + return error.offset == 38; + }); + } +} + +@reflectiveTest +class CreateConstructorForFinalFieldsRequiredPositionalTest + extends FixProcessorTest { @override FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS;