[analyzer] Generate multiple cases in missing cases fix

This pipes multiple witnesses from a non-exhaustive switch expression
or statement to the ADD_MISSING_SWITCH_CASES fix, such that multiple
cases can now be inserted in a single fix.

Change-Id: I5625bbb81c72917f10f4388cfe96d1bd1536c269
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371062
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2024-06-12 12:45:09 +00:00 committed by Commit Queue
parent 75f9312a50
commit 726f9f1a68
3 changed files with 51 additions and 28 deletions

View file

@ -31,8 +31,8 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
return;
}
var patternParts = diagnostic.data;
if (patternParts is! List<MissingPatternPart>) {
var patternPartsList = diagnostic.data;
if (patternPartsList is! List<List<MissingPatternPart>>) {
return;
}
@ -40,7 +40,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
await _switchExpression(
builder: builder,
node: node,
patternParts: patternParts,
patternPartsList: patternPartsList,
);
}
@ -48,7 +48,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
await _switchStatement(
builder: builder,
node: node,
patternParts: patternParts,
patternPartsList: patternPartsList,
);
}
}
@ -56,7 +56,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
Future<void> _switchExpression({
required ChangeBuilder builder,
required SwitchExpression node,
required List<MissingPatternPart> patternParts,
required List<List<MissingPatternPart>> patternPartsList,
}) async {
var lineIndent = utils.getLinePrefix(node.offset);
var singleIndent = utils.oneIndent;
@ -67,13 +67,15 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
rightParenthesis: node.rightParenthesis,
leftBracket: node.leftBracket,
rightBracket: node.rightBracket, (builder) {
builder.write(lineIndent);
builder.write(singleIndent);
builder.writeln('// TODO: Handle this case.');
builder.write(lineIndent);
builder.write(singleIndent);
_writePatternParts(builder, patternParts);
builder.writeln(' => throw UnimplementedError(),');
for (var patternParts in patternPartsList) {
builder.write(lineIndent);
builder.write(singleIndent);
builder.writeln('// TODO: Handle this case.');
builder.write(lineIndent);
builder.write(singleIndent);
_writePatternPart(builder, patternParts);
builder.writeln(' => throw UnimplementedError(),');
}
});
});
}
@ -81,7 +83,7 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
Future<void> _switchStatement({
required ChangeBuilder builder,
required SwitchStatement node,
required List<MissingPatternPart> patternParts,
required List<List<MissingPatternPart>> patternPartsList,
}) async {
var lineIndent = utils.getLinePrefix(node.offset);
var singleIndent = utils.oneIndent;
@ -92,20 +94,22 @@ class AddMissingSwitchCases extends ResolvedCorrectionProducer {
rightParenthesis: node.rightParenthesis,
leftBracket: node.leftBracket,
rightBracket: node.rightBracket, (builder) {
builder.write(lineIndent);
builder.write(singleIndent);
builder.write('case ');
_writePatternParts(builder, patternParts);
builder.writeln(':');
builder.write(lineIndent);
builder.write(singleIndent);
builder.write(singleIndent);
builder.writeln('// TODO: Handle this case.');
for (var patternParts in patternPartsList) {
builder.write(lineIndent);
builder.write(singleIndent);
builder.write('case ');
_writePatternPart(builder, patternParts);
builder.writeln(':');
builder.write(lineIndent);
builder.write(singleIndent);
builder.write(singleIndent);
builder.writeln('// TODO: Handle this case.');
}
});
});
}
void _writePatternParts(
void _writePatternPart(
DartEditBuilder builder,
List<MissingPatternPart> parts,
) {

View file

@ -81,6 +81,8 @@ int f(E x) {
E.first => 0,
// TODO: Handle this case.
E.second => throw UnimplementedError(),
// TODO: Handle this case.
E.third => throw UnimplementedError(),
};
}
''');
@ -108,6 +110,10 @@ int f(prefix.E x) {
return switch (x) {
// TODO: Handle this case.
prefix.E.first => throw UnimplementedError(),
// TODO: Handle this case.
prefix.E.second => throw UnimplementedError(),
// TODO: Handle this case.
prefix.E.third => throw UnimplementedError(),
};
}
''');
@ -148,6 +154,10 @@ int f() {
return switch (value) {
// TODO: Handle this case.
E.first => throw UnimplementedError(),
// TODO: Handle this case.
E.second => throw UnimplementedError(),
// TODO: Handle this case.
E.third => throw UnimplementedError(),
};
}
''');
@ -248,6 +258,8 @@ int f(num x) {
return switch (x) {
// TODO: Handle this case.
double() => throw UnimplementedError(),
// TODO: Handle this case.
int() => throw UnimplementedError(),
};
}
''');
@ -316,6 +328,8 @@ void f(num x) {
switch (x) {
case double():
// TODO: Handle this case.
case int():
// TODO: Handle this case.
}
}
''');

View file

@ -963,9 +963,16 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
var errorBuffer = SimpleDartBuffer();
error.witnesses.first.toDart(errorBuffer, forCorrection: false);
var correctionTextBuffer = SimpleDartBuffer();
var correctionDataBuffer = AnalyzerDartTemplateBuffer();
error.witnesses.first.toDart(correctionTextBuffer, forCorrection: true);
error.witnesses.first.toDart(correctionDataBuffer, forCorrection: true);
var correctionData = <List<MissingPatternPart>>[];
for (var witness in error.witnesses) {
var correctionDataBuffer = AnalyzerDartTemplateBuffer();
witness.toDart(correctionDataBuffer, forCorrection: true);
if (correctionDataBuffer.isComplete) {
correctionData.add(correctionDataBuffer.parts);
}
}
_errorReporter.atToken(
switchKeyword,
isSwitchExpression
@ -976,9 +983,7 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
errorBuffer.toString(),
correctionTextBuffer.toString(),
],
data: correctionDataBuffer.isComplete
? correctionDataBuffer.parts
: null,
data: correctionData.isNotEmpty ? correctionData : null,
);
}
}