Skip to content

Commit 0c643e6

Browse files
authored
add CompletableFuture function parameters as nullable (spotbugs#3270)
* reproduce issue * add CompletableFuture functions params as acceptable nullable * add changelog entry
1 parent b264a5f commit 0c643e6

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Currently the versioning policy of this project follows [Semantic Versioning v2.
99

1010
### Fixed
1111
- Fixed the parsing of generics methods in `ThrowingExceptions` ([#3267](https://github.com/spotbugs/spotbugs/issues/3267))
12+
- Accept the 1st parameter of `java.util.concurrent.CompletableFuture`'s `completeOnTimeout()`, `getNow()` and `obtrudeValue()` functions as nullable ([#1001](https://github.com/spotbugs/spotbugs/issues/1001)).
1213

1314
## 4.9.0 - 2025-01-15
1415
### Added
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package edu.umd.cs.findbugs.nullness;
2+
3+
import edu.umd.cs.findbugs.AbstractIntegrationTest;
4+
import org.junit.jupiter.api.Test;
5+
6+
class NullableFutureTest extends AbstractIntegrationTest {
7+
@Test
8+
void testIssue() {
9+
performAnalysis("nullnessAnnotations/NullableFuture.class");
10+
assertNoBugType("NP_NONNULL_PARAM_VIOLATION");
11+
}
12+
13+
@Test
14+
void testIssue1397() {
15+
performAnalysis("../java11/ghIssues/Issue1397.class");
16+
assertNoBugType("NP_NONNULL_PARAM_VIOLATION");
17+
}
18+
}

spotbugs/src/main/java/edu/umd/cs/findbugs/ba/DefaultNullnessAnnotations.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@ public static void addDefaultNullnessAnnotations(INullnessAnnotationDatabase dat
234234
"(Ljava/lang/Object;)Ljava/util/concurrent/CompletableFuture;", true, 0, NullnessAnnotation.NULLABLE);
235235
database.addMethodParameterAnnotation("java.util.concurrent.CompletableFuture", "completedStage",
236236
"(Ljava/lang/Object;)Ljava/util/concurrent/CompletionStage;", true, 0, NullnessAnnotation.NULLABLE);
237+
database.addMethodParameterAnnotation("java.util.concurrent.CompletableFuture", "completeOnTimeout",
238+
"(Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Ljava/util/concurrent/CompletableFuture;", false, 0,
239+
NullnessAnnotation.NULLABLE);
240+
database.addMethodParameterAnnotation("java.util.concurrent.CompletableFuture", "getNow",
241+
"(Ljava/lang/Object;)Ljava/lang/Object;", false, 0, NullnessAnnotation.NULLABLE);
242+
database.addMethodParameterAnnotation("java.util.concurrent.CompletableFuture", "obtrudeValue",
243+
"(Ljava/lang/Object;)V", false, 0, NullnessAnnotation.NULLABLE);
237244

238245
database.addMethodParameterAnnotation("java.util.concurrent.ExecutionException", "<init>", "(Ljava/lang/String;)V",
239246
false, 0, NullnessAnnotation.CHECK_FOR_NULL);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package nullnessAnnotations;
2+
3+
import java.util.concurrent.CompletableFuture;
4+
import java.util.concurrent.TimeUnit;
5+
6+
/**
7+
* <blockquote>Arguments used to pass a completion result (that is, for parameters of type T) for methods accepting them may be null, but passing a null value for any other parameter will result in a NullPointerException being thrown.</blockquote>
8+
* @see CompletableFuture
9+
* @see <a href="https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CompletableFuture.html">CompletableFuture JDK9</a>
10+
*/
11+
public class NullableFuture {
12+
/**
13+
* @see <a href="https://github.com/spotbugs/spotbugs/issues/1001">GitHub issue #1001</a>
14+
*/
15+
public void getNow() {
16+
// 1st argument of CompletableFuture#getNow(T) should be nullable
17+
CompletableFuture<Object> future = new CompletableFuture<>();
18+
future.getNow(null);
19+
}
20+
21+
public void completeOnTimeout() {
22+
CompletableFuture<Object> future = new CompletableFuture<>();
23+
future.completeOnTimeout(null, 1L, TimeUnit.MINUTES);
24+
}
25+
26+
public void obtrudeValue() {
27+
CompletableFuture<Object> future = new CompletableFuture<>();
28+
future.obtrudeValue(null);
29+
}
30+
}

0 commit comments

Comments
 (0)