Skip to content

Commit ee680cb

Browse files
cpovirkGoogle Java Core Libraries
authored andcommitted
Use JSpecify annotations in the public release.
We've been using these internally for over a year. With JSpecify 1.0 not far off and wider adoption to gradually follow, now seems like the time to expand our public usage of the annotations. We've already been using them in a few projects, but Truth may become the mostly widely used project that users actually link against to use them. At the same time, it's a library that's used only in testing code, so the stakes remain relatively low. Most users will see no effect from this change, since most users don't use nullness checking and since we already used some nullness annotations in our public release. The main effect users are likely to see is if they pass nullable values for parameters that are now recognized as non-nullable. Under Kotlin, the effect should normally be a warning, not an error, at least until [Kotlin 2.1 or so](https://youtrack.jetbrains.com/issue/KT-55586/Handle-nullability-from-jspecify-annotations-properly#focus=Comments-27-8368666.0-0). Please still [report any problems](https://github.com/google/truth/issues/new). (progress toward JSpecify adoption in our projects in general, including google/guava#2960) RELNOTES=Added more nullness information to our APIs (in the form of [JSpecify](https://jspecify.dev/) annotations). This could lead to additional warnings (or even errors) for users of Kotlin and other nullness checkers. Please [report any problems](https://github.com/google/truth/issues/new). PiperOrigin-RevId: 647012817
1 parent d39e722 commit ee680cb

File tree

92 files changed

+198
-88
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+198
-88
lines changed

core/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
<artifactId>guava</artifactId>
1616
</dependency>
1717
<dependency>
18-
<groupId>org.checkerframework</groupId>
19-
<artifactId>checker-qual</artifactId>
18+
<groupId>org.jspecify</groupId>
19+
<artifactId>jspecify</artifactId>
2020
</dependency>
2121
<dependency>
2222
<groupId>junit</groupId>

core/src/main/java/com/google/common/truth/AbstractArraySubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import static com.google.common.truth.Fact.simpleFact;
2121

2222
import java.lang.reflect.Array;
23-
import org.checkerframework.checker.nullness.qual.Nullable;
23+
import org.jspecify.annotations.NullMarked;
24+
import org.jspecify.annotations.Nullable;
2425

