Fix nullness warnings in Util and Assertions, and provide own castNonNull.

Using our own no-op castNonNull prevents linking into checkerframeworks library.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=206152148
This commit is contained in:
tonihei 2018-07-26 07:01:48 -07:00 committed by Oliver Woodman
parent 26a0ddcaec
commit 49ef1f3f8c
15 changed files with 60 additions and 37 deletions

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.ext.okhttp;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.net.Uri;
import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.audio;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.media.AudioTimestamp;
import android.media.AudioTrack;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.emsg;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Parcel;
import android.os.Parcelable;

View file

@ -104,6 +104,7 @@ public final class Assertions {
* @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null.
*/
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
@ -122,6 +123,7 @@ public final class Assertions {
* @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null.
*/
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
@ -137,6 +139,7 @@ public final class Assertions {
* @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length.
*/
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) {
@ -154,6 +157,7 @@ public final class Assertions {
* @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length.
*/
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) {

View file

@ -69,6 +69,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.PolyNull;
/**
@ -232,6 +233,17 @@ public final class Util {
list.subList(fromIndex, toIndex).clear();
}
/**
* Casts a nullable variable to a non-null variable without runtime null check.
*
* <p>Use {@link Assertions#checkNotNull(Object)} to throw if the value is null.
*/
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull("#1")
public static <T> T castNonNull(@Nullable T value) {
return value;
}
/**
* Copies and optionally truncates an array. Prevents null array elements created by {@link
* Arrays#copyOf(Object[], int)} by ensuring the new length does not exceed the current length.
@ -627,10 +639,10 @@ public final class Util {
/**
* Returns the index of the largest element in {@code list} that is less than (or optionally equal
* to) a specified {@code value}.
* <p>
* The search is performed using a binary search algorithm, so the list must be sorted. If the
* list contains multiple elements equal to {@code value} and {@code inclusive} is true, the
* index of the first one will be returned.
*
* <p>The search is performed using a binary search algorithm, so the list must be sorted. If the
* list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index
* of the first one will be returned.
*
* @param <T> The type of values being searched.
* @param list The list to search.
@ -643,8 +655,11 @@ public final class Util {
* @return The index of the largest element in {@code list} that is less than (or optionally equal
* to) {@code value}.
*/
public static <T> int binarySearchFloor(List<? extends Comparable<? super T>> list, T value,
boolean inclusive, boolean stayInBounds) {
public static <T extends Comparable<? super T>> int binarySearchFloor(
List<? extends Comparable<? super T>> list,
T value,
boolean inclusive,
boolean stayInBounds) {
int index = Collections.binarySearch(list, value);
if (index < 0) {
index = -(index + 2);
@ -693,10 +708,10 @@ public final class Util {
/**
* Returns the index of the smallest element in {@code list} that is greater than (or optionally
* equal to) a specified value.
* <p>
* The search is performed using a binary search algorithm, so the list must be sorted. If the
* list contains multiple elements equal to {@code value} and {@code inclusive} is true, the
* index of the last one will be returned.
*
* <p>The search is performed using a binary search algorithm, so the list must be sorted. If the
* list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index
* of the last one will be returned.
*
* @param <T> The type of values being searched.
* @param list The list to search.
@ -705,13 +720,16 @@ public final class Util {
* index. If false then the returned index corresponds to the smallest element strictly
* greater than the value.
* @param stayInBounds If true, then {@code (list.size() - 1)} will be returned in the case that
* the value is greater than the largest element in the list. If false then
* {@code list.size()} will be returned.
* the value is greater than the largest element in the list. If false then {@code
* list.size()} will be returned.
* @return The index of the smallest element in {@code list} that is greater than (or optionally
* equal to) {@code value}.
*/
public static <T> int binarySearchCeil(List<? extends Comparable<? super T>> list, T value,
boolean inclusive, boolean stayInBounds) {
public static <T extends Comparable<? super T>> int binarySearchCeil(
List<? extends Comparable<? super T>> list,
T value,
boolean inclusive,
boolean stayInBounds) {
int index = Collections.binarySearch(list, value);
if (index < 0) {
index = ~index;
@ -970,7 +988,7 @@ public final class Util {
* @param list A list of integers.
* @return The list in array form, or null if the input list was null.
*/
public static int[] toArray(List<Integer> list) {
public static int @PolyNull [] toArray(@PolyNull List<Integer> list) {
if (list == null) {
return null;
}
@ -1053,15 +1071,15 @@ public final class Util {
}
/**
* Returns a copy of {@code codecs} without the codecs whose track type doesn't match
* {@code trackType}.
* Returns a copy of {@code codecs} without the codecs whose track type doesn't match {@code
* trackType}.
*
* @param codecs A codec sequence string, as defined in RFC 6381.
* @param trackType One of {@link C}{@code .TRACK_TYPE_*}.
* @return A copy of {@code codecs} without the codecs whose track type doesn't match
* {@code trackType}.
* @return A copy of {@code codecs} without the codecs whose track type doesn't match {@code
* trackType}.
*/
public static String getCodecsOfType(String codecs, int trackType) {
public static @Nullable String getCodecsOfType(String codecs, int trackType) {
String[] codecArray = splitCodecs(codecs);
if (codecArray.length == 0) {
return null;
@ -1251,7 +1269,7 @@ public final class Util {
* "clearkey"}.
* @return The derived {@link UUID}, or {@code null} if one could not be derived.
*/
public static UUID getDrmUuid(String drmScheme) {
public static @Nullable UUID getDrmUuid(String drmScheme) {
switch (Util.toLowerInvariant(drmScheme)) {
case "widevine":
return C.WIDEVINE_UUID;
@ -1427,7 +1445,7 @@ public final class Util {
* @return The original value of the file name before it was escaped, or null if the escaped
* fileName seems invalid.
*/
public static String unescapeFileName(String fileName) {
public static @Nullable String unescapeFileName(String fileName) {
int length = fileName.length();
int percentCharacterCount = 0;
for (int i = 0; i < length; i++) {
@ -1473,8 +1491,9 @@ public final class Util {
/** Recursively deletes a directory and its content. */
public static void recursiveDelete(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
for (File child : fileOrDirectory.listFiles()) {
File[] directoryFiles = fileOrDirectory.listFiles();
if (directoryFiles != null) {
for (File child : directoryFiles) {
recursiveDelete(child);
}
}