[analyzer] handle dead code with do statement

Bug: #43511
Change-Id: Iddae879e5343ccdafc33258495771bd6a60afef2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260110
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Ahmed Ashour 2022-10-10 23:03:34 +00:00 committed by Commit Queue
parent 20218dfe15
commit 7432006bd7
4 changed files with 192 additions and 3 deletions

View file

@ -7,6 +7,7 @@ import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@ -73,8 +74,12 @@ class RemoveDeadCode extends CorrectionProducer {
});
}
} else if (coveredNode is Statement) {
var rangeToRemove =
utils.getLinesRangeStatements(<Statement>[coveredNode]);
if (coveredNode is DoStatement &&
await _computeDoStatement(builder, coveredNode)) {
return;
}
var rangeToRemove = utils.getLinesRangeStatements([coveredNode]);
await builder.addDartFileEdit(file, (builder) {
builder.addDeletion(rangeToRemove);
});
@ -87,4 +92,62 @@ class RemoveDeadCode extends CorrectionProducer {
});
}
}
Future<bool> _computeDoStatement(
ChangeBuilder builder, DoStatement statement) async {
var problemMessage = diagnostic?.problemMessage;
if (problemMessage != null) {
var problemOffset = problemMessage.offset;
var problemLength = problemMessage.length;
var doKeyword = statement.doKeyword;
var whileKeyword = statement.whileKeyword;
Future<void> deleteNoBrackets() async {
await builder.addDartFileEdit(file, (builder) {
builder.addDeletion(range.startStart(doKeyword, doKeyword.next!));
_deleteLineRange(
builder, range.startEnd(whileKeyword, statement.semicolon));
});
}
Future<void> deleteBrackets(Block block) async {
await builder.addDartFileEdit(file, (builder) {
_deleteLineRange(
builder, range.startEnd(doKeyword, block.leftBracket));
_deleteLineRange(
builder, range.startEnd(block.rightBracket, statement.semicolon));
});
}
if (problemOffset == doKeyword.offset) {
if (problemLength == doKeyword.length) {
await deleteNoBrackets();
return true;
} else {
var body = statement.body;
if (body is Block &&
problemLength == body.leftBracket.end - problemOffset) {
await deleteBrackets(body);
return true;
}
}
} else if (problemOffset + problemLength == statement.semicolon.end) {
if (problemOffset == whileKeyword.offset) {
await deleteNoBrackets();
return true;
} else {
var body = statement.body;
if (body is Block && problemOffset == body.rightBracket.offset) {
await deleteBrackets(body);
return true;
}
}
}
}
return false;
}
void _deleteLineRange(DartFileEditBuilder builder, SourceRange sourceRange) {
builder.addDeletion(utils.getLinesRange(sourceRange));
}
}

View file

@ -121,6 +121,70 @@ void f(bool c) {
''');
}
Future<void> test_doWhile_atDo() async {
await resolveTestCode('''
void f(bool c) {
do {
print(c);
return;
} while (c);
}
''');
await assertHasFix('''
void f(bool c) {
print(c);
return;
}
''', errorFilter: (err) => err.problemMessage.length == 4);
}
Future<void> test_doWhile_atDo_noBrackets() async {
await resolveTestCode('''
void f(bool c) {
do
return;
while (c);
}
''');
await assertHasFix('''
void f(bool c) {
return;
}
''', errorFilter: (err) => err.problemMessage.length == 2);
}
Future<void> test_doWhile_atWhile() async {
await resolveTestCode('''
void f(bool c) {
do {
print(c);
return;
} while (c);
}
''');
await assertHasFix('''
void f(bool c) {
print(c);
return;
}
''', errorFilter: (err) => err.problemMessage.length == 12);
}
Future<void> test_doWhile_atWhile_noBrackets() async {
await resolveTestCode('''
void f(bool c) {
do
return;
while (c);
}
''');
await assertHasFix('''
void f(bool c) {
return;
}
''', errorFilter: (err) => err.problemMessage.length == 10);
}
@failingTest
Future<void> test_for_returnInBody() async {
// https://github.com/dart-lang/sdk/issues/43511

View file

@ -518,9 +518,28 @@ class NullSafetyDeadCodeVerifier {
} else if (parent is BinaryExpression && node == parent.rightOperand) {
offset = parent.operator.offset;
}
if (parent is DoStatement) {
var doOffset = parent.doKeyword.offset;
var doEnd = parent.doKeyword.end;
var whileOffset = parent.whileKeyword.offset;
var whileEnd = parent.semicolon.end;
var body = parent.body;
if (body is Block) {
doEnd = body.leftBracket.end;
whileOffset = body.rightBracket.offset;
}
_errorReporter.reportErrorForOffset(
HintCode.DEAD_CODE, doOffset, doEnd - doOffset);
_errorReporter.reportErrorForOffset(
HintCode.DEAD_CODE, whileOffset, whileEnd - whileOffset);
offset = parent.semicolon.next!.offset;
}
var length = node.end - offset;
_errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length);
if (length > 0) {
_errorReporter.reportErrorForOffset(
HintCode.DEAD_CODE, offset, length);
}
}
_firstDeadNode = null;

View file

@ -30,6 +30,49 @@ void f(Object waldo) {
]);
}
test_doWhile() async {
await assertErrorsInCode(r'''
void f(bool c) {
do {
print(c);
return;
} while (c);
}
''', [
error(HintCode.DEAD_CODE, 19, 4),
error(HintCode.DEAD_CODE, 52, 12),
]);
}
test_doWhile_noBrackets() async {
await assertErrorsInCode(r'''
void f(bool c) {
do
return;
while (c);
}
''', [
error(HintCode.DEAD_CODE, 19, 2),
error(HintCode.DEAD_CODE, 36, 10),
]);
}
test_doWhile_statements() async {
await assertErrorsInCode(r'''
void f(bool c) {
do {
print(c);
return;
} while (c);
print('2');
}
''', [
error(HintCode.DEAD_CODE, 19, 4),
error(HintCode.DEAD_CODE, 52, 12),
error(HintCode.DEAD_CODE, 67, 11),
]);
}
test_flowEnd_tryStatement_body() async {
await assertErrorsInCode(r'''
Never foo() => throw 0;