2526
/**
2627
* A common supertype for Array subjects, abstracting some common display and error infrastructure.
2728
*
2829
* @author Christian Gruber ([email protected])
2930
*/
31+
@NullMarked
3032
abstract class AbstractArraySubject extends Subject {
3133
private final @Nullable Object actual;
3234

core/src/main/java/com/google/common/truth/ActualValueInference.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
import java.io.InputStream;
3434
import java.util.ArrayList;
3535
import java.util.Map.Entry;
36-
import org.checkerframework.checker.nullness.qual.Nullable;
36+
import org.jspecify.annotations.NullMarked;
37+
import org.jspecify.annotations.Nullable;
3738
import org.objectweb.asm.ClassReader;
3839
import org.objectweb.asm.ClassVisitor;
3940
import org.objectweb.asm.Handle;
@@ -69,6 +70,7 @@
6970
*/
7071
@GwtIncompatible
7172
@J2ktIncompatible
73+
@NullMarked
7274
final class ActualValueInference {
7375
/** <b>Call {@link Platform#inferDescription} rather than calling this directly.</b> */
7476
static @Nullable String describeActualValue(String className, String methodName, int lineNumber) {

core/src/main/java/com/google/common/truth/AssertionErrorWithFacts.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
import static com.google.common.truth.Fact.makeMessage;
2020

2121
import com.google.common.collect.ImmutableList;
22-
import org.checkerframework.checker.nullness.qual.Nullable;
22+
import org.jspecify.annotations.NullMarked;
23+
import org.jspecify.annotations.Nullable;
2324

2425
/**
2526
* An {@link AssertionError} composed of structured {@link Fact} instances and other string
2627
* messages.
2728
*/
2829
@SuppressWarnings("OverrideThrowableToString") // We intentionally hide the class name.
30+
@NullMarked
2931
final class AssertionErrorWithFacts extends AssertionError implements ErrorWithFacts {
3032
private final ImmutableList<Fact> facts;
3133

core/src/main/java/com/google/common/truth/BigDecimalSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import static com.google.common.truth.Fact.simpleFact;
2121

2222
import java.math.BigDecimal;
23-
import org.checkerframework.checker.nullness.qual.Nullable;
23+
import org.jspecify.annotations.NullMarked;
24+
import org.jspecify.annotations.Nullable;
2425

2526
/**
2627
* Propositions for {@link BigDecimal} typed subjects.
2728
*
2829
* @author Kurt Alfred Kluever
2930
*/
31+
@NullMarked
3032
public final class BigDecimalSubject extends ComparableSubject<BigDecimal> {
3133
private final @Nullable BigDecimal actual;
3234

core/src/main/java/com/google/common/truth/BooleanSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717

1818
import static com.google.common.truth.Fact.simpleFact;
1919

20-
import org.checkerframework.checker.nullness.qual.Nullable;
20+
import org.jspecify.annotations.NullMarked;
21+
import org.jspecify.annotations.Nullable;
2122

2223
/**
2324
* Propositions for boolean subjects.
2425
*
2526
* @author Christian Gruber ([email protected])
2627
*/
28+
@NullMarked
2729
public final class BooleanSubject extends Subject {
2830
private final @Nullable Boolean actual;
2931

core/src/main/java/com/google/common/truth/ClassSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
import static com.google.common.base.Preconditions.checkNotNull;
1919

2020
import com.google.common.annotations.GwtIncompatible;
21-
import org.checkerframework.checker.nullness.qual.Nullable;
21+
import org.jspecify.annotations.NullMarked;
22+
import org.jspecify.annotations.Nullable;
2223

2324
/**
2425
* Propositions for {@link Class} subjects.
2526
*
2627
* @author Kurt Alfred Kluever
2728
*/
29+
@NullMarked
2830
@GwtIncompatible("reflection")
2931
@J2ktIncompatible
3032
public final class ClassSubject extends Subject {

core/src/main/java/com/google/common/truth/ComparableSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@
1818
import static com.google.common.base.Preconditions.checkNotNull;
1919

2020
import com.google.common.collect.Range;
21-
import org.checkerframework.checker.nullness.qual.Nullable;
21+
import org.jspecify.annotations.NullMarked;
22+
import org.jspecify.annotations.Nullable;
2223

2324
/**
2425
* Propositions for {@link Comparable} typed subjects.
2526
*
2627
* @author Kurt Alfred Kluever
2728
* @param <T> the type of the object being tested by this {@code ComparableSubject}
2829
*/
30+
@NullMarked
2931
// TODO(b/136040841): Consider further tightening this to the proper `extends Comparable<? super T>`
3032
public abstract class ComparableSubject<T extends Comparable<?>> extends Subject {
3133
/**

core/src/main/java/com/google/common/truth/ComparisonFailureWithFacts.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121

2222
import com.google.common.collect.ImmutableList;
2323
import com.google.common.truth.Platform.PlatformComparisonFailure;
24-
import org.checkerframework.checker.nullness.qual.Nullable;
24+
import org.jspecify.annotations.NullMarked;
25+
import org.jspecify.annotations.Nullable;
2526

2627
/**
2728
* An {@link AssertionError} (usually a JUnit {@code ComparisonFailure}, but not under GWT) composed
2829
* of structured {@link Fact} instances and other string messages.
2930
*/
31+
@NullMarked
3032
final class ComparisonFailureWithFacts extends PlatformComparisonFailure implements ErrorWithFacts {
3133
private final ImmutableList<Fact> facts;
3234

core/src/main/java/com/google/common/truth/ComparisonFailures.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
import com.google.common.annotations.VisibleForTesting;
2828
import com.google.common.collect.ImmutableList;
29-
import org.checkerframework.checker.nullness.qual.Nullable;
29+
import org.jspecify.annotations.NullMarked;
30+
import org.jspecify.annotations.Nullable;
3031

3132
/**
3233
* Contains part of the code responsible for creating a JUnit {@code ComparisonFailure} (if
@@ -42,6 +43,7 @@
4243
* different implementation under GWT/j2cl, where {@code ComparisonFailure} is also unavailable but
4344
* we can't just recover from that at runtime.
4445
*/
46+
@NullMarked
4547
final class ComparisonFailures {
4648
static ImmutableList<Fact> makeComparisonFailureFacts(
4749
ImmutableList<Fact> headFacts,

core/src/main/java/com/google/common/truth/Correspondence.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
import com.google.common.collect.ImmutableList;
3232
import java.util.Arrays;
3333
import java.util.List;
34-
import org.checkerframework.checker.nullness.qual.Nullable;
34+
import org.jspecify.annotations.NullMarked;
35+
import org.jspecify.annotations.Nullable;
3536

3637
/**
3738
* Determines whether an instance of type {@code A} corresponds in some way to an instance of type
@@ -65,6 +66,7 @@
6566
*
6667
* @author Pete Gillin
6768
*/
69+
@NullMarked
6870
public abstract class Correspondence<A extends @Nullable Object, E extends @Nullable Object> {
6971

7072
/**

core/src/main/java/com/google/common/truth/CustomSubjectBuilder.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.common.base.Preconditions.checkNotNull;
2020

21+
import org.jspecify.annotations.NullMarked;
2122

2223
/**
2324
* In a fluent assertion chain, exposes one or more "custom" {@code that} methods, which accept a
@@ -35,6 +36,7 @@
3536
* extensions</a>. It explains the cases in which {@code CustomSubjectBuilder} is necessary, and it
3637
* links to further instructions.
3738
*/
39+
@NullMarked
3840
public abstract class CustomSubjectBuilder {
3941
/**
4042
* In a fluent assertion chain, the argument to the "custom" overload of {@link

core/src/main/java/com/google/common/truth/DiffUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323
import java.util.HashMap;
2424
import java.util.List;
2525
import java.util.Map;
26+
import org.jspecify.annotations.NullMarked;
2627

2728
/**
2829
* A custom implementation of the diff algorithm based on the solution described at
2930
* https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
3031
*
3132
* @author Yun Peng ([email protected])
3233
*/
34+
@NullMarked
3335
final class DiffUtils {
3436
// A list of unique strings appeared in compared texts.
3537
// The index of each string is its incremental Id.

core/src/main/java/com/google/common/truth/DoubleSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
import static java.lang.Double.NaN;
2727
import static java.lang.Double.doubleToLongBits;
2828

29-
import org.checkerframework.checker.nullness.qual.Nullable;
29+
import org.jspecify.annotations.NullMarked;
30+
import org.jspecify.annotations.Nullable;
3031

3132
/**
3233
* Propositions for {@link Double} subjects.
3334
*
3435
* @author Kurt Alfred Kluever
3536
*/
37+
@NullMarked
3638
public final class DoubleSubject extends ComparableSubject<Double> {
3739
private static final long NEG_ZERO_BITS = doubleToLongBits(-0.0);
3840

core/src/main/java/com/google/common/truth/ErrorWithFacts.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
package com.google.common.truth;
1818

1919
import com.google.common.collect.ImmutableList;
20+
import org.jspecify.annotations.NullMarked;
2021

2122
/**
2223
* Supertype of Truth's {@link AssertionError} subclasses that are created from a list of {@link
2324
* Fact} instances.
2425
*/
26+
@NullMarked
2527
interface ErrorWithFacts {
2628
ImmutableList<Fact> facts();
2729
}

core/src/main/java/com/google/common/truth/Expect.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
import com.google.errorprone.annotations.concurrent.GuardedBy;
3131
import java.util.ArrayList;
3232
import java.util.List;
33-
import org.checkerframework.checker.nullness.qual.Nullable;
33+
import org.jspecify.annotations.NullMarked;
34+
import org.jspecify.annotations.Nullable;
3435
import org.junit.internal.AssumptionViolatedException;
3536
import org.junit.rules.ErrorCollector;
3637
import org.junit.rules.TestRule;
@@ -83,6 +84,7 @@
8384
*/
8485
@GwtIncompatible("JUnit4")
8586
@J2ktIncompatible
87+
@NullMarked
8688
public final class Expect extends StandardSubjectBuilder implements TestRule {
8789

8890
private static final class ExpectationGatherer implements FailureStrategy {

core/src/main/java/com/google/common/truth/ExpectFailure.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
import com.google.common.annotations.GwtIncompatible;
2525
import com.google.common.truth.Truth.SimpleAssertionError;
2626
import com.google.errorprone.annotations.CanIgnoreReturnValue;
27-
import org.checkerframework.checker.nullness.qual.Nullable;
27+
import org.jspecify.annotations.NullMarked;
28+
import org.jspecify.annotations.Nullable;
2829
import org.junit.runner.Description;
2930
import org.junit.runners.model.Statement;
3031

@@ -66,6 +67,7 @@
6667
* also checks that the assertion you're testing uses the supplied {@link FailureStrategy} and calls
6768
* {@link FailureStrategy#fail} only once.
6869
*/
70+
@NullMarked
6971
public final class ExpectFailure implements Platform.JUnitTestRule {
7072
private boolean inRuleContext = false;
7173
private boolean failureExpected = false;

core/src/main/java/com/google/common/truth/Fact.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
import com.google.common.collect.ImmutableList;
2424
import java.io.Serializable;
25-
import org.checkerframework.checker.nullness.qual.Nullable;
25+
import org.jspecify.annotations.NullMarked;
26+
import org.jspecify.annotations.Nullable;
2627

2728
/**
2829
* A string key-value pair in a failure message, such as "expected: abc" or "but was: xyz."
@@ -34,6 +35,7 @@
3435
* <p>If you are writing a custom {@code Subject}, see <a
3536
* href="https://truth.dev/failure_messages">our tips on writing failure messages</a>.
3637
*/
38+
@NullMarked
3739
public final class Fact implements Serializable {
3840
/**
3941
* Creates a fact with the given key and value, which will be printed in a format like "key:

core/src/main/java/com/google/common/truth/FailureMetadata.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
import com.google.common.base.Function;
3131
import com.google.common.collect.ImmutableList;
32-
import org.checkerframework.checker.nullness.qual.Nullable;
32+
import org.jspecify.annotations.NullMarked;
33+
import org.jspecify.annotations.Nullable;
3334

3435
/**
3536
* An opaque, immutable object containing state from the previous calls in the fluent assertion
@@ -51,6 +52,7 @@
5152
* using their {@link CustomSubjectBuilder#metadata()} method to get an instance to pass to the
5253
* constructor.)
5354
*/
55+
@NullMarked
5456
public final class FailureMetadata {
5557
static FailureMetadata forFailureStrategy(FailureStrategy failureStrategy) {
5658
return new FailureMetadata(

core/src/main/java/com/google/common/truth/FailureStrategy.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.google.common.truth;
1717

18+
import org.jspecify.annotations.NullMarked;
1819

1920
/**
2021
* Defines what to do when a check fails.
@@ -53,6 +54,7 @@
5354
* StandardSubjectBuilder#forCustomFailureStrategy
5455
* StandardSubjectBuilder.forCustomFailureStrategy(STRATEGY)}.
5556
*/
57+
@NullMarked
5658
public interface FailureStrategy {
5759
/**
5860
* Handles a failure. The parameter is an {@code AssertionError} or subclass thereof, and it

core/src/main/java/com/google/common/truth/FloatSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
import static java.lang.Float.NaN;
2727
import static java.lang.Float.floatToIntBits;
2828

29-
import org.checkerframework.checker.nullness.qual.Nullable;
29+
import org.jspecify.annotations.NullMarked;
30+
import org.jspecify.annotations.Nullable;
3031

3132
/**
3233
* Propositions for {@link Float} subjects.
3334
*
3435
* @author Kurt Alfred Kluever
3536
*/
37+
@NullMarked
3638
public final class FloatSubject extends ComparableSubject<Float> {
3739
private static final int NEG_ZERO_BITS = floatToIntBits(-0.0f);
3840

core/src/main/java/com/google/common/truth/GraphMatching.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
import java.util.HashMap;
2828
import java.util.Map;
2929
import java.util.Queue;
30+
import org.jspecify.annotations.NullMarked;
3031

3132
/**
3233
* Helper routines related to <a href="https://en.wikipedia.org/wiki/Matching_(graph_theory)">graph
3334
* matchings</a>.
3435
*
3536
* @author Pete Gillin
3637
*/
38+
@NullMarked
3739
final class GraphMatching {
3840

3941
/**

core/src/main/java/com/google/common/truth/GuavaOptionalSubject.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
import static com.google.common.truth.Fact.simpleFact;
2020

2121
import com.google.common.base.Optional;
22-
import org.checkerframework.checker.nullness.qual.Nullable;
22+
import org.jspecify.annotations.NullMarked;
23+
import org.jspecify.annotations.Nullable;
2324

2425
/**
2526
* Propositions for Guava {@link Optional} subjects.
@@ -28,6 +29,7 @@
2829
*
2930
* @author Christian Gruber
3031
*/
32+
@NullMarked
3133
public final class GuavaOptionalSubject extends Subject {
3234
@SuppressWarnings("NullableOptional") // Truth always accepts nulls, no matter the type
3335
private final @Nullable Optional<?> actual;

core/src/main/java/com/google/common/truth/IgnoreJRERequirement.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
import static java.lang.annotation.ElementType.TYPE;
2222

2323
import java.lang.annotation.Target;
24+
import org.jspecify.annotations.NullMarked;
2425

2526
/**
2627
* Disables Animal Sniffer's checking of compatibility with older versions of Java/Android.
2728
*/
2829
@Target({METHOD, CONSTRUCTOR, TYPE})
30+
@NullMarked
2931
@interface IgnoreJRERequirement {}

0 commit comments

Comments
 (0)