Skip to content

Commit fef0045

Browse files
author
shaark
committed
issue-93. added more test case
1 parent 25e51c7 commit fef0045

17 files changed

+162
-35
lines changed

lib/src/lints/consider_making_a_member_private/consider_making_a_member_private_rule.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,18 @@ class ConsiderMakingAMemberPrivateRule extends SolidLintRule {
6969
node.visitChildren(visitor);
7070

7171
final unusedMembers = visitor.unusedPublicMembers;
72+
final unusedGlobalVariables = visitor.unusedGlobalVariables;
73+
final unusedGlobalFunctions = visitor.unusedGlobalFunctions;
7274

7375
for (final member in unusedMembers) {
7476
reporter.atNode(member, code);
7577
}
78+
for (final variable in unusedGlobalVariables) {
79+
reporter.atNode(variable, code);
80+
}
81+
for (final function in unusedGlobalFunctions) {
82+
reporter.atNode(function, code);
83+
}
7684
});
7785
}
7886
}

lib/src/lints/consider_making_a_member_private/visitor/consider_making_a_member_private_visitor.dart

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,48 @@
2424
import 'package:analyzer/dart/ast/ast.dart';
2525
import 'package:analyzer/dart/ast/visitor.dart';
2626

27-
/// The AST visitor that will find lines with code.
27+
/// AST Visitor for identifying unused public members, global functions,
28+
/// and variables.
2829
class ConsiderMakingAMemberPrivateVisitor extends RecursiveAstVisitor<void> {
2930
final CompilationUnit _node;
3031

3132
final _unusedPublicMembers = <ClassMember>{};
33+
final _unusedGlobalFunctions = <FunctionDeclaration>{};
34+
final _unusedGlobalVariables = <VariableDeclaration>{};
3235

33-
/// Returns public members that are not used as representatives of the class.
36+
/// Returns unused public members of classes.
3437
Iterable<ClassMember> get unusedPublicMembers => _unusedPublicMembers;
3538

36-
/// Creates a new instance of [ConsiderMakingAMemberPrivateVisitor].
39+
/// Returns unused global functions.
40+
Iterable<FunctionDeclaration> get unusedGlobalFunctions =>
41+
_unusedGlobalFunctions;
42+
43+
/// Returns unused global variables.
44+
Iterable<VariableDeclaration> get unusedGlobalVariables =>
45+
_unusedGlobalVariables;
46+
47+
/// Constructor for [ConsiderMakingAMemberPrivateVisitor]
3748
ConsiderMakingAMemberPrivateVisitor(this._node);
3849

3950
@override
4051
void visitClassDeclaration(ClassDeclaration node) {
52+
// Check for unused public members in a class.
4153
final classMembers = node.members.where((member) {
4254
if (member is MethodDeclaration || member is FieldDeclaration) {
4355
final name = _getMemberName(member);
4456
return name != null && !_isPrivate(name);
4557
}
58+
if (member is ConstructorDeclaration) {
59+
final name = _getMemberName(member);
60+
if (name == null) return true;
61+
62+
return !_isPrivate(name);
63+
}
4664
return false;
4765
}).toList();
4866

4967
for (final member in classMembers) {
50-
final memberName = _getMemberName(member)!;
68+
final memberName = _getMemberName(member);
5169
if (!_isUsedOutsideClass(memberName, node)) {
5270
_unusedPublicMembers.add(member);
5371
}
@@ -56,54 +74,105 @@ class ConsiderMakingAMemberPrivateVisitor extends RecursiveAstVisitor<void> {
5674
super.visitClassDeclaration(node);
5775
}
5876

59-
bool _isPrivate(String name) => name.startsWith('_');
77+
@override
78+
void visitFunctionDeclaration(FunctionDeclaration node) {
79+
final name = node.declaredElement?.name;
80+
if (!_isPrivate(name) && !_isUsedEntity(name)) {
81+
_unusedGlobalFunctions.add(node);
82+
}
83+
super.visitFunctionDeclaration(node);
84+
}
85+
86+
@override
87+
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
88+
for (final variable in node.variables.variables) {
89+
final name = variable.declaredElement?.name;
90+
if (!_isPrivate(name) && !_isUsedEntity(name)) {
91+
_unusedGlobalVariables.add(variable);
92+
}
93+
}
94+
super.visitTopLevelVariableDeclaration(node);
95+
}
96+
97+
bool _isPrivate(String? name) => name?.startsWith('_') ?? false;
6098

6199
String? _getMemberName(ClassMember member) {
62100
if (member is MethodDeclaration) return member.declaredElement?.name;
63101
if (member is FieldDeclaration) {
64102
final fields = member.fields.variables;
65103
return fields.isNotEmpty ? fields.first.declaredElement?.name : null;
66104
}
105+
if (member is ConstructorDeclaration) {
106+
return member.declaredElement?.name;
107+
}
67108
return null;
68109
}
69110

70-
bool _isUsedOutsideClass(String memberName, ClassDeclaration classNode) {
111+
bool _isUsedOutsideClass(String? memberName, ClassDeclaration classNode) {
71112
bool isUsedOutside = false;
72113

73114
_node.visitChildren(
74-
_PublicMemberUsageVisitor(
75-
memberName: memberName,
76-
classNode: classNode,
115+
_GlobalEntityUsageVisitor(
116+
entityName: memberName!,
77117
onUsageFound: () {
78118
isUsedOutside = true;
79119
},
80120
),
81121
);
82122

123+
if (memberName.isEmpty) return true;
124+
83125
return isUsedOutside;
84126
}
127+
128+
bool _isUsedEntity(String? entityName) {
129+
bool isUsed = false;
130+
131+
if (entityName == null) return false;
132+
133+
_node.visitChildren(
134+
_GlobalEntityUsageVisitor(
135+
entityName: entityName,
136+
onUsageFound: () {
137+
isUsed = true;
138+
},
139+
),
140+
);
141+
142+
return isUsed;
143+
}
85144
}
86145

87-
class _PublicMemberUsageVisitor extends RecursiveAstVisitor<void> {
88-
final String memberName;
89-
final ClassDeclaration classNode;
146+
class _GlobalEntityUsageVisitor extends RecursiveAstVisitor<void> {
147+
final String entityName;
90148
final Function() onUsageFound;
91149

92-
_PublicMemberUsageVisitor({
93-
required this.memberName,
94-
required this.classNode,
150+
_GlobalEntityUsageVisitor({
151+
required this.entityName,
95152
required this.onUsageFound,
96153
});
97154

98155
@override
99156
void visitSimpleIdentifier(SimpleIdentifier identifier) {
100-
if (identifier.name == memberName) {
101-
final parentClass = identifier.thisOrAncestorOfType<ClassDeclaration>();
102-
if (parentClass != classNode) {
103-
onUsageFound();
104-
}
157+
if (identifier.name == entityName) {
158+
onUsageFound();
105159
}
106-
107160
super.visitSimpleIdentifier(identifier);
108161
}
162+
163+
@override
164+
void visitInstanceCreationExpression(InstanceCreationExpression node) {
165+
if (node.constructorName.name?.name == entityName) {
166+
onUsageFound();
167+
}
168+
super.visitInstanceCreationExpression(node);
169+
}
170+
171+
@override
172+
void visitMethodInvocation(MethodInvocation node) {
173+
if (node.target != null && node.target.toString() == entityName) {
174+
onUsageFound();
175+
}
176+
super.visitMethodInvocation(node);
177+
}
109178
}

lint_test/avoid_debug_print_in_release_test/avoid_debug_print_in_release_prefix_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: unused_local_variable
1+
// ignore_for_file: unused_local_variable, consider_making_a_member_private
22

33
import 'package:flutter/foundation.dart' as f;
44

lint_test/avoid_debug_print_in_release_test/avoid_debug_print_in_release_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: unused_local_variable
1+
// ignore_for_file: unused_local_variable, consider_making_a_member_private
22

33
import 'package:flutter/foundation.dart';
44

lint_test/avoid_unnecessary_type_assertions_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: prefer_const_declarations, prefer_match_file_name, cyclomatic_complexity, unused_element
1+
// ignore_for_file: prefer_const_declarations, prefer_match_file_name, cyclomatic_complexity, unused_element, consider_making_a_member_private
22
// ignore_for_file: unnecessary_nullable_for_final_variable_declarations
33
// ignore_for_file: unnecessary_type_check
44
// ignore_for_file: unused_local_variable

lint_test/avoid_unnecessary_type_casts_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: prefer_const_declarations
1+
// ignore_for_file: prefer_const_declarations, consider_making_a_member_private
22
// ignore_for_file: unnecessary_nullable_for_final_variable_declarations
33
// ignore_for_file: unnecessary_cast
44
// ignore_for_file: unused_local_variable

lint_test/avoid_unrelated_type_assertions_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: prefer_const_declarations, prefer_match_file_name, unused_element
1+
// ignore_for_file: prefer_const_declarations, prefer_match_file_name, unused_element, consider_making_a_member_private
22
// ignore_for_file: unnecessary_nullable_for_final_variable_declarations
33
// ignore_for_file: unused_local_variable
44

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
//ignore_for_file:consider_making_a_member_private
12
// expect_lint: avoid_global_state
23
int banned = 5;
Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,65 @@
1-
// ignore_for_file: no_empty_block, prefer_match_file_name, unused_element, member_ordering
1+
// ignore_for_file: no_empty_block, prefer_match_file_name, unused_element, member_ordering, avoid_global_state, avoid_unused_parameters
22
/// Check the `consider_making_a_member_private` rule
33
///
44
5+
// expect_lint:consider_making_a_member_private
6+
const int unusedGlobalVariables = 0;
7+
8+
//no lint
9+
const int usedGlobalVariables = 0;
10+
11+
// expect_lint:consider_making_a_member_private
12+
void unusedGLobalFunction() {}
13+
14+
//no lint
15+
void usedGLobalFunction() {}
16+
517
class X {
618
// expect_lint:consider_making_a_member_private
719
void unusedX() {}
820

9-
// no lint
10-
void usedX() {}
21+
// expect_lint:consider_making_a_member_private
22+
final int unusedFinalX = 0;
23+
// expect_lint:consider_making_a_member_private
24+
static final int unusedStaticX = 0;
25+
26+
// expect_lint:consider_making_a_member_private
27+
int unusedMutableX = 0;
28+
29+
// expect_lint:consider_making_a_member_private
30+
int get unusedGetX => 0;
31+
32+
// expect_lint:consider_making_a_member_private
33+
set unusedSetX(int y) {}
34+
35+
// no lint
36+
void usedMethodX() {}
37+
38+
// expect_lint:consider_making_a_member_private
39+
static void unusedStaticMethodX() {}
40+
41+
// no lint
42+
X();
43+
44+
// expect_lint:consider_making_a_member_private
45+
X.withValue({
46+
required this.unusedMutableX,
47+
});
48+
49+
// expect_lint:consider_making_a_member_private
50+
factory X.factory() => X();
51+
52+
// no lint
53+
factory X.usedFactory() => X();
1154
}
1255

1356
class Y {
1457
// no lint
1558
void _y() {
1659
final x = X();
17-
x.usedX();
60+
X.usedFactory();
61+
x.usedMethodX();
62+
usedGLobalFunction();
63+
usedGlobalVariables;
1864
}
1965
}

lint_test/no_equal_then_else_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: unused_local_variable
1+
// ignore_for_file: unused_local_variable, consider_making_a_member_private
22
// ignore_for_file: cyclomatic_complexity
33
// ignore_for_file: no_magic_number
44
// ignore_for_file: prefer_conditional_expressions

0 commit comments

Comments
 (0)