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; 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.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.audio; 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.AudioTimestamp;
import android.media.AudioTrack; import android.media.AudioTrack;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.emsg; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata.id3; 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.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

View file

@ -104,6 +104,7 @@ public final class Assertions {
* @return The non-null reference that was validated. * @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null. * @throws NullPointerException If {@code reference} is null.
*/ */
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"}) @EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference) { public static <T> T checkNotNull(@Nullable T reference) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
@ -122,6 +123,7 @@ public final class Assertions {
* @return The non-null reference that was validated. * @return The non-null reference that was validated.
* @throws NullPointerException If {@code reference} is null. * @throws NullPointerException If {@code reference} is null.
*/ */
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"}) @EnsuresNonNull({"#1"})
public static <T> T checkNotNull(@Nullable T reference, Object errorMessage) { public static <T> T checkNotNull(@Nullable T reference, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) {
@ -137,6 +139,7 @@ public final class Assertions {
* @return The non-null, non-empty string that was validated. * @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length. * @throws IllegalArgumentException If {@code string} is null or 0-length.
*/ */
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"}) @EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string) { public static String checkNotEmpty(@Nullable String string) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(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. * @return The non-null, non-empty string that was validated.
* @throws IllegalArgumentException If {@code string} is null or 0-length. * @throws IllegalArgumentException If {@code string} is null or 0-length.
*/ */
@SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"})
@EnsuresNonNull({"#1"}) @EnsuresNonNull({"#1"})
public static String checkNotEmpty(@Nullable String string, Object errorMessage) { public static String checkNotEmpty(@Nullable String string, Object errorMessage) {
if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) { 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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.checker.nullness.qual.PolyNull;
/** /**
@ -232,6 +233,17 @@ public final class Util {
list.subList(fromIndex, toIndex).clear(); 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 * 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. * 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 * Returns the index of the largest element in {@code list} that is less than (or optionally equal
* to) a specified {@code value}. * to) a specified {@code value}.
* <p> *
* The search is performed using a binary search algorithm, so the list must be sorted. If the * <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 * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index
* index of the first one will be returned. * of the first one will be returned.
* *
* @param <T> The type of values being searched. * @param <T> The type of values being searched.
* @param list The list to search. * @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 * @return The index of the largest element in {@code list} that is less than (or optionally equal
* to) {@code value}. * to) {@code value}.
*/ */
public static <T> int binarySearchFloor(List<? extends Comparable<? super T>> list, T value, public static <T extends Comparable<? super T>> int binarySearchFloor(
boolean inclusive, boolean stayInBounds) { List<? extends Comparable<? super T>> list,
T value,
boolean inclusive,
boolean stayInBounds) {
int index = Collections.binarySearch(list, value); int index = Collections.binarySearch(list, value);
if (index < 0) { if (index < 0) {
index = -(index + 2); 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 * Returns the index of the smallest element in {@code list} that is greater than (or optionally
* equal to) a specified value. * equal to) a specified value.
* <p> *
* The search is performed using a binary search algorithm, so the list must be sorted. If the * <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 * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index
* index of the last one will be returned. * of the last one will be returned.
* *
* @param <T> The type of values being searched. * @param <T> The type of values being searched.
* @param list The list to search. * @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 * index. If false then the returned index corresponds to the smallest element strictly
* greater than the value. * greater than the value.
* @param stayInBounds If true, then {@code (list.size() - 1)} will be returned in the case that * @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 * the value is greater than the largest element in the list. If false then {@code
* {@code list.size()} will be returned. * list.size()} will be returned.
* @return The index of the smallest element in {@code list} that is greater than (or optionally * @return The index of the smallest element in {@code list} that is greater than (or optionally
* equal to) {@code value}. * equal to) {@code value}.
*/ */
public static <T> int binarySearchCeil(List<? extends Comparable<? super T>> list, T value, public static <T extends Comparable<? super T>> int binarySearchCeil(
boolean inclusive, boolean stayInBounds) { List<? extends Comparable<? super T>> list,
T value,
boolean inclusive,
boolean stayInBounds) {
int index = Collections.binarySearch(list, value); int index = Collections.binarySearch(list, value);
if (index < 0) { if (index < 0) {
index = ~index; index = ~index;
@ -970,7 +988,7 @@ public final class Util {
* @param list A list of integers. * @param list A list of integers.
* @return The list in array form, or null if the input list was null. * @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) { if (list == null) {
return 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 * Returns a copy of {@code codecs} without the codecs whose track type doesn't match {@code
* {@code trackType}. * trackType}.
* *
* @param codecs A codec sequence string, as defined in RFC 6381. * @param codecs A codec sequence string, as defined in RFC 6381.
* @param trackType One of {@link C}{@code .TRACK_TYPE_*}. * @param trackType One of {@link C}{@code .TRACK_TYPE_*}.
* @return A copy of {@code codecs} without the codecs whose track type doesn't match * @return A copy of {@code codecs} without the codecs whose track type doesn't match {@code
* {@code trackType}. * trackType}.
*/ */
public static String getCodecsOfType(String codecs, int trackType) { public static @Nullable String getCodecsOfType(String codecs, int trackType) {
String[] codecArray = splitCodecs(codecs); String[] codecArray = splitCodecs(codecs);
if (codecArray.length == 0) { if (codecArray.length == 0) {
return null; return null;
@ -1251,7 +1269,7 @@ public final class Util {
* "clearkey"}. * "clearkey"}.
* @return The derived {@link UUID}, or {@code null} if one could not be derived. * @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)) { switch (Util.toLowerInvariant(drmScheme)) {
case "widevine": case "widevine":
return C.WIDEVINE_UUID; 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 * @return The original value of the file name before it was escaped, or null if the escaped
* fileName seems invalid. * fileName seems invalid.
*/ */
public static String unescapeFileName(String fileName) { public static @Nullable String unescapeFileName(String fileName) {
int length = fileName.length(); int length = fileName.length();
int percentCharacterCount = 0; int percentCharacterCount = 0;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
@ -1473,8 +1491,9 @@ public final class Util {
/** Recursively deletes a directory and its content. */ /** Recursively deletes a directory and its content. */
public static void recursiveDelete(File fileOrDirectory) { public static void recursiveDelete(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) { File[] directoryFiles = fileOrDirectory.listFiles();
for (File child : fileOrDirectory.listFiles()) { if (directoryFiles != null) {
for (File child : directoryFiles) {
recursiveDelete(child); recursiveDelete(child);
} }
} }