Fix nullsafe FIXMES for Task.java and mark nullsafe (#50355)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50355

Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations.
Changelog: [Android][Fixed] Made Task.java nullsafe

Reviewed By: cortinico

Differential Revision: D71979582

fbshipit-source-id: f4104e5deb1d0538fe8b4968dc1411036a3e9634
This commit is contained in:
Gijs Weterings
2025-04-03 08:01:59 -07:00
committed by Facebook GitHub Bot
parent af4f0d0cff
commit eba9ebe0a9
2 changed files with 25 additions and 20 deletions
@@ -8,6 +8,8 @@
package com.facebook.react.runtime.internal.bolts;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.interfaces.TaskInterface;
import java.util.ArrayList;
import java.util.List;
@@ -21,6 +23,7 @@ import java.util.concurrent.TimeUnit;
*
* @param <TResult> The type of the result of the task.
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
public class Task<TResult> implements TaskInterface<TResult> {
/**
* An {@link java.util.concurrent.Executor} that executes tasks in the current thread unless the
@@ -75,18 +78,16 @@ public class Task<TResult> implements TaskInterface<TResult> {
private final Object lock = new Object();
private boolean complete;
private boolean cancelled;
// NULLSAFE_FIXME[Field Not Initialized]
private TResult result;
// NULLSAFE_FIXME[Field Not Initialized]
private Exception error;
private @Nullable TResult result;
private @Nullable Exception error;
private boolean errorHasBeenObserved;
// NULLSAFE_FIXME[Field Not Initialized]
private UnobservedErrorNotifier unobservedErrorNotifier;
private List<Continuation<TResult, Void>> continuations = new ArrayList<>();
private @Nullable UnobservedErrorNotifier unobservedErrorNotifier;
private @Nullable List<Continuation<TResult, Void>> continuations = new ArrayList<>();
/* package */ Task() {}
private Task(TResult result) {
private Task(@Nullable TResult result) {
trySetResult(result);
}
@@ -94,7 +95,6 @@ public class Task<TResult> implements TaskInterface<TResult> {
if (cancelled) {
trySetCancelled();
} else {
// NULLSAFE_FIXME[Parameter Not Nullable]
trySetResult(null);
}
}
@@ -139,7 +139,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
* @return The result of the task, if set. {@code null} otherwise.
*/
@Override
public TResult getResult() {
public @Nullable TResult getResult() {
synchronized (lock) {
return result;
}
@@ -149,13 +149,12 @@ public class Task<TResult> implements TaskInterface<TResult> {
* @return The error for the task, if set. {@code null} otherwise.
*/
@Override
public Exception getError() {
public @Nullable Exception getError() {
synchronized (lock) {
if (error != null) {
errorHasBeenObserved = true;
if (unobservedErrorNotifier != null) {
unobservedErrorNotifier.setObserved();
// NULLSAFE_FIXME[Field Not Nullable]
unobservedErrorNotifier = null;
}
}
@@ -180,10 +179,10 @@ public class Task<TResult> implements TaskInterface<TResult> {
* false} otherwise.
*/
@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public boolean waitForCompletion(long duration, TimeUnit timeUnit) throws InterruptedException {
public boolean waitForCompletion(long duration, @Nullable TimeUnit timeUnit)
throws InterruptedException {
synchronized (lock) {
if (!isCompleted()) {
if (!isCompleted() && timeUnit != null) {
lock.wait(timeUnit.toMillis(duration));
}
return isCompleted();
@@ -227,6 +226,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
return Task.cancelled();
}
if (task.isFaulted()) {
Assertions.assertNotNull(task.getError());
return Task.forError(task.getError());
}
return Task.forResult(null);
@@ -270,6 +270,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
synchronized (lock) {
completed = this.isCompleted();
if (!completed) {
Assertions.assertNotNull(continuations);
continuations.add(
new Continuation<TResult, Void>() {
@Override
@@ -307,6 +308,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
synchronized (lock) {
completed = this.isCompleted();
if (!completed) {
Assertions.assertNotNull(continuations);
continuations.add(
new Continuation<TResult, Void>() {
@Override
@@ -343,6 +345,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
@Override
public Task<TContinuationResult> then(Task<TResult> task) {
if (task.isFaulted()) {
Assertions.assertNotNull(task.getError());
return Task.forError(task.getError());
} else if (task.isCancelled()) {
return Task.cancelled();
@@ -374,6 +377,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
@Override
public Task<TContinuationResult> then(Task<TResult> task) {
if (task.isFaulted()) {
Assertions.assertNotNull(task.getError());
return Task.forError(task.getError());
} else if (task.isCancelled()) {
return Task.cancelled();
@@ -464,6 +468,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
if (task.isCancelled()) {
tcs.setCancelled();
} else if (task.isFaulted()) {
Assertions.assertNotNull(task.getError());
tcs.setError(task.getError());
} else {
tcs.setResult(task.getResult());
@@ -486,6 +491,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
private void runContinuations() {
synchronized (lock) {
Assertions.assertNotNull(continuations);
for (Continuation<TResult, ?> continuation : continuations) {
try {
continuation.then(this);
@@ -495,7 +501,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
throw new RuntimeException(e);
}
}
// NULLSAFE_FIXME[Field Not Nullable]
// only setting continuations to null in siutations where complete is set to true
continuations = null;
}
}
@@ -515,7 +521,7 @@ public class Task<TResult> implements TaskInterface<TResult> {
}
/** Sets the result on the Task if the Task hasn't already been completed. */
/* package */ boolean trySetResult(TResult result) {
/* package */ boolean trySetResult(@Nullable TResult result) {
synchronized (lock) {
if (complete) {
return false;
@@ -545,7 +551,6 @@ public class Task<TResult> implements TaskInterface<TResult> {
}
}
// NULLSAFE_FIXME[Parameter Not Nullable]
private static Task<?> TASK_NULL = new Task<>(null);
private static Task<Boolean> TASK_TRUE = new Task<>((Boolean) true);
private static Task<Boolean> TASK_FALSE = new Task<>((Boolean) false);
@@ -25,7 +25,7 @@ internal class TaskCompletionSource<TResult>() {
fun trySetResult(result: TResult?): Boolean = task.trySetResult(result)
/** Sets the error on the Task if the Task hasn't already been completed. */
fun trySetError(error: Exception?): Boolean = task.trySetError(error)
fun trySetError(error: Exception): Boolean = task.trySetError(error)
/** Sets the cancelled flag on the task, throwing if the Task has already been completed. */
fun setCancelled(): Unit {
@@ -42,7 +42,7 @@ internal class TaskCompletionSource<TResult>() {
}
/** Sets the error of the Task, throwing if the Task has already been completed. */
fun setError(error: Exception?): Unit {
fun setError(error: Exception): Unit {
if (!trySetError(error)) {
throw IllegalStateException("Cannot set the error on a completed task.")
}