mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 08:44:27 +00:00
[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:
parent
20218dfe15
commit
7432006bd7
4 changed files with 192 additions and 3 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue