Skip to content

Commit 10569cb

Browse files
FMorschelCommit Queue
authored andcommitted
[DAS] Adds fixes for required named parameters
Bug: #53707 Fixes: #60783 Change-Id: I62646bd1ac5805fb9030eda712064ec7d8c253b9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422369 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Auto-Submit: Felipe Morschel <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
1 parent b2766ec commit 10569cb

File tree

9 files changed

+501
-67
lines changed

9 files changed

+501
-67
lines changed

pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,34 @@ import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
77
import 'package:analyzer/dart/ast/ast.dart';
88
import 'package:analyzer/dart/element/element.dart';
99
import 'package:analyzer/src/generated/error_verifier.dart';
10-
import 'package:analyzer/src/utilities/extensions/flutter.dart';
1110
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
1211
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
1312

13+
/// The boolean value indicates whether the field is required.
14+
/// The string value is the field/parameter name.
15+
typedef _FieldRecord = ({bool isRequired, String parameter});
16+
1417
class AddFieldFormalParameters extends ResolvedCorrectionProducer {
15-
AddFieldFormalParameters({required super.context});
18+
final _Style _style;
19+
20+
bool _useRequired = false;
21+
22+
@override
23+
final FixKind fixKind;
24+
25+
AddFieldFormalParameters({required super.context})
26+
: _style = _Style.base,
27+
fixKind = DartFixKind.ADD_INITIALIZING_FORMAL_PARAMETERS;
28+
29+
AddFieldFormalParameters.requiredNamed({required super.context})
30+
: _style = _Style.requiredNamed,
31+
fixKind = DartFixKind.ADD_INITIALIZING_FORMAL_NAMED_PARAMETERS;
1632

1733
@override
1834
CorrectionApplicability get applicability =>
1935
// TODO(applicability): comment on why.
2036
CorrectionApplicability.singleLocation;
2137

22-
@override
23-
FixKind get fixKind => DartFixKind.ADD_INITIALIZING_FORMAL_PARAMETERS;
24-
2538
@override
2639
Future<void> compute(ChangeBuilder builder) async {
2740
var constructor = node.parent;
@@ -47,43 +60,73 @@ class AddFieldFormalParameters extends ResolvedCorrectionProducer {
4760
(a, b) => a.firstFragment.nameOffset! - b.firstFragment.nameOffset!,
4861
);
4962

50-
// Specialize for Flutter widgets.
51-
if (superType.isExactlyStatelessWidgetType ||
52-
superType.isExactlyStatefulWidgetType) {
53-
if (parameters.isNotEmpty && parameters.last.isNamed) {
54-
String parameterForField(FieldElement field) {
55-
var prefix = '';
56-
if (typeSystem.isPotentiallyNonNullable(field.type)) {
57-
prefix = 'required ';
58-
}
59-
return '${prefix}this.${field.name}';
60-
}
61-
62-
var fieldParametersCode = fields.map(parameterForField).join(', ');
63-
await builder.addDartFileEdit(file, (builder) {
64-
builder.addSimpleInsertion(
65-
parameters.last.end,
66-
', $fieldParametersCode',
67-
);
68-
});
69-
return;
70-
}
71-
}
72-
7363
// Prepare the last required parameter.
7464
FormalParameter? lastRequiredParameter;
65+
FormalParameter? firstNamedParameter;
7566
for (var parameter in parameters) {
7667
if (parameter.isRequiredPositional) {
7768
lastRequiredParameter = parameter;
69+
} else if (_style == _Style.base) {
70+
break;
71+
} else if (parameter.isOptionalPositional) {
72+
// If there are optional positional parameters, we can't add required
73+
// named parameters.
74+
return;
75+
} else if (parameter.isNamed) {
76+
firstNamedParameter = parameter;
77+
break;
7878
}
7979
}
8080

81-
var fieldParametersCode = fields
82-
.map((field) => 'this.${field.name}')
83-
.join(', ');
81+
if (_style == _Style.requiredNamed) {
82+
_useRequired = true;
83+
}
84+
85+
var fieldsRecords = fields.map(_parameterForField).toList();
86+
var requiredFirst =
87+
getCodeStyleOptions(unitResult.file).requiredNamedParametersFirst;
88+
if (requiredFirst) {
89+
fieldsRecords.sort((a, b) {
90+
if (a.isRequired && !b.isRequired) {
91+
return -1;
92+
} else if (!a.isRequired && b.isRequired) {
93+
return 1;
94+
}
95+
return a.parameter.compareTo(b.parameter);
96+
});
97+
}
98+
var requiredParameters = fieldsRecords.where((r) => r.isRequired);
99+
var optionalParameters = fieldsRecords
100+
.where((r) => !r.isRequired)
101+
.map((r) => r.parameter);
102+
var fieldParametersCode = fieldsRecords.map((r) => r.parameter).join(', ');
84103
await builder.addDartFileEdit(file, (builder) {
85-
if (lastRequiredParameter != null) {
104+
if (firstNamedParameter != null &&
105+
requiredFirst &&
106+
requiredParameters.isNotEmpty) {
86107
builder.addSimpleInsertion(
108+
firstNamedParameter.offset,
109+
'${requiredParameters.map((r) => r.parameter).join(', ')}, ',
110+
);
111+
if (optionalParameters.isNotEmpty) {
112+
fieldParametersCode = optionalParameters.join(', ');
113+
} else {
114+
return; // No optional parameters to add.
115+
}
116+
}
117+
if (_style == _Style.requiredNamed) {
118+
var lastParameter = parameters.lastOrNull;
119+
if (lastParameter != null) {
120+
var write = ', ';
121+
if (!lastParameter.isNamed) {
122+
write += '{$fieldParametersCode}';
123+
} else {
124+
write += fieldParametersCode;
125+
}
126+
builder.addSimpleInsertion(parameters.last.end, write);
127+
}
128+
} else if (lastRequiredParameter != null) {
129+
return builder.addSimpleInsertion(
87130
lastRequiredParameter.end,
88131
', $fieldParametersCode',
89132
);
@@ -96,4 +139,16 @@ class AddFieldFormalParameters extends ResolvedCorrectionProducer {
96139
}
97140
});
98141
}
142+
143+
_FieldRecord _parameterForField(FieldElement field) {
144+
var prefix = '';
145+
var isRequired = false;
146+
if (typeSystem.isPotentiallyNonNullable(field.type) && _useRequired) {
147+
isRequired = true;
148+
prefix = 'required ';
149+
}
150+
return (isRequired: isRequired, parameter: '${prefix}this.${field.name}');
151+
}
99152
}
153+
154+
enum _Style { base, requiredNamed }

0 commit comments

Comments
 (0)