From 7f45c0c4e53fe4f8d68c693f677965d0b17fb1ac Mon Sep 17 00:00:00 2001 From: cpovirk Date: Fri, 30 Jul 2021 11:22:53 -0700 Subject: [PATCH] Build Truth with `-source 8 -target 8`, updating annotations appropriately. This is a small step in the general direction of https://github.com/google/truth/issues/746 While there, improve the documentation of deprecated `LiteProtoSubject.isEqualTo(MessageLite.Builder)` and `isNotEqualTo(MessageLite.Builder)`, and add a TODO about possible future steps. RELNOTES=Truth is now built with `-source 8 -target 8`. This means that it no longer runs under Java 7 VMs. It continues to run under Android, even old versions, for all apps that have [enabled support for Java 8 language features](https://developer.android.com/studio/write/java8-support#supported_features). PiperOrigin-RevId: 387845958 --- .../common/truth/ActualValueInference.java | 10 +----- .../google/common/truth/FailureMetadata.java | 2 +- .../google/common/truth/IterableSubject.java | 23 ++++++++------ .../com/google/common/truth/LazyMessage.java | 3 +- .../com/google/common/truth/MapSubject.java | 12 +++---- .../google/common/truth/MultimapSubject.java | 12 +++---- .../common/truth/ObjectArraySubject.java | 2 +- .../truth/PrimitiveBooleanArraySubject.java | 2 +- .../truth/PrimitiveByteArraySubject.java | 2 +- .../truth/PrimitiveCharArraySubject.java | 2 +- .../truth/PrimitiveDoubleArraySubject.java | 2 +- .../truth/PrimitiveFloatArraySubject.java | 2 +- .../truth/PrimitiveIntArraySubject.java | 2 +- .../truth/PrimitiveLongArraySubject.java | 2 +- .../truth/PrimitiveShortArraySubject.java | 2 +- .../common/truth/StandardSubjectBuilder.java | 20 ++++++------ .../java/com/google/common/truth/Subject.java | 4 +-- .../java/com/google/common/truth/Truth.java | 18 +++++------ .../com/google/common/truth/SubjectTest.java | 17 ++++++++++ extensions/java8/pom.xml | 4 --- .../extensions/proto/LiteProtoSubject.java | 31 ++++++++++++++++--- .../proto/IterableOfProtosSubject.java | 16 +++++----- .../IterableOfProtosUsingCorrespondence.java | 8 ++--- .../MapWithProtoValuesFluentAssertion.java | 2 +- .../proto/MapWithProtoValuesSubject.java | 3 +- ...ultimapWithProtoValuesFluentAssertion.java | 2 +- .../proto/MultimapWithProtoValuesSubject.java | 3 +- .../proto/ProtoTruthMessageDifferencer.java | 2 +- pom.xml | 7 ++--- 29 files changed, 121 insertions(+), 96 deletions(-) diff --git a/core/src/main/java/com/google/common/truth/ActualValueInference.java b/core/src/main/java/com/google/common/truth/ActualValueInference.java index 5959bb606..3984c9c60 100644 --- a/core/src/main/java/com/google/common/truth/ActualValueInference.java +++ b/core/src/main/java/com/google/common/truth/ActualValueInference.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Map.Entry; +import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Handle; @@ -1507,14 +1508,5 @@ private static void closeQuietly(InputStream stream) { } } - /* - * TODO(cpovirk): Switch to using Checker Framework @Nullable. The problem I see if I try to - * switch now is that the AutoValue-generated code is `@Nullable ActualValueInference.StackEntry` - * rather than `ActualValueInference.@Nullable StackEntry`. AutoValue normally gets this right - * (b/29530042), so I think the failure here is because we use `-source 7`. That might still be - * fine, except that j2objc compilation appears to then use `-source 8`. - */ - @interface Nullable {} - private ActualValueInference() {} } diff --git a/core/src/main/java/com/google/common/truth/FailureMetadata.java b/core/src/main/java/com/google/common/truth/FailureMetadata.java index 00c890cfd..2f5bce208 100644 --- a/core/src/main/java/com/google/common/truth/FailureMetadata.java +++ b/core/src/main/java/com/google/common/truth/FailureMetadata.java @@ -161,7 +161,7 @@ enum OldAndNewValuesAreSimilar { * to set a message is {@code check(...).withMessage(...).that(...)} (for calls from within a * {@code Subject}) or {@link Truth#assertWithMessage} (for most other calls). */ - FailureMetadata withMessage(String format, /*@Nullable*/ Object[] args) { + FailureMetadata withMessage(String format, @Nullable Object[] args) { ImmutableList messages = append(this.messages, new LazyMessage(format, args)); return derive(messages, steps); } diff --git a/core/src/main/java/com/google/common/truth/IterableSubject.java b/core/src/main/java/com/google/common/truth/IterableSubject.java index bfb5dad26..24757edcd 100644 --- a/core/src/main/java/com/google/common/truth/IterableSubject.java +++ b/core/src/main/java/com/google/common/truth/IterableSubject.java @@ -204,7 +204,7 @@ public final void containsNoDuplicates() { /** Checks that the subject contains at least one of the provided objects or fails. */ public final void containsAnyOf( - @Nullable Object first, @Nullable Object second, @Nullable Object /*@Nullable*/... rest) { + @Nullable Object first, @Nullable Object second, @Nullable Object @Nullable ... rest) { containsAnyIn(accumulate(first, second, rest)); } @@ -255,7 +255,7 @@ public final void containsAnyIn(Object[] expected) { public final Ordered containsAtLeast( @Nullable Object firstExpected, @Nullable Object secondExpected, - @Nullable Object /*@Nullable*/... restOfExpected) { + @Nullable Object @Nullable ... restOfExpected) { return containsAtLeastElementsIn(accumulate(firstExpected, secondExpected, restOfExpected)); } @@ -379,7 +379,7 @@ private static void moveElements(List input, Collection output, int m * elements, not an element itself. This helps human readers and avoids a compiler warning. */ @CanIgnoreReturnValue - public final Ordered containsExactly(@Nullable Object /*@Nullable*/... varargs) { + public final Ordered containsExactly(@Nullable Object @Nullable ... varargs) { List expected = (varargs == null) ? newArrayList((Object) null) : asList(varargs); return containsExactlyElementsIn( expected, varargs != null && varargs.length == 1 && varargs[0] instanceof Iterable); @@ -694,7 +694,7 @@ enum ElementFactGrouping { public final void containsNoneOf( @Nullable Object firstExcluded, @Nullable Object secondExcluded, - @Nullable Object /*@Nullable*/... restOfExcluded) { + @Nullable Object @Nullable ... restOfExcluded) { containsNoneIn(accumulate(firstExcluded, secondExcluded, restOfExcluded)); } @@ -845,7 +845,7 @@ private void pairwiseCheck(String expectedFact, PairwiseChecker checker) { @Override @Deprecated public void isNoneOf( - @Nullable Object first, @Nullable Object second, @Nullable Object /*@Nullable*/... rest) { + @Nullable Object first, @Nullable Object second, @Nullable Object @Nullable ... rest) { super.isNoneOf(first, second, rest); } @@ -1056,6 +1056,11 @@ public UsingCorrespondence displayingDiffsPairedBy( * Checks that the subject contains at least one element that corresponds to the given expected * element. */ + /* + * TODO(cpovirk): Do we want @Nullable on usages of E? Probably not, since it could throw errors + * during comparisons? Or maybe we should take the risk for user convenience? If we make + * changes, also make them in MapSubject, MultimapSubject, and possibly others. + */ public void contains(@Nullable E expected) { Correspondence.ExceptionStore exceptions = Correspondence.ExceptionStore.forIterable(); for (A actual : getCastActual()) { @@ -1153,7 +1158,7 @@ public void doesNotContain(@Nullable E excluded) { */ @SafeVarargs @CanIgnoreReturnValue - public final Ordered containsExactly(@Nullable E /*@Nullable*/... expected) { + public final Ordered containsExactly(@Nullable E @Nullable ... expected) { return containsExactlyElementsIn( (expected == null) ? newArrayList((E) null) : asList(expected)); } @@ -1504,7 +1509,7 @@ private boolean failIfOneToOneMappingHasMissingOrExtra( @SafeVarargs @CanIgnoreReturnValue public final Ordered containsAtLeast( - @Nullable E first, @Nullable E second, @Nullable E /*@Nullable*/... rest) { + @Nullable E first, @Nullable E second, @Nullable E @Nullable ... rest) { return containsAtLeastElementsIn(accumulate(first, second, rest)); } @@ -1753,7 +1758,7 @@ private boolean failIfOneToOneMappingHasMissing( */ @SafeVarargs public final void containsAnyOf( - @Nullable E first, @Nullable E second, @Nullable E /*@Nullable*/... rest) { + @Nullable E first, @Nullable E second, @Nullable E @Nullable ... rest) { containsAnyIn(accumulate(first, second, rest)); } @@ -1861,7 +1866,7 @@ private ImmutableList describeAnyMatchesByKey( public final void containsNoneOf( @Nullable E firstExcluded, @Nullable E secondExcluded, - @Nullable E /*@Nullable*/... restOfExcluded) { + @Nullable E @Nullable ... restOfExcluded) { containsNoneIn(accumulate(firstExcluded, secondExcluded, restOfExcluded)); } diff --git a/core/src/main/java/com/google/common/truth/LazyMessage.java b/core/src/main/java/com/google/common/truth/LazyMessage.java index aa5b3c54c..3fd26c904 100644 --- a/core/src/main/java/com/google/common/truth/LazyMessage.java +++ b/core/src/main/java/com/google/common/truth/LazyMessage.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; +import org.checkerframework.checker.nullness.qual.Nullable; final class LazyMessage { private static final String PLACEHOLDER_ERR = @@ -28,7 +29,7 @@ final class LazyMessage { private final String format; private final Object[] args; - LazyMessage(String format, /*@Nullable*/ Object... args) { + LazyMessage(String format, @Nullable Object... args) { this.format = format; this.args = args; int placeholders = countPlaceholders(format); diff --git a/core/src/main/java/com/google/common/truth/MapSubject.java b/core/src/main/java/com/google/common/truth/MapSubject.java index 6315a8e8a..2744d505f 100644 --- a/core/src/main/java/com/google/common/truth/MapSubject.java +++ b/core/src/main/java/com/google/common/truth/MapSubject.java @@ -188,18 +188,18 @@ public final Ordered containsExactly() { */ @CanIgnoreReturnValue public final Ordered containsExactly( - @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { return containsExactlyEntriesIn(accumulateMap("containsExactly", k0, v0, rest)); } @CanIgnoreReturnValue public final Ordered containsAtLeast( - @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { return containsAtLeastEntriesIn(accumulateMap("containsAtLeast", k0, v0, rest)); } private static Map accumulateMap( - String functionName, @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + String functionName, @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { checkArgument( rest.length % 2 == 0, "There must be an equal number of key/value pairs " @@ -682,8 +682,7 @@ public void doesNotContainEntry(@Nullable Object excludedKey, @Nullable E exclud // TODO(b/25744307): Can we add an error-prone check that rest.length % 2 == 0? // For bonus points, checking that the even-numbered values are of type E would be sweet. @CanIgnoreReturnValue - public Ordered containsExactly( - @Nullable Object k0, @Nullable E v0, /*@Nullable*/ Object... rest) { + public Ordered containsExactly(@Nullable Object k0, @Nullable E v0, @Nullable Object... rest) { @SuppressWarnings("unchecked") // throwing ClassCastException is the correct behaviour Map expectedMap = (Map) accumulateMap("containsExactly", k0, v0, rest); return containsExactlyEntriesIn(expectedMap); @@ -702,8 +701,7 @@ public Ordered containsExactly( // TODO(b/25744307): Can we add an error-prone check that rest.length % 2 == 0? // For bonus points, checking that the even-numbered values are of type E would be sweet. @CanIgnoreReturnValue - public Ordered containsAtLeast( - @Nullable Object k0, @Nullable E v0, /*@Nullable*/ Object... rest) { + public Ordered containsAtLeast(@Nullable Object k0, @Nullable E v0, @Nullable Object... rest) { @SuppressWarnings("unchecked") // throwing ClassCastException is the correct behaviour Map expectedMap = (Map) accumulateMap("containsAtLeast", k0, v0, rest); return containsAtLeastEntriesIn(expectedMap); diff --git a/core/src/main/java/com/google/common/truth/MultimapSubject.java b/core/src/main/java/com/google/common/truth/MultimapSubject.java index 332da4ae0..a80545ad2 100644 --- a/core/src/main/java/com/google/common/truth/MultimapSubject.java +++ b/core/src/main/java/com/google/common/truth/MultimapSubject.java @@ -305,7 +305,7 @@ public final Ordered containsExactly() { */ @CanIgnoreReturnValue public final Ordered containsExactly( - @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { return containsExactlyEntriesIn(accumulateMultimap(k0, v0, rest)); } @@ -317,12 +317,12 @@ public final Ordered containsExactly( */ @CanIgnoreReturnValue public final Ordered containsAtLeast( - @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { return containsAtLeastEntriesIn(accumulateMultimap(k0, v0, rest)); } private static Multimap accumulateMultimap( - @Nullable Object k0, @Nullable Object v0, /*@Nullable*/ Object... rest) { + @Nullable Object k0, @Nullable Object v0, @Nullable Object... rest) { checkArgument( rest.length % 2 == 0, "There must be an equal number of key/value pairs " @@ -770,8 +770,7 @@ private Ordered internalContainsAtLeastEntriesIn( * key/value pairs at compile time. Please make sure you provide varargs in key/value pairs! */ @CanIgnoreReturnValue - public Ordered containsExactly( - @Nullable Object k0, @Nullable E v0, /*@Nullable*/ Object... rest) { + public Ordered containsExactly(@Nullable Object k0, @Nullable E v0, @Nullable Object... rest) { @SuppressWarnings("unchecked") Multimap expectedMultimap = (Multimap) accumulateMultimap(k0, v0, rest); return containsExactlyEntriesIn(expectedMultimap); @@ -790,8 +789,7 @@ public Ordered containsExactly() { * key/value pairs at compile time. Please make sure you provide varargs in key/value pairs! */ @CanIgnoreReturnValue - public Ordered containsAtLeast( - @Nullable Object k0, @Nullable E v0, /*@Nullable*/ Object... rest) { + public Ordered containsAtLeast(@Nullable Object k0, @Nullable E v0, @Nullable Object... rest) { @SuppressWarnings("unchecked") Multimap expectedMultimap = (Multimap) accumulateMultimap(k0, v0, rest); return containsAtLeastEntriesIn(expectedMultimap); diff --git a/core/src/main/java/com/google/common/truth/ObjectArraySubject.java b/core/src/main/java/com/google/common/truth/ObjectArraySubject.java index cd6b42b5a..2b6184e42 100644 --- a/core/src/main/java/com/google/common/truth/ObjectArraySubject.java +++ b/core/src/main/java/com/google/common/truth/ObjectArraySubject.java @@ -27,7 +27,7 @@ public final class ObjectArraySubject extends AbstractArraySubject { private final T[] actual; ObjectArraySubject( - FailureMetadata metadata, @Nullable T /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, @Nullable T @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveBooleanArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveBooleanArraySubject.java index 47605bc64..a4cf61cf5 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveBooleanArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveBooleanArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveBooleanArraySubject extends AbstractArraySubject { private final boolean[] actual; PrimitiveBooleanArraySubject( - FailureMetadata metadata, boolean /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, boolean @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveByteArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveByteArraySubject.java index 59a3c7dda..204ad3840 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveByteArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveByteArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveByteArraySubject extends AbstractArraySubject { private final byte[] actual; PrimitiveByteArraySubject( - FailureMetadata metadata, byte /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, byte @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveCharArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveCharArraySubject.java index 6e94b2cf1..5a89e71c4 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveCharArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveCharArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveCharArraySubject extends AbstractArraySubject { private final char[] actual; PrimitiveCharArraySubject( - FailureMetadata metadata, char /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, char @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveDoubleArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveDoubleArraySubject.java index dc2651051..4fb7ad455 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveDoubleArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveDoubleArraySubject.java @@ -34,7 +34,7 @@ public final class PrimitiveDoubleArraySubject extends AbstractArraySubject { private final double[] actual; PrimitiveDoubleArraySubject( - FailureMetadata metadata, double /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, double @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveFloatArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveFloatArraySubject.java index ae106d5f3..580ff4f41 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveFloatArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveFloatArraySubject.java @@ -34,7 +34,7 @@ public final class PrimitiveFloatArraySubject extends AbstractArraySubject { private final float[] actual; PrimitiveFloatArraySubject( - FailureMetadata metadata, float /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, float @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveIntArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveIntArraySubject.java index f2c4abb5b..0dc669817 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveIntArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveIntArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveIntArraySubject extends AbstractArraySubject { private final int[] actual; PrimitiveIntArraySubject( - FailureMetadata metadata, int /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, int @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveLongArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveLongArraySubject.java index 1d5aec0c0..53c0d5963 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveLongArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveLongArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveLongArraySubject extends AbstractArraySubject { private final long[] actual; PrimitiveLongArraySubject( - FailureMetadata metadata, long /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, long @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/PrimitiveShortArraySubject.java b/core/src/main/java/com/google/common/truth/PrimitiveShortArraySubject.java index cd17c874e..c96bf3f39 100644 --- a/core/src/main/java/com/google/common/truth/PrimitiveShortArraySubject.java +++ b/core/src/main/java/com/google/common/truth/PrimitiveShortArraySubject.java @@ -27,7 +27,7 @@ public final class PrimitiveShortArraySubject extends AbstractArraySubject { private final short[] actual; PrimitiveShortArraySubject( - FailureMetadata metadata, short /*@Nullable*/[] o, @Nullable String typeDescription) { + FailureMetadata metadata, short @Nullable [] o, @Nullable String typeDescription) { super(metadata, o, typeDescription); this.actual = o; } diff --git a/core/src/main/java/com/google/common/truth/StandardSubjectBuilder.java b/core/src/main/java/com/google/common/truth/StandardSubjectBuilder.java index 512de7e85..baaaae67a 100644 --- a/core/src/main/java/com/google/common/truth/StandardSubjectBuilder.java +++ b/core/src/main/java/com/google/common/truth/StandardSubjectBuilder.java @@ -112,39 +112,39 @@ public final IterableSubject that(@Nullable Iterable actual) { return new IterableSubject(metadata(), actual); } - public final ObjectArraySubject that(@Nullable T /*@Nullable*/[] actual) { + public final ObjectArraySubject that(@Nullable T @Nullable [] actual) { return new ObjectArraySubject<>(metadata(), actual, "array"); } - public final PrimitiveBooleanArraySubject that(boolean /*@Nullable*/[] actual) { + public final PrimitiveBooleanArraySubject that(boolean @Nullable [] actual) { return new PrimitiveBooleanArraySubject(metadata(), actual, "array"); } - public final PrimitiveShortArraySubject that(short /*@Nullable*/[] actual) { + public final PrimitiveShortArraySubject that(short @Nullable [] actual) { return new PrimitiveShortArraySubject(metadata(), actual, "array"); } - public final PrimitiveIntArraySubject that(int /*@Nullable*/[] actual) { + public final PrimitiveIntArraySubject that(int @Nullable [] actual) { return new PrimitiveIntArraySubject(metadata(), actual, "array"); } - public final PrimitiveLongArraySubject that(long /*@Nullable*/[] actual) { + public final PrimitiveLongArraySubject that(long @Nullable [] actual) { return new PrimitiveLongArraySubject(metadata(), actual, "array"); } - public final PrimitiveCharArraySubject that(char /*@Nullable*/[] actual) { + public final PrimitiveCharArraySubject that(char @Nullable [] actual) { return new PrimitiveCharArraySubject(metadata(), actual, "array"); } - public final PrimitiveByteArraySubject that(byte /*@Nullable*/[] actual) { + public final PrimitiveByteArraySubject that(byte @Nullable [] actual) { return new PrimitiveByteArraySubject(metadata(), actual, "array"); } - public final PrimitiveFloatArraySubject that(float /*@Nullable*/[] actual) { + public final PrimitiveFloatArraySubject that(float @Nullable [] actual) { return new PrimitiveFloatArraySubject(metadata(), actual, "array"); } - public final PrimitiveDoubleArraySubject that(double /*@Nullable*/[] actual) { + public final PrimitiveDoubleArraySubject that(double @Nullable [] actual) { return new PrimitiveDoubleArraySubject(metadata(), actual, "array"); } @@ -189,7 +189,7 @@ public final StandardSubjectBuilder withMessage(@Nullable String messageToPrepen * @throws IllegalArgumentException if the number of placeholders in the format string does not * equal the number of given arguments */ - public final StandardSubjectBuilder withMessage(String format, /*@Nullable*/ Object... args) { + public final StandardSubjectBuilder withMessage(String format, @Nullable Object... args) { return new StandardSubjectBuilder(metadata().withMessage(format, args)); } diff --git a/core/src/main/java/com/google/common/truth/Subject.java b/core/src/main/java/com/google/common/truth/Subject.java index 0d1436a6c..a659c5d2f 100644 --- a/core/src/main/java/com/google/common/truth/Subject.java +++ b/core/src/main/java/com/google/common/truth/Subject.java @@ -346,7 +346,7 @@ public void isIn(Iterable iterable) { /** Fails unless the subject is equal to any of the given elements. */ public void isAnyOf( - @Nullable Object first, @Nullable Object second, @Nullable Object /*@Nullable*/... rest) { + @Nullable Object first, @Nullable Object second, @Nullable Object @Nullable ... rest) { isIn(accumulate(first, second, rest)); } @@ -359,7 +359,7 @@ public void isNotIn(Iterable iterable) { /** Fails if the subject is equal to any of the given elements. */ public void isNoneOf( - @Nullable Object first, @Nullable Object second, @Nullable Object /*@Nullable*/... rest) { + @Nullable Object first, @Nullable Object second, @Nullable Object @Nullable ... rest) { isNotIn(accumulate(first, second, rest)); } diff --git a/core/src/main/java/com/google/common/truth/Truth.java b/core/src/main/java/com/google/common/truth/Truth.java index fa9b5aeeb..57620501e 100644 --- a/core/src/main/java/com/google/common/truth/Truth.java +++ b/core/src/main/java/com/google/common/truth/Truth.java @@ -193,39 +193,39 @@ public static IterableSubject assertThat(@Nullable Iterable actual) { return assert_().that(actual); } - public static ObjectArraySubject assertThat(@Nullable T /*@Nullable*/[] actual) { + public static ObjectArraySubject assertThat(@Nullable T @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveBooleanArraySubject assertThat(boolean /*@Nullable*/[] actual) { + public static PrimitiveBooleanArraySubject assertThat(boolean @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveShortArraySubject assertThat(short /*@Nullable*/[] actual) { + public static PrimitiveShortArraySubject assertThat(short @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveIntArraySubject assertThat(int /*@Nullable*/[] actual) { + public static PrimitiveIntArraySubject assertThat(int @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveLongArraySubject assertThat(long /*@Nullable*/[] actual) { + public static PrimitiveLongArraySubject assertThat(long @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveByteArraySubject assertThat(byte /*@Nullable*/[] actual) { + public static PrimitiveByteArraySubject assertThat(byte @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveCharArraySubject assertThat(char /*@Nullable*/[] actual) { + public static PrimitiveCharArraySubject assertThat(char @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveFloatArraySubject assertThat(float /*@Nullable*/[] actual) { + public static PrimitiveFloatArraySubject assertThat(float @Nullable [] actual) { return assert_().that(actual); } - public static PrimitiveDoubleArraySubject assertThat(double /*@Nullable*/[] actual) { + public static PrimitiveDoubleArraySubject assertThat(double @Nullable [] actual) { return assert_().that(actual); } diff --git a/core/src/test/java/com/google/common/truth/SubjectTest.java b/core/src/test/java/com/google/common/truth/SubjectTest.java index 32919ce41..129ab5227 100644 --- a/core/src/test/java/com/google/common/truth/SubjectTest.java +++ b/core/src/test/java/com/google/common/truth/SubjectTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.TestPlatform.isGwt; import static com.google.common.truth.Truth.assertAbout; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.TruthJUnit.assume; import static org.junit.Assert.fail; import com.google.common.annotations.GwtIncompatible; @@ -58,7 +59,16 @@ public class SubjectTest extends BaseSubjectTestCase { @Test @GwtIncompatible("NullPointerTester") @SuppressWarnings("GoogleInternalApi") + /* + * TODO(cpovirk): Reenable these tests publicly. Currently, we depend on guava-android, whose + * NullPointerTester doesn't yet recognize type-use @Nullable annotations. And we can't mix the + * -jre version of guava-testlib with the -android version of guava because the NullPointerTester + * feature we need requires a -jre-only API. + */ + @org.junit.Ignore public void nullPointerTester() { + assume().that(isAndroid()).isFalse(); // type-annotation @Nullable is not available + NullPointerTester npTester = new NullPointerTester(); npTester.setDefault(Fact.class, simpleFact("fact")); @@ -88,7 +98,10 @@ public void nullPointerTester() { @Test @GwtIncompatible("NullPointerTester") + @org.junit.Ignore // TODO(cpovirk): Reenable publicly. (See nullPointerTester().) public void allAssertThatOverloadsAcceptNull() throws Exception { + assume().that(isAndroid()).isFalse(); // type-annotation @Nullable is not available + NullPointerTester npTester = new NullPointerTester(); npTester.setDefault(Fact.class, simpleFact("fact")); for (Method method : Truth.class.getDeclaredMethods()) { @@ -811,4 +824,8 @@ public ForbidsEqualityChecksSubject createSubject(FailureMetadata metadata, Obje } }; } + + private static boolean isAndroid() { + return System.getProperty("java.runtime.name").contains("Android"); + } } diff --git a/extensions/java8/pom.xml b/extensions/java8/pom.xml index f3dfec9ff..d4e3fa792 100644 --- a/extensions/java8/pom.xml +++ b/extensions/java8/pom.xml @@ -31,10 +31,6 @@ maven-compiler-plugin - - 1.8 - 1.8 - maven-jar-plugin diff --git a/extensions/liteproto/src/main/java/com/google/common/truth/extensions/proto/LiteProtoSubject.java b/extensions/liteproto/src/main/java/com/google/common/truth/extensions/proto/LiteProtoSubject.java index 8bee5946e..3a0774eed 100644 --- a/extensions/liteproto/src/main/java/com/google/common/truth/extensions/proto/LiteProtoSubject.java +++ b/extensions/liteproto/src/main/java/com/google/common/truth/extensions/proto/LiteProtoSubject.java @@ -139,10 +139,31 @@ public void isEqualTo(@Nullable Object expected) { /** * @deprecated A Builder can never compare equal to a MessageLite instance. Use {@code build()}, - * or {@code buildPartial()} on the argument to get a MessageLite for comparison instead. + * or {@code buildPartial()} on the argument to get a MessageLite for comparison instead. Or, + * if you are passing {@code null}, use {@link #isNull()}. + */ + /* + * TODO(cpovirk): Consider @DoNotCall -- or probably some other static analysis, given the problem + * discussed in the rest of this comment. + * + * The problem: isEqualTo(null) resolves to this overload (since this overload is more specific + * than isEqualTo(Object)), so @DoNotCall would break all assertions of that form. + * + * To address that, we could try also adding something like ` void isEqualTo(NullT)` and hoping that isEqualTo(null) would resolve to + * that instead. That would also have the benefit of making isEqualTo(null) not produce a + * deprecation warning (though of course people "should" use isNull(): b/17294077). But yuck. + * + * Given the null issue, maybe we should never have added this overload in the first place, + * instead adding static analysis specific to MessageLite-MessageLite.Builder comparisons. (Sadly, + * we can't remove it now without breaking binary compatibility.) + * + * Still, we could add static analysis to produce a compile error for isEqualTo(Builder) this even + * today, even without using @DoNotCall. And then we could consider removing @Deprecated to stop + * spamming the people who call isEqualTo(null). */ @Deprecated - public void isEqualTo(MessageLite./*@Nullable*/ Builder builder) { + public void isEqualTo(MessageLite.@Nullable Builder builder) { isEqualTo((Object) builder); } @@ -169,10 +190,12 @@ public void isNotEqualTo(@Nullable Object expected) { /** * @deprecated A Builder will never compare equal to a MessageLite instance. Use {@code build()}, - * or {@code buildPartial()} on the argument to get a MessageLite for comparison instead. + * or {@code buildPartial()} on the argument to get a MessageLite for comparison instead. Or, + * if you are passing {@code null}, use {@link #isNotNull()}. */ + // TODO(cpovirk): Consider @DoNotCall or other static analysis. (See isEqualTo(Builder).) @Deprecated - public void isNotEqualTo(MessageLite./*@Nullable*/ Builder builder) { + public void isNotEqualTo(MessageLite.@Nullable Builder builder) { isNotEqualTo((Object) builder); } diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosSubject.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosSubject.java index 0b9252a72..10ccf6d54 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosSubject.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosSubject.java @@ -735,7 +735,7 @@ public void doesNotContain(@Nullable M excluded) { @Override @CanIgnoreReturnValue - public Ordered containsExactly(/*@Nullable*/ M... expected) { + public Ordered containsExactly(@Nullable M... expected) { return delegate(Arrays.asList(expected)).containsExactly(expected); } @@ -753,7 +753,7 @@ public Ordered containsExactlyElementsIn(M[] expected) { @Override @CanIgnoreReturnValue - public Ordered containsAtLeast(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest) { + public Ordered containsAtLeast(@Nullable M first, @Nullable M second, @Nullable M... rest) { return delegate(Lists.asList(first, second, rest)).containsAtLeast(first, second, rest); } @@ -770,7 +770,7 @@ public Ordered containsAtLeastElementsIn(M[] expected) { } @Override - public void containsAnyOf(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest) { + public void containsAnyOf(@Nullable M first, @Nullable M second, @Nullable M... rest) { delegate(Lists.asList(first, second, rest)).containsAnyOf(first, second, rest); } @@ -786,7 +786,7 @@ public void containsAnyIn(M[] expected) { @Override public void containsNoneOf( - @Nullable M firstExcluded, @Nullable M secondExcluded, /*@Nullable*/ M... restOfExcluded) { + @Nullable M firstExcluded, @Nullable M secondExcluded, @Nullable M... restOfExcluded) { delegate(Lists.asList(firstExcluded, secondExcluded, restOfExcluded)) .containsNoneOf(firstExcluded, secondExcluded, restOfExcluded); } @@ -1029,7 +1029,7 @@ public void doesNotContain(@Nullable M excluded) { } @Override - public Ordered containsExactly(/*@Nullable*/ M... expected) { + public Ordered containsExactly(@Nullable M... expected) { return usingCorrespondence().containsExactly(expected); } @@ -1044,7 +1044,7 @@ public Ordered containsExactlyElementsIn(M[] expected) { } @Override - public Ordered containsAtLeast(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest) { + public Ordered containsAtLeast(@Nullable M first, @Nullable M second, @Nullable M... rest) { return usingCorrespondence().containsAtLeast(first, second, rest); } @@ -1059,7 +1059,7 @@ public Ordered containsAtLeastElementsIn(M[] expected) { } @Override - public void containsAnyOf(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest) { + public void containsAnyOf(@Nullable M first, @Nullable M second, @Nullable M... rest) { usingCorrespondence().containsAnyOf(first, second, rest); } @@ -1075,7 +1075,7 @@ public void containsAnyIn(M[] expected) { @Override public void containsNoneOf( - @Nullable M firstExcluded, @Nullable M secondExcluded, /*@Nullable*/ M... restOfExcluded) { + @Nullable M firstExcluded, @Nullable M secondExcluded, @Nullable M... restOfExcluded) { usingCorrespondence().containsNoneOf(firstExcluded, secondExcluded, restOfExcluded); } diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosUsingCorrespondence.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosUsingCorrespondence.java index 5a49369af..9c366f588 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosUsingCorrespondence.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/IterableOfProtosUsingCorrespondence.java @@ -83,7 +83,7 @@ IterableOfProtosUsingCorrespondence displayingDiffsPairedBy( * elements, not an element itself. */ @CanIgnoreReturnValue - Ordered containsExactly(/*@Nullable*/ M... expected); + Ordered containsExactly(@Nullable M... expected); /** * Checks that subject contains exactly elements that correspond to the expected elements, i.e. @@ -117,7 +117,7 @@ IterableOfProtosUsingCorrespondence displayingDiffsPairedBy( * subject, but they are not required to be consecutive. */ @CanIgnoreReturnValue - Ordered containsAtLeast(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest); + Ordered containsAtLeast(@Nullable M first, @Nullable M second, @Nullable M... rest); /** * Checks that the subject contains elements that corresponds to all of the expected elements, @@ -147,7 +147,7 @@ IterableOfProtosUsingCorrespondence displayingDiffsPairedBy( * Checks that the subject contains at least one element that corresponds to at least one of the * expected elements. */ - void containsAnyOf(@Nullable M first, @Nullable M second, /*@Nullable*/ M... rest); + void containsAnyOf(@Nullable M first, @Nullable M second, @Nullable M... rest); /** * Checks that the subject contains at least one element that corresponds to at least one of the @@ -167,7 +167,7 @@ IterableOfProtosUsingCorrespondence displayingDiffsPairedBy( * to any of the given elements.) */ void containsNoneOf( - @Nullable M firstExcluded, @Nullable M secondExcluded, /*@Nullable*/ M... restOfExcluded); + @Nullable M firstExcluded, @Nullable M secondExcluded, @Nullable M... restOfExcluded); /** * Checks that the subject contains no elements that correspond to any of the given elements. diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesFluentAssertion.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesFluentAssertion.java index fee524234..f1aa7af10 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesFluentAssertion.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesFluentAssertion.java @@ -524,7 +524,7 @@ MapWithProtoValuesFluentAssertion unpackingAnyUsingForValues( * key/value pairs at compile time. Please make sure you provide varargs in key/value pairs! */ @CanIgnoreReturnValue - Ordered containsExactly(@Nullable Object k0, @Nullable M v0, /*@Nullable*/ Object... rest); + Ordered containsExactly(@Nullable Object k0, @Nullable M v0, @Nullable Object... rest); /** * Fails if the map does not contain exactly the keys in the given map, mapping to values that diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesSubject.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesSubject.java index 2f4fac81c..9248843e9 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesSubject.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MapWithProtoValuesSubject.java @@ -870,8 +870,7 @@ public void doesNotContainEntry(@Nullable Object excludedKey, @Nullable M exclud @Override @CanIgnoreReturnValue @SuppressWarnings("unchecked") // ClassCastException is fine - public Ordered containsExactly( - @Nullable Object k0, @Nullable M v0, /*@Nullable*/ Object... rest) { + public Ordered containsExactly(@Nullable Object k0, @Nullable M v0, @Nullable Object... rest) { List expectedValues = new ArrayList<>(); expectedValues.add(v0); for (int i = 1; i < rest.length; i += 2) { diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesFluentAssertion.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesFluentAssertion.java index 224e3302a..838389b4e 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesFluentAssertion.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesFluentAssertion.java @@ -536,7 +536,7 @@ MultimapWithProtoValuesFluentAssertion unpackingAnyUsingForValues( * key/value pairs at compile time. Please make sure you provide varargs in key/value pairs! */ @CanIgnoreReturnValue - public Ordered containsExactly(@Nullable Object k0, @Nullable M v0, /*@Nullable*/ Object... rest); + public Ordered containsExactly(@Nullable Object k0, @Nullable M v0, @Nullable Object... rest); /** * @deprecated Do not call {@code equals()} on a {@code MultimapWithProtoValuesFluentAssertion}. diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesSubject.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesSubject.java index 8a1e5c0a4..b7afda3e9 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesSubject.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/MultimapWithProtoValuesSubject.java @@ -916,8 +916,7 @@ public Ordered containsExactly() { @Override @CanIgnoreReturnValue @SuppressWarnings("unchecked") // ClassCastException is fine - public Ordered containsExactly( - @Nullable Object k0, @Nullable M v0, /*@Nullable*/ Object... rest) { + public Ordered containsExactly(@Nullable Object k0, @Nullable M v0, @Nullable Object... rest) { List expectedValues = new ArrayList<>(); expectedValues.add(v0); for (int i = 1; i < rest.length; i += 2) { diff --git a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/ProtoTruthMessageDifferencer.java b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/ProtoTruthMessageDifferencer.java index d843a61de..8a62255ad 100644 --- a/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/ProtoTruthMessageDifferencer.java +++ b/extensions/proto/src/main/java/com/google/common/truth/extensions/proto/ProtoTruthMessageDifferencer.java @@ -505,7 +505,7 @@ private RepeatedField compareRepeatedFieldExpectingSubsequence( // Also removes the index for the matching value from actualIndicies. // // If there is no match, returns null. - private RepeatedField./*@Nullable*/ PairResult findMatchingPairResult( + private RepeatedField.@Nullable PairResult findMatchingPairResult( Deque actualIndices, List actualValues, int expectedIndex, diff --git a/pom.xml b/pom.xml index f2b859ab8..6724c646d 100644 --- a/pom.xml +++ b/pom.xml @@ -258,7 +258,6 @@ https://junit.org/junit4/javadoc/latest/ https://docs.oracle.com/javase/7/docs/api/ - 8 **/super/**/*.java @@ -293,10 +292,8 @@ maven-compiler-plugin 3.8.1 - 1.7 - 1.7 - 1.8 - 1.8 + 1.8 + 1.8