Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.matchers.UnusedReturnValueMatcher;
import com.google.errorprone.util.SourceVersion;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LambdaExpressionTree;
Expand Down Expand Up @@ -337,18 +338,23 @@ && matchingMethods(
if (parent instanceof ExpressionStatementTree
&& constantExpressions.constantExpression(invocationTree, state).isEmpty()
&& considerBlanketFixes) {
ImmutableSet<String> identifiersInScope =
findAllIdents(state).stream().map(v -> v.name.toString()).collect(toImmutableSet());
concat(Stream.of("unused"), range(2, 10).mapToObj(i -> "unused" + i))
// TODO(b/72928608): Handle even local variables declared *later* within this scope.
// TODO(b/250568455): Also check whether we have suggested this name before in this scope.
.filter(n -> !identifiersInScope.contains(n))
.findFirst()
.ifPresent(
n ->
fixes.put(
"Suppress error by assigning to a variable",
prefixWith(parent, format("var %s = ", n))));
if (SourceVersion.supportsUnnamedVariablesAndPatterns(state.context)) {
fixes.put("Suppress error by assigning to a variable", prefixWith(parent, "var _ = "));
} else {
ImmutableSet<String> identifiersInScope =
findAllIdents(state).stream().map(v -> v.name.toString()).collect(toImmutableSet());
concat(Stream.of("unused"), range(2, 10).mapToObj(i -> "unused" + i))
// TODO(b/72928608): Handle even local variables declared *later* within this scope.
// TODO(b/250568455): Also check whether we have suggested this name before in this
// scope.
.filter(n -> !identifiersInScope.contains(n))
.findFirst()
.ifPresent(
n ->
fixes.put(
"Suppress error by assigning to a variable",
prefixWith(parent, format("var %s = ", n))));
}
}
if (parent instanceof ExpressionStatementTree && considerBlanketFixes) {
if (constantExpressions.constantExpression(invocationTree, state).isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.google.errorprone.util.SourceVersion;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
Expand Down Expand Up @@ -329,7 +330,10 @@ public Description matchClass(ClassTree tree, VisitorState state) {

private Description describeInvocationResultIgnored(
ExpressionTree invocationTree, String shortCall, MethodSymbol symbol, VisitorState state) {
String assignmentToUnused = "var unused = ...";
String assignmentToUnused =
SourceVersion.supportsUnnamedVariablesAndPatterns(state.context)
? "var _ = ..."
: "var unused = ...";
String message =
invocationResultIgnored(shortCall, assignmentToUnused, apiTrailer(symbol, state));
return buildDescription(invocationTree)
Expand Down Expand Up @@ -373,7 +377,11 @@ protected Description describeReturnValueIgnored(MemberReferenceTree tree, Visit
+ "."
+ state.getTypes().findDescriptorSymbol(getType(tree).asElement()).getSimpleName();
String methodReference = state.getSourceForNode(tree);
String assignmentLambda = parensAndMaybeEllipsis + " -> { var unused = ...; }";
String assignmentLambda =
parensAndMaybeEllipsis
+ (SourceVersion.supportsUnnamedVariablesAndPatterns(state.context)
? " -> { var _ = ...; }"
: " -> { var unused = ...; }");
String message =
methodReferenceIgnoresResult(
shortCall,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public Description matchVariable(VariableTree tree, VisitorState state) {
|| hasImplicitType(tree, state)) {
return NO_MATCH;
}
// Foo unused = ...;
if (symbol.getSimpleName().contentEquals("unused")) {
// Foo unused = ...; or Foo _ = ...;
if (symbol.getSimpleName().contentEquals("unused") || symbol.getSimpleName().isEmpty()) {
return fix(tree);
}
// MyException exception = assertThrows(MyException.class, () -> ...);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.errorprone.bugpatterns;

import static com.google.common.truth.TruthJUnit.assume;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Joiner;
Expand Down Expand Up @@ -47,6 +48,11 @@ public class CheckReturnValueTest {

@Test
public void positiveCases() {
/*
* TODO(cpovirk): Split or otherwise modify this test to work when run under Java 21, where we
* suggest `var unused =` instead of `var _ =`.
*/
assume().that(Runtime.version().feature()).isAtLeast(22);
compilationHelper
.addSourceLines(
"CheckReturnValuePositiveCases.java",
Expand All @@ -72,7 +78,7 @@ public void foo() {
int i = 1;
// BUG: Diagnostic contains: The result of `increment(...)` must be used
//
// If you really don't want to use the result, then assign it to a variable: `var unused = ...`.
// If you really don't want to use the result, then assign it to a variable: `var _ = ...`.
//
// If callers of `increment(...)` shouldn't be required to use its result, then annotate it with
// `@CanIgnoreReturnValue`.
Expand Down Expand Up @@ -109,7 +115,7 @@ public void testResolvedToVoidMethodReference(boolean predicate) {
// To use the result, you may need to restructure your code.
//
// If you really don't want to use the result, then switch to a lambda that assigns it to a
// variable: `() -> { var unused = ...; }`.
// variable: `() -> { var _ = ...; }`.
//
// If callers of `increment()` shouldn't be required to use its result, then annotate it with
// `@CanIgnoreReturnValue`.
Expand All @@ -127,7 +133,7 @@ public void testConstructorResolvedToVoidMethodReference() {
// To use the result, you may need to restructure your code.
//
// If you really don't want to use the result, then switch to a lambda that assigns it to a
// variable: `() -> { var unused = ...; }`.
// variable: `() -> { var _ = ...; }`.
//
// If callers of `MyObject()` shouldn't be required to use its result, then annotate it with
// `@CanIgnoreReturnValue`.
Expand Down Expand Up @@ -167,7 +173,7 @@ class MySubObject3 extends MyObject {

// BUG: Diagnostic contains: The result of `new MyObject()` must be used
//
// If you really don't want to use the result, then assign it to a variable: `var unused = ...`.
// If you really don't want to use the result, then assign it to a variable: `var _ = ...`.
//
// If callers of `MyObject()` shouldn't be required to use its result, then annotate it with
// `@CanIgnoreReturnValue`.
Expand Down Expand Up @@ -1382,6 +1388,11 @@ String makeBarOrThrow() {

@Test
public void doesNotSuggestCanIgnoreReturnValueForOtherFile() {
/*
* This is the one test of introducing an unused variable that we run targeting Java 22+ to test
* that we suggest `var unused =` instead of `var _ =` there.
*/
assume().that(Runtime.version().feature()).isAtLeast(22);
refactoringHelper
.addInputLines(
"Lib.java",
Expand Down Expand Up @@ -1417,7 +1428,7 @@ void foo(Lib l) {
@CheckReturnValue
class Test {
void foo(Lib l) {
var unused = l.makeBarOrThrow();
var _ = l.makeBarOrThrow();
}
}
""")
Expand All @@ -1427,6 +1438,7 @@ void foo(Lib l) {
@Test
public void suggestsVarUnusedForConstructor() {
refactoringHelper
.setArgs("-source", "21")
.addInputLines(
"Test.java",
"""
Expand All @@ -1453,6 +1465,7 @@ void go() {
@Test
public void suggestsVarUnused2() {
refactoringHelper
.setArgs("-source", "21")
.addInputLines(
"Lib.java",
"""
Expand Down Expand Up @@ -1492,6 +1505,7 @@ void foo(Lib lib) {
@Test
public void inheritsCanIgnoreReturnValue() {
refactoringHelper
.setArgs("-source", "21")
.addInputLines(
"Super.java",
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ public void proto_buildPartial() {
@Test
public void refactoringDeletesConstantExpressionCall() {
refactoringHelper
.setArgs("-source", "21")
.addInputLines(
"Test.java",
"""
Expand Down Expand Up @@ -825,6 +826,7 @@ void f(Optional<Integer> o) {
@Test
public void refactoringDoesNotAssignToOriginalForTypeArgumentMismatch() {
refactoringHelper
.setArgs("-source", "21")
.addInputLines(
"Test.java",
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.google.errorprone.bugpatterns;

import static com.google.common.truth.TruthJUnit.assume;

import com.google.errorprone.BugCheckerRefactoringTestHelper;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -420,4 +422,29 @@ void test() {
.expectUnchanged()
.doTest();
}

@Test
public void varUnnamed() {
assume().that(Runtime.version().feature()).isAtLeast(22);
refactoringHelper
.addInputLines(
"Test.java",
"""
class Test {
public void trim(String string) {
String _ = string.trim();
}
}
""")
.addOutputLines(
"Test.java",
"""
class Test {
public void trim(String string) {
var _ = string.trim();
}
}
""")
.doTest();
}
}
Loading