4
4
5
5
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart' ;
6
6
import 'package:analysis_server/src/services/correction/fix.dart' ;
7
+ import 'package:analysis_server/src/services/correction/util.dart' ;
7
8
import 'package:analyzer/dart/analysis/features.dart' ;
8
9
import 'package:analyzer/dart/ast/ast.dart' ;
10
+ import 'package:analyzer/dart/element/element.dart' ;
9
11
import 'package:analyzer/dart/element/nullability_suffix.dart' ;
10
12
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart' ;
13
+ import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart' ;
11
14
import 'package:analyzer_plugin/utilities/fixes/fixes.dart' ;
12
15
13
16
class CreateConstructorForFinalFields extends CorrectionProducer {
14
17
@override
15
18
FixKind get fixKind => DartFixKind .CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS ;
16
19
17
- bool get _isNonNullable => unit.featureSet.isEnabled (Feature .non_nullable);
18
-
19
20
@override
20
21
Future <void > compute (ChangeBuilder builder) async {
21
22
if (node is ! SimpleIdentifier || node.parent is ! VariableDeclaration ) {
@@ -33,15 +34,12 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
33
34
return ;
34
35
}
35
36
36
- // prepare names of uninitialized final fields
37
- var fieldNames = < String > [];
37
+ var variableLists = < VariableDeclarationList > [];
38
38
for (var member in classDeclaration.members) {
39
39
if (member is FieldDeclaration ) {
40
40
var variableList = member.fields;
41
41
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);
45
43
}
46
44
}
47
45
}
@@ -59,41 +57,22 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
59
57
if (keyClass == null ) {
60
58
return ;
61
59
}
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
+ }
96
68
} 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
+
97
76
await builder.addDartFileEdit (file, (builder) {
98
77
builder.addInsertion (targetLocation.offset, (builder) {
99
78
builder.write (targetLocation.prefix);
@@ -105,6 +84,96 @@ class CreateConstructorForFinalFields extends CorrectionProducer {
105
84
}
106
85
}
107
86
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
+
108
177
/// Return an instance of this class. Used as a tear-off in `FixProcessor` .
109
178
static CreateConstructorForFinalFields newInstance () =>
110
179
CreateConstructorForFinalFields ();
0 commit comments