001// From the Checker Framework, but replace uses of "org.checkerframework.checker.nullness" by 002// "daikon.tools.nullness" and comment out nullness annotations and their import statement. 003package daikon.tools.nullness; 004 005import org.checkerframework.checker.nullness.qual.EnsuresNonNull; 006import org.checkerframework.checker.nullness.qual.NonNull; 007import org.checkerframework.checker.nullness.qual.Nullable; 008 009/** 010 * Utility class for the Nullness Checker. 011 * 012 * <p>To avoid the need to write the NullnessUtil class name, do: 013 * 014 * <pre>import static daikon.tools.nullness.NullnessUtil.castNonNull;</pre> 015 * 016 * or 017 * 018 * <pre>import static daikon.tools.nullness.NullnessUtil.*;</pre> 019 * 020 * <p><b>Run-time Dependency</b> 021 * 022 * <p>Please note that using this class introduces a run-time dependency. This means that you need 023 * to distribute (or link to) Daikon, along with your binaries. 024 * 025 * <p>To eliminate this dependency, you can simply copy this class into your own project. 026 */ 027@SuppressWarnings({ 028 "nullness", // Nullness utilities are trusted regarding nullness. 029 "cast" // Casts look redundant if Nullness Checker is not run. 030}) 031public final class NullnessUtil { 032 033 private NullnessUtil() { 034 throw new AssertionError("shouldn't be instantiated"); 035 } 036 037 /** 038 * A method that suppresses warnings from the Nullness Checker. 039 * 040 * <p>The method takes a possibly-null reference, unsafely casts it to have the @NonNull type 041 * qualifier, and returns it. The Nullness Checker considers both the return value, and also the 042 * argument, to be non-null after the method call. Therefore, the {@code castNonNull} method can 043 * be used either as a cast expression or as a statement. The Nullness Checker issues no warnings 044 * in any of the following code: 045 * 046 * <pre>{@code 047 * // one way to use as a cast: 048 * {@literal @}NonNull String s = castNonNull(possiblyNull1); 049 * 050 * // another way to use as a cast: 051 * castNonNull(possiblyNull2).toString(); 052 * 053 * // one way to use as a statement: 054 * castNonNull(possiblyNull3); 055 * possiblyNull3.toString();` 056 * }</pre> 057 * 058 * The {@code castNonNull} method is intended to be used in situations where the programmer 059 * definitively knows that a given reference is not null, but the type system is unable to make 060 * this deduction. It is not intended for defensive programming, in which a programmer cannot 061 * prove that the value is not null but wishes to have an earlier indication if it is. See the 062 * Checker Framework Manual for further discussion. 063 * 064 * <p>The method throws {@link AssertionError} if Java assertions are enabled and the argument is 065 * {@code null}. If the exception is ever thrown, then that indicates that the programmer misused 066 * the method by using it in a circumstance where its argument can be null. 067 * 068 * @param ref a reference of @Nullable type 069 * @return the argument, casted to have the type qualifier @NonNull 070 */ 071 public static @EnsuresNonNull("#1") <T extends @Nullable Object> @NonNull T castNonNull(T ref) { 072 assert ref != null : "Misuse of castNonNull: called with a null argument"; 073 return (@NonNull T) ref; 074 } 075 076 /** 077 * Like castNonNull, but whereas that method only checks and casts the reference itself, this 078 * traverses all levels of the argument array. The array is recursively checked to ensure that all 079 * elements at every array level are non-null. 080 * 081 * @param <T> the type of array elements 082 * @param arr an array that contains no null elements at any level 083 * @return the argument, with each array level casted to {@code @NonNull} 084 * @see #castNonNull(Object) 085 */ 086 public static @EnsuresNonNull("#1") <T extends @Nullable Object> 087 @NonNull T @NonNull [] castNonNullDeep(T @Nullable [] arr) { 088 return (@NonNull T[]) castNonNullDeepArray(arr); 089 } 090 091 /** 092 * Like castNonNull, but whereas that method only checks and casts the reference itself, this 093 * traverses all levels of the argument array. The array is recursively checked to ensure that all 094 * elements at every array level are non-null. 095 * 096 * @param <T> the type of array elements 097 * @param arr an array that contains no null elements at any level 098 * @return the argument, with each array level casted to {@code @NonNull} 099 * @see #castNonNull(Object) 100 */ 101 public static <T extends @Nullable Object> @NonNull T @NonNull [][] castNonNullDeep( 102 T @Nullable [] @Nullable [] arr) { 103 return (@NonNull T[][]) castNonNullDeepArray(arr); 104 } 105 106 /** 107 * Like castNonNull, but whereas that method only checks and casts the reference itself, this 108 * traverses all levels of the argument array. The array is recursively checked to ensure that all 109 * elements at every array level are non-null. 110 * 111 * @param <T> the type of array elements 112 * @param arr an array that contains no null elements at any level 113 * @return the argument, with each array level casted to {@code @NonNull} 114 * @see #castNonNull(Object) 115 */ 116 public static <T extends @Nullable Object> @NonNull T @NonNull [][][] castNonNullDeep( 117 T @Nullable [] @Nullable [] @Nullable [] arr) { 118 return (@NonNull T[][][]) castNonNullDeepArray(arr); 119 } 120 121 /** 122 * Like castNonNull, but whereas that method only checks and casts the reference itself, this 123 * traverses all levels of the argument array. The array is recursively checked to ensure that all 124 * elements at every array level are non-null. 125 * 126 * @param <T> the type of array elements 127 * @param arr an array that contains no null elements at any level 128 * @return the argument, with each array level casted to {@code @NonNull} 129 * @see #castNonNull(Object) 130 */ 131 public static @EnsuresNonNull("#1") <T extends @Nullable Object> 132 @NonNull T @NonNull [][][][] castNonNullDeep( 133 T @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr) { 134 return (@NonNull T[][][][]) castNonNullDeepArray(arr); 135 } 136 137 /** 138 * Like castNonNull, but whereas that method only checks and casts the reference itself, this 139 * traverses all levels of the argument array. The array is recursively checked to ensure that all 140 * elements at every array level are non-null. 141 * 142 * @param <T> the type of array elements 143 * @param arr an array that contains no null elements at any level 144 * @return the argument, with each array level casted to {@code @NonNull} 145 * @see #castNonNull(Object) 146 */ 147 public static @EnsuresNonNull("#1") <T extends @Nullable Object> 148 @NonNull T @NonNull [][][][][] castNonNullDeep( 149 T @Nullable [] @Nullable [] @Nullable [] @Nullable [] @Nullable [] arr) { 150 return (@NonNull T[][][][][]) castNonNullDeepArray(arr); 151 } 152 153 /** 154 * Does the work for the {@code castNonNullDeep} family of overloads. Throws an exception if any 155 * level of the array contains a null element. 156 * 157 * @param <T> the type of array elements 158 * @param arr an array that contains no null elements at any level 159 * @return the argument, with each array level casted to {@code @NonNull} 160 */ 161 private static <T extends @Nullable Object> @NonNull T @NonNull [] castNonNullDeepArray( 162 T @Nullable [] arr) { 163 assert arr != null : "Misuse of castNonNullDeepArray: called with a null array argument"; 164 for (int i = 0; i < arr.length; ++i) { 165 assert arr[i] != null : "Misuse of castNonNull: called with a null array element"; 166 castNonNullDeepIfArray(arr[i]); 167 } 168 return (@NonNull T[]) arr; 169 } 170 171 /** 172 * If the argument is an array, calls {@link #castNonNullDeepArray}. 173 * 174 * @param ref a value that might be an array, and if so should be null at all levels 175 */ 176 private static void castNonNullDeepIfArray(Object ref) { 177 assert ref != null : "Misuse of castNonNullIfArray: called with a null argument"; 178 Class<?> comp = ref.getClass().getComponentType(); 179 if (comp != null) { 180 // comp is non-null for arrays, otherwise null. 181 if (comp.isPrimitive()) { 182 // Nothing to do for arrays of primitive type: primitives are 183 // never null. 184 } else { 185 castNonNullDeepArray((Object[]) ref); 186 } 187 } 188 } 189}