blob: b042b05414160adc248794d122bf8554b74456ac [file] [log] [blame]
import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.framework.qual.DefaultQualifier;
/**
* The component type of newly created arrays is always @Nullable, also for boxed types. This is an
* expanded version of the test case for Issue 151:
* https://github.com/typetools/checker-framework/issues/151
*/
public class ArrayCreationNullable {
void testObjectArray(@NonNull Object @NonNull [] p) {
@NonNull Object @NonNull [] objs;
// :: error: (new.array)
objs = new Object[10];
objs[0].toString();
// :: error: (assignment)
objs = new @Nullable Object[10];
objs[0].toString();
// :: error: (new.array)
objs = new @NonNull Object[10];
objs[0].toString();
// Allowed.
objs = p;
objs[0].toString();
}
@DefaultQualifier(NonNull.class)
void testObjectArray2() {
Object[] objs;
// Even if the default qualifier is NonNull, array component
// types must be Nullable.
// :: error: (new.array)
objs = new Object[10];
objs[0].toString();
}
void testInitializers() {
Object[] objs = {1, 2, 3};
objs = new Integer[] {1, 2, 3};
objs = new Object[] {new Object(), "ha"};
@NonNull Object[] objs2 = {};
// :: error: (assignment)
objs2 = new Integer[] {1, null, 3};
// :: error: (assignment)
objs2 = new Object[] {new Object(), "ha", null};
@NonNull Object[] objs3 = new Integer[] {1, 2, 3};
objs3 = new Integer[] {1, 2, 3};
// :: error: (assignment)
objs3 = new Integer[] {1, 2, 3, null};
(new Integer[] {1, 2, 3})[0].toString();
// :: error: (dereference.of.nullable)
(new Integer[] {1, 2, 3, null})[0].toString();
// The assignment context is used to infer a @Nullable component type.
@Nullable Object[] objs4 = new Integer[] {1, 2, 3};
// :: error: (dereference.of.nullable)
objs4[0].toString();
objs4 = new Integer[] {1, 2, 3};
}
void testStringArray(@NonNull String @NonNull [] p) {
@NonNull String @NonNull [] strs;
// :: error: (new.array)
strs = new String[10];
strs[0].toString();
// :: error: (assignment)
strs = new @Nullable String[10];
strs[0].toString();
// :: error: (new.array)
strs = new @NonNull String[10];
strs[0].toString();
// Allowed.
strs = p;
strs[0].toString();
}
void testIntegerArray(@NonNull Integer @NonNull [] p) {
@NonNull Integer @NonNull [] ints;
// :: error: (new.array)
ints = new Integer[10];
ints[0].toString();
// :: error: (assignment)
ints = new @Nullable Integer[10];
ints[0].toString();
// :: error: (new.array)
ints = new @NonNull Integer[10];
ints[0].toString();
// Allowed.
ints = p;
ints[0].toString();
}
// The component type of zero-length arrays can be non-null - they will always generate
// IndexOutOfBoundsExceptions, but are usually just used for the type, e.g. in List.toArray.
void testLengthZero() {
@NonNull Object @NonNull [] objs;
objs = new Object[0];
}
/* Test case for Issue 153.
// toArray re-uses the passed array, if it is of appropriate size.
// It is only guaranteed to be non-null, if it is at most the same size.
void testToArray(java.util.Set<Object> nns) {
@NonNull Object [] nna = nns.toArray(new Object[nns.size()]);
// Given array is too small -> new one is created.
nna = nns.toArray(new Object[nns.size()-2]);
// Padding elements will be null.
// TODO:: error: (assignment)
nna = nns.toArray(new Object[nns.size() + 2]);
@Nullable Object [] nbla = nns.toArray(new Object[nns.size() + 2]);
}
*/
void testMultiDim() {
// new double[10][10] has type double @NonNull[] @Nullable[]
// :: error: (new.array)
double @NonNull [] @NonNull [] daa = new double[10][10];
double @NonNull [] @Nullable [] daa2 = new double[10][10];
// new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
// :: error: (new.array)
@Nullable Object @NonNull [] @NonNull [] oaa = new Object[10][10];
@Nullable Object @NonNull [] @Nullable [] oaa2 = new Object[10][10];
// new Object[10][10] has type @Nullable Object @NonNull[] @Nullable[]
// :: error: (new.array)
oaa2 = new Object @NonNull [10] @NonNull [10];
@MonotonicNonNull Object @NonNull [] @MonotonicNonNull [] oaa3 =
new @MonotonicNonNull Object @NonNull [10] @MonotonicNonNull [10];
oaa3[0] = new @MonotonicNonNull Object[4];
// :: error: (assignment)
oaa3[0] = null;
// :: error: (assignment) :: error: (accessing.nullable)
oaa3[0][0] = null;
}
@PolyNull Object[] testPolyNull(@PolyNull Object[] in) {
@PolyNull Object[] out = new @PolyNull Object[in.length];
for (int i = 0; i < in.length; ++i) {
if (in[i] == null) {
out[i] = null;
} else {
out[i] = in[i].getClass().toString();
// :: error: (assignment)
out[i] = null;
}
}
return out;
}
void testMonotonicNonNull() {
@MonotonicNonNull Object @NonNull [] loa = new @MonotonicNonNull Object @NonNull [10];
loa = new Object @NonNull [10];
loa[0] = new Object();
@MonotonicNonNull Object @NonNull [] loa2 = new Object @NonNull [10];
// :: error: (dereference.of.nullable)
loa2[0].toString();
}
@MonotonicNonNull Object @NonNull [] testReturnContext() {
return new Object[10];
}
// :: error: (new.array)
@NonNull Object @NonNull [] oa0 = new Object[10];
// OK
@MonotonicNonNull Object @NonNull [] loa0 = new @MonotonicNonNull Object @NonNull [10];
Object[] oa1 = new Object[] {new Object()};
// :: error: (assignment)
Object[] oa2 = new Object[] {new Object(), null};
public static void main(String[] args) {
ArrayCreationNullable e = new ArrayCreationNullable();
Integer[] ints = new Integer[] {5, 6};
// This would result in a NPE, if there were no error.
e.testIntegerArray(ints);
}
}