Issue 52175. Support for ConstructorDeclaration in 'Remove unused element' quick fix.

Bug: https://github.com/dart-lang/sdk/issues/52175
Change-Id: I7c5a237fc9a358488e4431d4785ec51b0322f66a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298800
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-04-27 16:00:12 +00:00 committed by Commit Queue
parent 63bc3a685e
commit 58e48de282
2 changed files with 126 additions and 14 deletions

View file

@ -10,6 +10,7 @@ import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@ -30,32 +31,41 @@ class RemoveUnusedElement extends _RemoveUnused {
Future<void> compute(ChangeBuilder builder) async {
final sourceRanges = <SourceRange>[];
final referencedNode = node;
if (referencedNode is ClassDeclaration ||
referencedNode is EnumDeclaration ||
referencedNode is FunctionDeclaration ||
referencedNode is FunctionTypeAlias ||
referencedNode is MethodDeclaration ||
referencedNode is VariableDeclaration) {
final element = referencedNode is Declaration
? referencedNode.declaredElement!
: (referencedNode as NamedCompilationUnitMember).declaredElement!;
final node = this.node;
if (node is ConstructorDeclaration) {
await _constructorDeclaration(
builder: builder,
node: node,
);
return;
}
if (node is ClassDeclaration ||
node is EnumDeclaration ||
node is FunctionDeclaration ||
node is FunctionTypeAlias ||
node is MethodDeclaration ||
node is VariableDeclaration) {
final element = node is Declaration
? node.declaredElement!
: (node as NamedCompilationUnitMember).declaredElement!;
final references = _findAllReferences(unit, element);
// todo (pq): consider filtering for references that are limited to within the class.
if (references.isEmpty) {
var parent = referencedNode.parent;
var parent = node.parent;
var grandParent = parent?.parent;
SourceRange sourceRange;
if (referencedNode is VariableDeclaration &&
if (node is VariableDeclaration &&
parent is VariableDeclarationList &&
grandParent != null) {
if (parent.variables.length == 1) {
sourceRange = utils.getLinesRange(range.node(grandParent));
} else {
sourceRange = range.nodeInList(parent.variables, referencedNode);
sourceRange = range.nodeInList(parent.variables, node);
}
} else {
sourceRange = utils.getLinesRange(range.node(referencedNode));
sourceRange = utils.getLinesRange(range.node(node));
}
sourceRanges.add(sourceRange);
}
@ -67,6 +77,27 @@ class RemoveUnusedElement extends _RemoveUnused {
}
});
}
Future<void> _constructorDeclaration({
required ChangeBuilder builder,
required ConstructorDeclaration node,
}) async {
final NodeList<ClassMember> members;
switch (node.parent) {
case ClassDeclaration classDeclaration:
members = classDeclaration.members;
case EnumDeclaration enumDeclaration:
members = enumDeclaration.members;
case _:
return;
}
final nodeRange = range.nodeInList(members, node);
await builder.addDartFileEdit(file, (builder) {
builder.addDeletion(nodeRange);
});
}
}
class RemoveUnusedField extends _RemoveUnused {

View file

@ -21,6 +21,55 @@ class RemoveUnusedElementTest extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.REMOVE_UNUSED_ELEMENT;
Future<void> test_class_constructor_first() async {
await resolveTestCode(r'''
class A {
A._named();
A();
}
''');
await assertHasFix(r'''
class A {
A();
}
''');
}
Future<void> test_class_constructor_last() async {
await resolveTestCode(r'''
class A {
A();
A._named();
}
''');
await assertHasFix(r'''
class A {
A();
}
''');
}
Future<void> test_class_constructor_middle() async {
await resolveTestCode(r'''
class A {
A();
A._named();
void foo() {}
}
''');
await assertHasFix(r'''
class A {
A();
void foo() {}
}
''');
}
Future<void> test_class_notUsed_inClassMember() async {
await resolveTestCode(r'''
class _A {
@ -55,6 +104,38 @@ class _A {
''');
}
Future<void> test_enum_constructor_first() async {
await resolveTestCode(r'''
enum E {
v;
const E._named();
const E();
}
''');
await assertHasFix(r'''
enum E {
v;
const E();
}
''');
}
Future<void> test_enum_constructor_last() async {
await resolveTestCode(r'''
enum E {
v;
const E();
const E._named();
}
''');
await assertHasFix(r'''
enum E {
v;
const E();
}
''');
}
Future<void> test_enum_notUsed_noReference() async {
await resolveTestCode(r'''
enum _MyEnum {A, B, C}