Skip to content

Commit d2d83df

Browse files
asashourCommit Bot
authored and
Commit Bot
committed
CreateConstructorForFinalFields to handle NNBD and super_parameters
Fixes #45812 Change-Id: I8d0f9677cbc9c7628dc9068c83409a1145638e0d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/239300 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 06e0672 commit d2d83df

File tree

2 files changed

+298
-50
lines changed

2 files changed

+298
-50
lines changed

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

Lines changed: 110 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@
44

55
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
66
import 'package:analysis_server/src/services/correction/fix.dart';
7+
import 'package:analysis_server/src/services/correction/util.dart';
78
import 'package:analyzer/dart/analysis/features.dart';
89
import 'package:analyzer/dart/ast/ast.dart';
10+
import 'package:analyzer/dart/element/element.dart';
911
import 'package:analyzer/dart/element/nullability_suffix.dart';
1012
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
13+
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
1114
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
1215

1316
class CreateConstructorForFinalFields extends CorrectionProducer {
1417
@override
1518
FixKind get fixKind => DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS;
1619

17-
bool get _isNonNullable => unit.featureSet.isEnabled(Feature.non_nullable);
18-
1920
@override
2021
Future<void> compute(ChangeBuilder builder) async {
2122
if (node is! SimpleIdentifier || node.parent is! VariableDeclaration) {
@@ -33,15 +34,12 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
3334
return;
3435
}
3536

36-
// prepare names of uninitialized final fields
37-
var fieldNames = <String>[];
37+
var variableLists = <VariableDeclarationList>[];
3838
for (var member in classDeclaration.members) {
3939
if (member is FieldDeclaration) {
4040
var variableList = member.fields;
4141
if (variableList.isFinal && !variableList.isLate) {
42-
fieldNames.addAll(variableList.variables
43-
.where((v) => v.initializer == null)
44-
.map((v) => v.name.name));
42+
variableLists.add(variableList);
4543
}
4644
}
4745
}
@@ -59,41 +57,22 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
5957
if (keyClass == null) {
6058
return;
6159
}
62-
await builder.addDartFileEdit(file, (builder) {
63-
builder.addInsertion(targetLocation.offset, (builder) {
64-
builder.write(targetLocation.prefix);
65-
builder.write('const ');
66-
builder.write(className);
67-
builder.write('({');
68-
builder.writeType(
69-
keyClass.instantiate(
70-
typeArguments: const [],
71-
nullabilitySuffix: _isNonNullable
72-
? NullabilitySuffix.question
73-
: NullabilitySuffix.star,
74-
),
75-
);
76-
builder.write(' key');
77-
78-
var childrenFields = <String>[];
79-
for (var fieldName in fieldNames) {
80-
if (fieldName == 'child' || fieldName == 'children') {
81-
childrenFields.add(fieldName);
82-
continue;
83-
}
84-
builder.write(', this.');
85-
builder.write(fieldName);
86-
}
87-
for (var fieldName in childrenFields) {
88-
builder.write(', this.');
89-
builder.write(fieldName);
90-
}
91-
92-
builder.write('}) : super(key: key);');
93-
builder.write(targetLocation.suffix);
94-
});
95-
});
60+
61+
if (unit.featureSet.isEnabled(Feature.super_parameters)) {
62+
await _withSuperParameters(
63+
builder, targetLocation, className, variableLists);
64+
} else {
65+
await _withoutSuperParameters(
66+
builder, targetLocation, className, keyClass, variableLists);
67+
}
9668
} else {
69+
var fieldNames = <String>[];
70+
for (var variableList in variableLists) {
71+
fieldNames.addAll(variableList.variables
72+
.where((v) => v.initializer == null)
73+
.map((v) => v.name.name));
74+
}
75+
9776
await builder.addDartFileEdit(file, (builder) {
9877
builder.addInsertion(targetLocation.offset, (builder) {
9978
builder.write(targetLocation.prefix);
@@ -105,6 +84,96 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
10584
}
10685
}
10786

87+
Future<void> _withoutSuperParameters(
88+
ChangeBuilder builder,
89+
ClassMemberLocation targetLocation,
90+
String className,
91+
ClassElement keyClass,
92+
List<VariableDeclarationList> variableLists) async {
93+
var isNonNullable = unit.featureSet.isEnabled(Feature.non_nullable);
94+
await builder.addDartFileEdit(file, (builder) {
95+
builder.addInsertion(targetLocation.offset, (builder) {
96+
builder.write(targetLocation.prefix);
97+
builder.write('const ');
98+
builder.write(className);
99+
builder.write('({');
100+
builder.writeType(
101+
keyClass.instantiate(
102+
typeArguments: const [],
103+
nullabilitySuffix: isNonNullable
104+
? NullabilitySuffix.question
105+
: NullabilitySuffix.star,
106+
),
107+
);
108+
builder.write(' key');
109+
110+
_writeParameters(builder, variableLists, isNonNullable);
111+
112+
builder.write('}) : super(key: key);');
113+
builder.write(targetLocation.suffix);
114+
});
115+
});
116+
}
117+
118+
Future<void> _withSuperParameters(
119+
ChangeBuilder builder,
120+
ClassMemberLocation targetLocation,
121+
String className,
122+
List<VariableDeclarationList> variableLists) async {
123+
await builder.addDartFileEdit(file, (builder) {
124+
builder.addInsertion(targetLocation.offset, (builder) {
125+
builder.write(targetLocation.prefix);
126+
builder.write('const ');
127+
builder.write(className);
128+
builder.write('({');
129+
builder.write('super.key');
130+
131+
_writeParameters(builder, variableLists, true);
132+
133+
builder.write('});');
134+
builder.write(targetLocation.suffix);
135+
});
136+
});
137+
}
138+
139+
void _writeParameters(DartEditBuilder builder,
140+
List<VariableDeclarationList> variableLists, bool isNonNullable) {
141+
var childrenFields = <String>[];
142+
var childrenNullables = <bool>[];
143+
for (var variableList in variableLists) {
144+
var fieldNames = variableList.variables
145+
.where((v) => v.initializer == null)
146+
.map((v) => v.name.name);
147+
148+
for (var fieldName in fieldNames) {
149+
if (fieldName == 'child' || fieldName == 'children') {
150+
childrenFields.add(fieldName);
151+
childrenNullables.add(variableList.type?.type?.nullabilitySuffix ==
152+
NullabilitySuffix.question);
153+
continue;
154+
}
155+
builder.write(', ');
156+
if (isNonNullable &&
157+
variableList.type?.type?.nullabilitySuffix !=
158+
NullabilitySuffix.question) {
159+
builder.write('required ');
160+
}
161+
builder.write('this.');
162+
builder.write(fieldName);
163+
}
164+
}
165+
for (var i = 0; i < childrenFields.length; i++) {
166+
var fieldName = childrenFields[i];
167+
var nullableField = childrenNullables[i];
168+
builder.write(', ');
169+
if (isNonNullable && !nullableField) {
170+
builder.write('required ');
171+
}
172+
builder.write('this.');
173+
builder.write(fieldName);
174+
}
175+
}
176+
108177
/// Return an instance of this class. Used as a tear-off in `FixProcessor`.
109178
static CreateConstructorForFinalFields newInstance() =>
110179
CreateConstructorForFinalFields();

0 commit comments

Comments
 (0)