diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/ReturnValueIgnored.java b/core/src/main/java/com/google/errorprone/bugpatterns/ReturnValueIgnored.java index cf171465eda2..ca9970af4dff 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/ReturnValueIgnored.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/ReturnValueIgnored.java @@ -204,8 +204,16 @@ private static boolean functionalMethod(ExpressionTree tree, VisitorState state) private static final Matcher OPTIONAL_METHODS = anyOf( staticMethod().onClass("java.util.Optional"), + instanceMethod().onExactClass("java.util.Optional").named("filter"), + instanceMethod().onExactClass("java.util.Optional").named("flatMap"), + instanceMethod().onExactClass("java.util.Optional").named("get"), + instanceMethod().onExactClass("java.util.Optional").named("isEmpty"), instanceMethod().onExactClass("java.util.Optional").named("isPresent"), - instanceMethod().onExactClass("java.util.Optional").named("isEmpty")); + instanceMethod().onExactClass("java.util.Optional").named("map"), + instanceMethod().onExactClass("java.util.Optional").named("or"), + instanceMethod().onExactClass("java.util.Optional").named("orElse"), + instanceMethod().onExactClass("java.util.Optional").named("orElseGet"), + instanceMethod().onExactClass("java.util.Optional").named("orElseThrow")); /** * The return values of {@link java.util.concurrent.TimeUnit} methods should always be checked. diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java index 43eeadcbb0d8..214a630e97d8 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/ReturnValueIgnoredTest.java @@ -17,10 +17,13 @@ package com.google.errorprone.bugpatterns; import com.google.errorprone.CompilationTestHelper; +import com.google.errorprone.util.RuntimeVersion; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import static org.junit.Assume.assumeTrue; + /** @author alexeagle@google.com (Alex Eagle) */ @RunWith(JUnit4.class) public class ReturnValueIgnoredTest { @@ -139,42 +142,104 @@ public void javaTime() { "}") .doTest(); } - @Test public void optionalStaticMethods() { compilationHelper - .addSourceLines( - "Test.java", - "import java.util.Optional;", - "class Test {", - " void optional() {", - " // BUG: Diagnostic contains: ReturnValueIgnored", - " Optional.empty();", - " // BUG: Diagnostic contains: ReturnValueIgnored", - " Optional.of(42);", - " // BUG: Diagnostic contains: ReturnValueIgnored", - " Optional.ofNullable(null);", - " }", - "}") - .doTest(); + .addSourceLines( + "Test.java", + "import java.util.Optional;", + "class Test {", + " void optional() {", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " Optional.empty();", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " Optional.of(42);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " Optional.ofNullable(null);", + " }", + "}") + .doTest(); } @Test public void optionalInstanceMethods() { compilationHelper - .addSourceLines( - "Test.java", - "import java.util.Optional;", - "class Test {", - " void optional() {", - " Optional optional = Optional.of(42);", - " // BUG: Diagnostic contains: ReturnValueIgnored", - " optional.isPresent();", - " optional.filter(v -> v > 40);", - " optional.map(v -> Integer.toString(v));", - " }", - "}") - .doTest(); + .addSourceLines( + "Test.java", + "import java.util.Optional;", + "class Test {", + " void optional() {", + " Optional optional = Optional.of(42);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.filter(v -> v > 40);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.flatMap(v -> Optional.of(v + 1));", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.get();", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.isPresent();", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.map(v -> v + 1);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.orElse(40);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.orElseGet(() -> 40);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.orElseThrow(() -> new RuntimeException());", + " }", + "}") + .doTest(); + } + + @Test + public void optionalInstanceMethods_jdk9() { + assumeTrue(RuntimeVersion.isAtLeast9()); + compilationHelper + .addSourceLines( + "Test.java", + "import java.util.Optional;", + "class Test {", + " void optional() {", + " Optional optional = Optional.of(42);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.or(() -> Optional.empty());", + " }", + "}") + .doTest(); + } + + @Test + public void optionalInstanceMethods_jdk10() { + assumeTrue(RuntimeVersion.isAtLeast10()); + compilationHelper + .addSourceLines( + "Test.java", + "import java.util.Optional;", + "class Test {", + " void optional() {", + " Optional optional = Optional.of(42);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.orElseThrow();", + " }", + "}") + .doTest(); + } + + @Test + public void optionalInstanceMethods_jdk11() { + assumeTrue(RuntimeVersion.isAtLeast11()); + compilationHelper + .addSourceLines( + "Test.java", + "import java.util.Optional;", + "class Test {", + " void optional() {", + " Optional optional = Optional.of(42);", + " // BUG: Diagnostic contains: ReturnValueIgnored", + " optional.isEmpty();", + " }", + "}") + .doTest(); } @Test