From dd93f6fae0bb246adebbe86158b2eecd653699ac Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Tue, 18 Feb 2025 21:48:29 -0800 Subject: [PATCH] Fix for create constructor for Widget with private fields. Fixes https://github.com/dart-lang/sdk/issues/56182 Change-Id: I25a94dbb5af5dda4db1fde9494783df215587fd5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/410520 Reviewed-by: Samuel Rawlins Commit-Queue: Keerti Parthasarathy --- .../create_constructor_for_final_fields.dart | 42 +++++++++++---- ...ate_constructor_for_final_fields_test.dart | 52 +++++++++++++++++++ 2 files changed, 84 insertions(+), 10 deletions(-) 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 e2899155af5..ff73e262e78 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 @@ -174,13 +174,19 @@ class CreateConstructorForFinalFields extends ResolvedCorrectionProducer { ), ); builder.write(' key'); + var fieldsForInitializers = <_Field>[]; _writeFlutterParameters( builder: builder, variableLists: fixContext.variableLists, + fieldsForInitializers: fieldsForInitializers, ); - builder.write('}) : super(key: key);'); + builder.write('}) : '); + if (fieldsForInitializers.isNotEmpty) { + builder.write('${_getInitalizersString(fieldsForInitializers)}, '); + } + builder.write('super(key: key);'); }); }); } @@ -198,16 +204,29 @@ class CreateConstructorForFinalFields extends ResolvedCorrectionProducer { builder.write('({'); builder.write('super.key'); + var fieldsForInitializers = <_Field>[]; _writeFlutterParameters( builder: builder, variableLists: fixContext.variableLists, + fieldsForInitializers: fieldsForInitializers, ); - builder.write('});'); + builder.write('})'); + if (fieldsForInitializers.isNotEmpty) { + builder.write(' : ${_getInitalizersString(fieldsForInitializers)}'); + } + builder.write(';'); }); }); } + String _getInitalizersString(List<_Field> fieldsForInitializers) => + fieldsForInitializers + .map((field) { + return '${field.fieldName} = ${field.namedFormalParameterName}'; + }) + .join(', '); + Future _notFlutterNamed({ required _FixContext fixContext, required NamedCompilationUnitMember containerDeclaration, @@ -259,12 +278,7 @@ class CreateConstructorForFinalFields extends ResolvedCorrectionProducer { builder.write('})'); if (fieldsForInitializers.isNotEmpty) { - var code = fieldsForInitializers - .map((field) { - return '${field.fieldName} = ${field.namedFormalParameterName}'; - }) - .join(', '); - builder.write(' : $code'); + builder.write(' : ${_getInitalizersString(fieldsForInitializers)}'); } builder.write(';'); @@ -332,6 +346,7 @@ class CreateConstructorForFinalFields extends ResolvedCorrectionProducer { void _writeFlutterParameters({ required DartEditBuilder builder, required Iterable variableLists, + required List<_Field> fieldsForInitializers, }) { var fields = _fieldsToWrite(variableLists); if (fields == null) { @@ -345,8 +360,15 @@ class CreateConstructorForFinalFields extends ResolvedCorrectionProducer { if (field.hasNonNullableType) { builder.write('required '); } - builder.write('this.'); - builder.write(field.fieldName); + if (field.namedFormalParameterName == field.fieldName) { + builder.write('this.'); + builder.write(field.fieldName); + } else { + builder.write(utils.getNodeText(field.typeAnnotation)); + builder.write(' '); + builder.write(field.namedFormalParameterName); + fieldsForInitializers.add(field); + } } } } 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 dc4639d041e..e4ef8547d4c 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 @@ -46,6 +46,31 @@ class Test { '''); } + Future test_class_flutter() async { + writeTestPackageConfig(flutter: true); + await resolveTestCode(''' +import 'package:flutter/widgets.dart'; + +class Test extends StatelessWidget { + final int _a; +} +'''); + await assertHasFix( + ''' +import 'package:flutter/widgets.dart'; + +class Test extends StatelessWidget { + final int _a; + + const Test({super.key, required int a}) : _a = a; +} +''', + errorFilter: (error) { + return error.message.contains("'_a' must be initialized"); + }, + ); + } + Future test_class_hasSuperClass_withOptionalNamed() async { await resolveTestCode(''' class A { @@ -556,4 +581,31 @@ class MyWidget extends StatelessWidget { }, ); } + + Future test_class_flutter_private_field() async { + writeTestPackageConfig(flutter: true); + await resolveTestCode(''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int _a; + final int b; +} +'''); + await assertHasFix( + ''' +import 'package:flutter/widgets.dart'; + +class MyWidget extends StatelessWidget { + final int _a; + final int b; + + const MyWidget({Key? key, required int a, required this.b}) : _a = a, super(key: key); +} +''', + errorFilter: (error) { + return error.message.contains("'b'"); + }, + ); + } }