blob: 2ef24c22d3145deddc3854d548799e1f3b14e1a4 [file] [log] [blame]
import org.checkerframework.checker.nullness.qual.*;
public class FlowNullness {
public void testIf() {
String str = "foo";
@NonNull String a;
// :: warning: (nulltest.redundant)
if (str != null) {
a = str;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testIfNoBlock() {
String str = "foo";
@NonNull String a;
// :: warning: (nulltest.redundant)
if (str != null) {
a = str;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testElse() {
String str = "foo";
@NonNull String a;
// :: warning: (nulltest.redundant)
if (str == null) {
testAssert();
} else {
a = str;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testElseNoBlock() {
String str = "foo";
@NonNull String a;
// :: warning: (nulltest.redundant)
if (str == null) {
testAssert();
} else {
a = str;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testReturnIf() {
String str = "foo";
// :: warning: (nulltest.redundant)
if (str == null) {
testAssert();
return;
}
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testReturnElse() {
String str = "foo";
// :: warning: (nulltest.redundant)
if (str != null) {
testAssert();
} else {
return;
}
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testThrowIf() {
String str = "foo";
// :: warning: (nulltest.redundant)
if (str == null) {
testAssert();
throw new RuntimeException("foo");
}
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testThrowElse() {
String str = "foo";
// :: warning: (nulltest.redundant)
if (str != null) {
testAssert();
} else {
throw new RuntimeException("foo");
}
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testAssert() {
String str = "foo";
// :: warning: (nulltest.redundant)
assert str != null;
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testWhile() {
String str = "foo";
// :: warning: (nulltest.redundant)
while (str != null) {
@NonNull String a = str;
break;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testIfInstanceOf() {
String str = "foo";
@NonNull String a;
if (str instanceof String) {
a = str;
}
str = null;
// :: error: (assignment)
@NonNull String b = str;
}
public void testNew() {
String str = "foo";
@NonNull String a = str;
str = null;
// :: error: (assignment)
@NonNull String b = str;
String s2 = new String();
s2.toString();
}
public void testExit() {
String str = "foo";
// :: warning: (nulltest.redundant)
if (str == null) {
System.exit(0);
}
@NonNull String a = str;
}
void testMore() {
String str = null + " foo";
@NonNull String a = str;
}
void orderOfEvaluation() {
class MyClass {
@org.checkerframework.dataflow.qual.Pure
public boolean equals(@Nullable Object o) {
return o != null;
}
void test(@Nullable Object a, @Nullable Object b) {}
}
MyClass m = new MyClass();
m.equals(m = null);
MyClass n = new MyClass();
// :: error: (dereference.of.nullable)
n.test(n = null, n.toString()); // error
MyClass o = null;
// :: error: (dereference.of.nullable)
o.equals(o == new MyClass()); // error
}
void instanceOf(@Nullable Object o) {
if (o instanceof String) {
// cannot be null here
o.toString();
return;
}
// :: error: (dereference.of.nullable)
o.toString(); // error
}
public static void checkConditional1(@Nullable Object a) {
if (a == null) {
} else {
a.getClass(); // not an error
}
}
public static void checkConditional2(@Nullable Object a) {
if (a == null) {
} else if (a instanceof String) {
} else {
a.getClass(); // not an error
}
}
public static String spf(String format, @NonNull Object[] args) {
int current_arg = 0;
Object arg = args[current_arg];
if (false) {
return arg.toString(); // not an error
}
if (arg instanceof long[]) {
return "foo";
} else {
return arg.toString(); // still not an error
}
}
void empty_makes_no_change() {
String o1 = "not null!";
if (false) {
// empty branch
} else {
o1 = "still not null!";
}
System.out.println(o1.toString());
}
@org.checkerframework.dataflow.qual.Pure
public boolean equals(@Nullable Object o) {
if (!(o instanceof Integer)) {
return false;
}
@NonNull Object nno = o;
@NonNull Integer nni = (Integer) o;
return true;
}
void while_set_and_test(@Nullable String s) {
String line;
// imagine "s" is "reader.readLine()" (but avoid use of libraries in unit tests)
while ((line = s) != null) {
line.trim();
}
}
void equality_test(@Nullable String s) {
@NonNull String n = "m";
if (s == n) {
s.toString();
}
}
@Nullable Object returnNullable() {
return null;
}
void testNullableCall() {
if (returnNullable() != null) {
// :: error: (dereference.of.nullable)
returnNullable().toString(); // error
}
}
void nonNullArg(@NonNull Object arg) {
// empty body
}
void testNonNullArg(@Nullable Object arg) {
// :: error: (argument)
nonNullArg(arg); // error
nonNullArg(arg); // no error
}
void test() {
String[] s = null;
// :: error: (dereference.of.nullable)
for (int i = 0; i < s.length; ++i) { // error
String m = s[i]; // fine.. s cannot be null
}
}
private double @MonotonicNonNull []
intersect; // = null; TODO: do we want to allow assignments of null to MonotonicNonNull?
public void add_modified(double[] a, int count) {
// System.out.println ("common: " + ArraysMDE.toString (a));
// :: warning: (nulltest.redundant)
if (a == null) {
return;
} else if (intersect == null) {
intersect = a;
return;
}
double[] tmp = new double[intersect.length];
}
}