From 8b555128beb587c7b3ce36324e500d7137b8656d Mon Sep 17 00:00:00 2001 From: Brian Wilkerson Date: Wed, 27 May 2026 14:39:09 -0700 Subject: [PATCH] Support converting a declaring param to an initializing param Server already supports the opposite, so this just makes it possible to go both ways. This doesn't support converting a declaring function typed parameter. We could add that, but I'm hoping it's rare enough to not be worth doing. Other than that, I think I've covered all the cases, but please pay special attention to the test coverage. Change-Id: I400204ca820d0e0f1cc44075dd54946db79b2115 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506740 Reviewed-by: Samuel Rawlins Commit-Queue: Brian Wilkerson --- .../dart/convert_to_initializing_formal.dart | 27 ++++++++++++++++ .../convert_to_initializing_formal_test.dart | 32 ++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart index 8864212b91f..38840f556ae 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart @@ -7,6 +7,7 @@ import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analysis_server_plugin/edit/dart/correction_producer.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer_plugin/utilities/assist/assist.dart'; @@ -336,6 +337,32 @@ class ConvertToInitializingFormal extends ResolvedCorrectionProducer { field, assignment: statement, ); + } else if (parameter is RegularFormalParameter && + parameterElement is FieldFormalParameterElement) { + // This is a declaring parameter in a primary constructor. + var keyword = parameter.constFinalOrVarKeyword; + if (keyword == null) return; + var parameterName = parameter.name; + if (parameterName == null) return; + var container = node.thisOrAncestorOfType(); + if (container == null) return; + if (parameter.functionTypedSuffix != null) return; + await builder.addDartFileEdit(file, (builder) { + var type = parameter.type; + // Remove the `var` or `final` keyword, and add `this.`. + builder.addSimpleReplacement( + range.startStart(keyword, parameterName), + 'this.', + ); + // Add the field. + builder.insertField(container, (builder) { + builder.writeFieldDeclaration( + parameterName.lexeme, + isFinal: keyword.keyword == Keyword.FINAL, + type: type?.type, + ); + }); + }); } } diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_initializing_formal_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_initializing_formal_test.dart index 7e969ae7239..6107249d265 100644 --- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_initializing_formal_test.dart +++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_initializing_formal_test.dart @@ -279,7 +279,37 @@ class A { '''); } - Future test_parameterDeclaration_primary() async { + Future test_parameterDeclaration_primary_declaring_final() async { + await resolveTestCode(''' +class C(final int ^test); +'''); + await assertHasAssist(''' +class C(this.test) { + final int test; +} +'''); + } + + Future + test_parameterDeclaration_primary_declaring_functionTyped() async { + await resolveTestCode(''' +class C(var int ^test(String)); +'''); + await assertNoAssist(); + } + + Future test_parameterDeclaration_primary_declaring_var() async { + await resolveTestCode(''' +class C(var int ^test); +'''); + await assertHasAssist(''' +class C(this.test) { + int test; +} +'''); + } + + Future test_parameterDeclaration_primary_regular() async { await resolveTestCode(''' class C(int ^test) { int test;