Skip to content

Commit c3f1b36

Browse files
author
Dart CI
committed
Version 2.19.0-406.0.dev
Merge c29f994 into dev
2 parents 861d031 + c29f994 commit c3f1b36

File tree

26 files changed

+759
-38
lines changed

26 files changed

+759
-38
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
6+
import 'package:analysis_server/src/services/correction/fix.dart';
7+
import 'package:analyzer/dart/analysis/features.dart';
8+
import 'package:analyzer/dart/ast/ast.dart';
9+
import 'package:analyzer/dart/element/element.dart';
10+
import 'package:analyzer/source/source_range.dart';
11+
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
12+
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
13+
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
14+
import 'package:analyzer_plugin/utilities/range_factory.dart';
15+
import 'package:collection/collection.dart';
16+
17+
class AddSuperParameter extends CorrectionProducer {
18+
int _missingCount = 0;
19+
20+
@override
21+
List<Object> get fixArguments => [_missingCount == 1 ? '' : 's'];
22+
23+
@override
24+
FixKind get fixKind => DartFixKind.ADD_SUPER_PARAMETER;
25+
26+
@override
27+
Future<void> compute(ChangeBuilder builder) async {
28+
if (!libraryElement.featureSet.isEnabled(Feature.super_parameters)) {
29+
return;
30+
}
31+
var constructorDeclaration = node.parent;
32+
if (constructorDeclaration is! ConstructorDeclaration) return;
33+
var classDeclaration = constructorDeclaration.parent;
34+
if (classDeclaration is! ClassDeclaration) return;
35+
var superUnnamedConstructor =
36+
classDeclaration.declaredElement?.supertype?.element.unnamedConstructor;
37+
if (superUnnamedConstructor == null) return;
38+
var superParameters = superUnnamedConstructor.parameters;
39+
var parameters = constructorDeclaration.parameters.parameters;
40+
var missingNamedParameters = <ParameterElement>[];
41+
var superPositionalParameters = <ParameterElement>[];
42+
for (var superParameter in superParameters) {
43+
if (superParameter.isRequired) {
44+
var name = superParameter.name;
45+
if (superParameter.isNamed) {
46+
if (!parameters.any((parameter) => parameter.name?.lexeme == name)) {
47+
missingNamedParameters.add(superParameter);
48+
}
49+
} else {
50+
superPositionalParameters.add(superParameter);
51+
}
52+
}
53+
}
54+
55+
var arePositionalOrdered = true;
56+
FormalParameter? lastPositionalParameter;
57+
for (var i = 0; i < parameters.length; i++) {
58+
var parameter = parameters[i];
59+
if (parameter.isRequiredPositional) {
60+
if (parameter is! SuperFormalParameter ||
61+
i >= superPositionalParameters.length ||
62+
parameter.name.lexeme != superPositionalParameters[i].name) {
63+
arePositionalOrdered = false;
64+
break;
65+
}
66+
lastPositionalParameter = parameter;
67+
}
68+
}
69+
70+
var missingPositionalParameters = <ParameterElement>[];
71+
if (arePositionalOrdered) {
72+
var index = lastPositionalParameter == null
73+
? 0
74+
: parameters.indexOf(lastPositionalParameter) + 1;
75+
missingPositionalParameters = superPositionalParameters.sublist(index);
76+
}
77+
78+
_missingCount =
79+
missingPositionalParameters.length + missingNamedParameters.length;
80+
81+
if (parameters.isEmpty) {
82+
var offset = constructorDeclaration.parameters.leftParenthesis.end;
83+
await builder.addDartFileEdit(file, (builder) {
84+
builder.addInsertion(offset, (builder) {
85+
_writePositional(builder, missingPositionalParameters,
86+
needsInitialComma: false);
87+
88+
if (missingNamedParameters.isNotEmpty) {
89+
_writeNamed(
90+
builder,
91+
missingNamedParameters,
92+
needsInitialComma: missingPositionalParameters.isNotEmpty,
93+
);
94+
}
95+
});
96+
});
97+
} else {
98+
var lastNamedParameter =
99+
parameters.lastWhereOrNull((parameter) => parameter.isNamed);
100+
if (missingPositionalParameters.isNotEmpty) {
101+
var offset = lastPositionalParameter == null
102+
? constructorDeclaration.parameters.leftParenthesis.end
103+
: lastPositionalParameter.end;
104+
105+
await builder.addDartFileEdit(file, (builder) {
106+
builder.addInsertion(offset, (builder) {
107+
_writePositional(builder, missingPositionalParameters,
108+
needsInitialComma: lastPositionalParameter != null);
109+
if (lastPositionalParameter == null && lastNamedParameter != null) {
110+
builder.write(', ');
111+
}
112+
});
113+
});
114+
}
115+
116+
if (missingNamedParameters.isNotEmpty) {
117+
SourceRange replacementRange;
118+
if (lastNamedParameter != null) {
119+
replacementRange = SourceRange(lastNamedParameter.end, 0);
120+
} else if (lastPositionalParameter != null) {
121+
replacementRange = range.endStart(lastPositionalParameter,
122+
constructorDeclaration.parameters.rightParenthesis);
123+
} else {
124+
replacementRange = SourceRange(
125+
constructorDeclaration.parameters.leftParenthesis.end, 0);
126+
}
127+
128+
await builder.addDartFileEdit(file, (builder) {
129+
builder.addReplacement(replacementRange, (builder) {
130+
_writeNamed(
131+
builder,
132+
missingNamedParameters,
133+
needsInitialComma: true,
134+
lastNamedParameter: lastNamedParameter,
135+
);
136+
});
137+
});
138+
}
139+
}
140+
}
141+
142+
void _writeNamed(
143+
DartEditBuilder builder,
144+
List<ParameterElement> parameters, {
145+
FormalParameter? lastNamedParameter,
146+
required bool needsInitialComma,
147+
}) {
148+
var firstParameter = true;
149+
void writeComma() {
150+
if (firstParameter) {
151+
firstParameter = false;
152+
} else {
153+
builder.write(', ');
154+
}
155+
}
156+
157+
if (needsInitialComma) {
158+
builder.write(', ');
159+
}
160+
if (lastNamedParameter == null) {
161+
builder.write('{');
162+
}
163+
for (var parameter in parameters) {
164+
writeComma();
165+
_writeParameter(builder, parameter);
166+
}
167+
if (lastNamedParameter == null) {
168+
builder.write('}');
169+
}
170+
}
171+
172+
void _writeParameter(DartEditBuilder builder, ParameterElement parameter) {
173+
var parameterName = parameter.displayName;
174+
175+
if (parameter.isRequiredNamed) {
176+
builder.write('required ');
177+
}
178+
179+
builder.write('super.');
180+
builder.write(parameterName);
181+
}
182+
183+
void _writePositional(
184+
DartEditBuilder builder,
185+
List<ParameterElement> parameters, {
186+
required bool needsInitialComma,
187+
}) {
188+
var firstParameter = true;
189+
void writeComma() {
190+
if (firstParameter && !needsInitialComma) {
191+
firstParameter = false;
192+
} else {
193+
builder.write(', ');
194+
}
195+
}
196+
197+
for (var parameter in parameters) {
198+
writeComma();
199+
_writeParameter(builder, parameter);
200+
}
201+
}
202+
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ class DartFixKind {
278278
DartFixKindPriority.DEFAULT,
279279
'Add super constructor {0} invocation',
280280
);
281+
static const ADD_SUPER_PARAMETER = FixKind(
282+
'dart.fix.add.superParameter',
283+
DartFixKindPriority.DEFAULT,
284+
"Add required parameter{0}",
285+
);
281286
static const ADD_SWITCH_CASE_BREAK = FixKind(
282287
'dart.fix.add.switchCaseReturn',
283288
DartFixKindPriority.DEFAULT,
@@ -1436,7 +1441,7 @@ class DartFixKind {
14361441
static const REPLACE_RETURN_TYPE_FUTURE_MULTI = FixKind(
14371442
'dart.fix.replace.returnTypeFuture.multi',
14381443
DartFixKindPriority.IN_FILE,
1439-
"Return a 'Future' where required in file.",
1444+
"Return a 'Future' where required in file",
14401445
);
14411446
static const REPLACE_RETURN_TYPE_ITERABLE = FixKind(
14421447
'dart.fix.replace.returnTypeIterable',
@@ -1548,7 +1553,7 @@ class DartFixKind {
15481553
static const REPLACE_WITH_NOT_NULL_AWARE_MULTI = FixKind(
15491554
'dart.fix.replace.withNotNullAware.multi',
15501555
DartFixKindPriority.IN_FILE,
1551-
'Replace with non-null-aware operator everywhere in file.',
1556+
'Replace with non-null-aware operator everywhere in file',
15521557
);
15531558
static const REPLACE_WITH_NULL_AWARE = FixKind(
15541559
'dart.fix.replace.withNullAware',

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import 'package:analysis_server/src/services/correction/dart/add_return_null.dar
3434
import 'package:analysis_server/src/services/correction/dart/add_return_type.dart';
3535
import 'package:analysis_server/src/services/correction/dart/add_static.dart';
3636
import 'package:analysis_server/src/services/correction/dart/add_super_constructor_invocation.dart';
37+
import 'package:analysis_server/src/services/correction/dart/add_super_parameter.dart';
3738
import 'package:analysis_server/src/services/correction/dart/add_switch_case_break.dart';
3839
import 'package:analysis_server/src/services/correction/dart/add_trailing_comma.dart';
3940
import 'package:analysis_server/src/services/correction/dart/add_type_annotation.dart';
@@ -992,6 +993,9 @@ class FixProcessor extends BaseProcessor {
992993
ChangeTo.classOrMixin,
993994
CreateClass.new,
994995
],
996+
CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS: [
997+
AddSuperParameter.new,
998+
],
995999
CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD: [
9961000
ChangeTo.field,
9971001
CreateField.new,

0 commit comments

Comments
 (0)