Skip to content

Commit f289d9e

Browse files
graememorganError Prone Team
authored and
Error Prone Team
committed
VoidUsed: flag Void variables being _used_, where they can simply be replaced with a literal null.
Findings here (unknown commit) before I fixed the bug with assignments. PiperOrigin-RevId: 627676095
1 parent 3ee6f41 commit f289d9e

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2024 The Error Prone Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.errorprone.bugpatterns;
18+
19+
import static com.google.common.collect.Sets.immutableEnumSet;
20+
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
21+
import static com.google.errorprone.matchers.Description.NO_MATCH;
22+
import static com.google.errorprone.suppliers.Suppliers.JAVA_LANG_VOID_TYPE;
23+
import static com.google.errorprone.util.ASTHelpers.getSymbol;
24+
import static com.google.errorprone.util.ASTHelpers.isSameType;
25+
import static javax.lang.model.element.ElementKind.FIELD;
26+
import static javax.lang.model.element.ElementKind.LOCAL_VARIABLE;
27+
import static javax.lang.model.element.ElementKind.PARAMETER;
28+
29+
import com.google.common.collect.ImmutableSet;
30+
import com.google.errorprone.BugPattern;
31+
import com.google.errorprone.VisitorState;
32+
import com.google.errorprone.bugpatterns.BugChecker.IdentifierTreeMatcher;
33+
import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;
34+
import com.google.errorprone.fixes.SuggestedFix;
35+
import com.google.errorprone.matchers.Description;
36+
import com.sun.source.tree.AssignmentTree;
37+
import com.sun.source.tree.IdentifierTree;
38+
import com.sun.source.tree.MemberSelectTree;
39+
import com.sun.source.tree.Tree;
40+
import javax.lang.model.element.ElementKind;
41+
42+
/** A BugPattern; see the summary. */
43+
@BugPattern(
44+
summary =
45+
"Using a Void-typed variable is potentially confusing, and can be replaced with a literal"
46+
+ " `null`.",
47+
severity = WARNING)
48+
public final class VoidUsed extends BugChecker
49+
implements IdentifierTreeMatcher, MemberSelectTreeMatcher {
50+
@Override
51+
public Description matchIdentifier(IdentifierTree tree, VisitorState state) {
52+
return handle(tree, state);
53+
}
54+
55+
@Override
56+
public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {
57+
return handle(tree, state);
58+
}
59+
60+
private Description handle(Tree tree, VisitorState state) {
61+
var parent = state.getPath().getParentPath().getLeaf();
62+
if (parent instanceof AssignmentTree && ((AssignmentTree) parent).getVariable().equals(tree)) {
63+
return NO_MATCH;
64+
}
65+
var symbol = getSymbol(tree);
66+
if (symbol == null
67+
|| !KINDS.contains(symbol.getKind())
68+
|| !isSameType(symbol.type, JAVA_LANG_VOID_TYPE.get(state), state)) {
69+
return NO_MATCH;
70+
}
71+
return describeMatch(tree, SuggestedFix.replace(tree, "null"));
72+
}
73+
74+
private static final ImmutableSet<ElementKind> KINDS =
75+
immutableEnumSet(PARAMETER, LOCAL_VARIABLE, FIELD);
76+
}

core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@
434434
import com.google.errorprone.bugpatterns.VarTypeName;
435435
import com.google.errorprone.bugpatterns.VariableNameSameAsType;
436436
import com.google.errorprone.bugpatterns.Varifier;
437+
import com.google.errorprone.bugpatterns.VoidUsed;
437438
import com.google.errorprone.bugpatterns.WaitNotInLoop;
438439
import com.google.errorprone.bugpatterns.WildcardImport;
439440
import com.google.errorprone.bugpatterns.WithSignatureDiscouraged;
@@ -1094,6 +1095,7 @@ public static ScannerSupplier warningChecks() {
10941095
UnusedVariable.class,
10951096
UseBinds.class,
10961097
VariableNameSameAsType.class,
1098+
VoidUsed.class,
10971099
WaitNotInLoop.class,
10981100
WakelockReleasedDangerously.class,
10991101
WithSignatureDiscouraged.class
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2024 The Error Prone Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.errorprone.bugpatterns;
18+
19+
import com.google.errorprone.CompilationTestHelper;
20+
import org.junit.Test;
21+
import org.junit.runner.RunWith;
22+
import org.junit.runners.JUnit4;
23+
24+
@RunWith(JUnit4.class)
25+
public final class VoidUsedTest {
26+
private final CompilationTestHelper helper =
27+
CompilationTestHelper.newInstance(VoidUsed.class, getClass());
28+
29+
@Test
30+
public void positive() {
31+
helper
32+
.addSourceLines(
33+
"Test.java", //
34+
"class Test {",
35+
" void test(Void v) {",
36+
" // BUG: Diagnostic contains: null",
37+
" System.out.println(v);",
38+
" }",
39+
"}")
40+
.doTest();
41+
}
42+
43+
@Test
44+
public void notVoid_noFinding() {
45+
helper
46+
.addSourceLines(
47+
"Test.java", //
48+
"class Test {",
49+
" void test(Integer v) {",
50+
" System.out.println(v);",
51+
" }",
52+
"}")
53+
.doTest();
54+
}
55+
56+
@Test
57+
public void assignedTo_noFinding() {
58+
helper
59+
.addSourceLines(
60+
"Test.java", //
61+
"class Test {",
62+
" void test(Void v) {",
63+
" v = null;",
64+
" }",
65+
"}")
66+
.doTest();
67+
}
68+
}

0 commit comments

Comments
 (0)