fix for UNUSED_LOCAL_VARIABLE

see: https://github.com/dart-lang/sdk/issues/38361

Change-Id: I5329067d6f132393efd9194886713c30e1dafbfc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117205
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
pq 2019-09-14 13:45:44 +00:00 committed by commit-bot@chromium.org
parent 4512b22595
commit 4575e4df37
5 changed files with 134 additions and 5 deletions

View file

@ -323,6 +323,8 @@ class DartFixKind {
appliedTogetherMessage: "Remove all unused imports in this file");
static const REMOVE_UNUSED_LABEL =
const FixKind('REMOVE_UNUSED_LABEL', 50, "Remove unused label");
static const REMOVE_UNUSED_LOCAL_VARIABLE = const FixKind(
'REMOVE_UNUSED_LOCAL_VARIABLE', 50, "Remove unused local variable");
static const RENAME_TO_CAMEL_CASE =
const FixKind('RENAME_TO_CAMEL_CASE', 50, "Rename to '{0}'");
static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(

View file

@ -376,11 +376,9 @@ class FixProcessor extends BaseProcessor {
if (errorCode == HintCode.UNUSED_LABEL) {
await _addFix_removeUnusedLabel();
}
// TODO(brianwilkerson) Add a fix to remove the local variable, either with
// or without the initialization code.
// if (errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
// await _addFix_removeUnusedLocalVariable();
// }
if (errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
await _addFix_removeUnusedLocalVariable();
}
if (errorCode == HintCode.UNUSED_SHOWN_NAME) {
await _addFix_removeNameFromCombinator();
}
@ -3536,6 +3534,50 @@ class FixProcessor extends BaseProcessor {
}
}
Future<void> _addFix_removeUnusedLocalVariable() async {
final declaration = node.parent;
if (!(declaration is VariableDeclaration && declaration.name == node)) {
return;
}
Element element = (declaration as VariableDeclaration).declaredElement;
if (element is LocalElement) {
final functionBody = declaration.thisOrAncestorOfType<FunctionBody>();
final references = findLocalElementReferences(functionBody, element);
final changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
for (var reference in references) {
final node = reference.thisOrAncestorMatching((node) =>
node is VariableDeclaration || node is AssignmentExpression);
var sourceRange;
if (node is VariableDeclaration) {
VariableDeclarationList parent = node.parent;
if (parent.variables.length == 1) {
sourceRange = range.node(parent.parent);
} else {
sourceRange =
range.endEnd(node.beginToken.previous, node.endToken.next);
}
} else if (node is AssignmentExpression) {
// todo (pq): consider node.parent is! ExpressionStatement to handle
// assignments in parens, etc.
if (node.parent is ArgumentList) {
sourceRange =
range.endStart(node.beginToken.previous, node.operator.next);
} else {
sourceRange = range.node(node.parent);
}
} else {
return;
}
builder.addDeletion(utils.getLinesRange(sourceRange));
}
});
_addFixFromBuilder(
changeBuilder, DartFixKind.REMOVE_UNUSED_LOCAL_VARIABLE);
}
}
Future<void> _addFix_renameToCamelCase() async {
if (node is! SimpleIdentifier) {
return;

View file

@ -37,6 +37,7 @@ class FixesTest extends AbstractAnalysisTest {
addTestFile('''
main() {
Completer<String> x = null;
print(x);
}
''');
await waitForTasksFinished();

View file

@ -0,0 +1,82 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'fix_processor.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(RemoveUnusedLocalVariableTest);
});
}
@reflectiveTest
class RemoveUnusedLocalVariableTest extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.REMOVE_UNUSED_LOCAL_VARIABLE;
test_inArgumentList() async {
await resolveTestUnit(r'''
main() {
var v = 1;
print(v = 2);
}
''');
await assertHasFix(r'''
main() {
print(2);
}
''');
}
test_inDeclarationList() async {
await resolveTestUnit(r'''
main() {
var v = 1, v2 = 3;
v = 2;
print(v2);
}
''');
await assertHasFix(r'''
main() {
var v2 = 3;
print(v2);
}
''');
}
test_withReferences() async {
await resolveTestUnit(r'''
main() {
var v = 1;
v = 2;
}
''');
await assertHasFix(r'''
main() {
}
''');
}
test_withReferences_beforeDeclaration() async {
// CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION
verifyNoTestUnitErrors = false;
await resolveTestUnit(r'''
main() {
v = 2;
var v = 1;
}
''');
await assertHasFix(r'''
main() {
}
''',
errorFilter: (e) =>
e.errorCode != CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION);
}
}

View file

@ -104,6 +104,7 @@ import 'remove_unused_catch_clause_test.dart' as remove_unused_catch_clause;
import 'remove_unused_catch_stack_test.dart' as remove_unused_catch_stack;
import 'remove_unused_import_test.dart' as remove_unused_import;
import 'remove_unused_label_test.dart' as remove_unused_label;
import 'remove_unused_local_variable_test.dart' as remove_unused_local_variable;
import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
@ -221,6 +222,7 @@ main() {
remove_unused_catch_stack.main();
remove_unused_import.main();
remove_unused_label.main();
remove_unused_local_variable.main();
rename_to_camel_case.main();
replace_boolean_with_bool.main();
replace_colon_with_equals.main();