blob: e48a931d24182263cf40a5a97d75aa5b4aabb2e5 [file] [log] [blame]
import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.dataflow.qual.Pure;
public class RequiresNonNullTest {
@Nullable Object field1;
@Nullable Object field2;
@RequiresNonNull("field1")
void method1() {
field1.toString(); // OK, field1 is known to be non-null
this.field1.toString(); // OK, field1 is known to be non-null
// :: error: (dereference.of.nullable)
field2.toString(); // error, might throw NullPointerException
}
@RequiresNonNull("field1")
void method1also() {
// ok, precondition satisfied by NNOE
method1();
}
void method2() {
field1 = new Object();
method1(); // OK, satisfies method precondition
field1 = null;
// :: error: (contracts.precondition)
method1(); // error, does not satisfy method precondition
}
protected @Nullable Object field;
@RequiresNonNull("field")
public void requiresNonNullField() {}
public void clientFail(RequiresNonNullTest arg1) {
// :: error: (contracts.precondition)
arg1.requiresNonNullField();
}
public void clientOK(RequiresNonNullTest arg2) {
arg2.field = new Object();
// note that the following line works
@NonNull Object o = arg2.field;
arg2.requiresNonNullField(); // OK, field is known to be non-null
}
// TODO: forbid the field in @NNOE to be less visible than the method
protected static @Nullable Object staticfield;
@Pure
@RequiresNonNull("staticfield")
// :: warning: (purity.deterministic.void.method)
public void reqStaticName() {
reqStaticQualName();
}
@Pure
@RequiresNonNull("RequiresNonNullTest.staticfield")
// :: warning: (purity.deterministic.void.method)
public void reqStaticQualName() {
reqStaticName();
}
public void statClientOK(RequiresNonNullTest arg1) {
staticfield = new Object();
arg1.reqStaticName();
staticfield = new Object();
arg1.reqStaticQualName();
RequiresNonNullTest.staticfield = new Object();
arg1.reqStaticName();
RequiresNonNullTest.staticfield = new Object();
arg1.reqStaticQualName();
}
public void statClientFail(RequiresNonNullTest arg1) {
// :: error: (contracts.precondition)
arg1.reqStaticName();
// :: error: (contracts.precondition)
arg1.reqStaticQualName();
}
class NNOESubTest extends RequiresNonNullTest {
public void subClientOK(NNOESubTest arg3) {
arg3.field = new Object();
arg3.requiresNonNullField();
}
public void subClientFail(NNOESubTest arg4) {
// :: error: (contracts.precondition)
arg4.requiresNonNullField();
}
public void subStat(NNOESubTest arg5) {
RequiresNonNullTest.staticfield = new Object();
arg5.reqStaticQualName();
staticfield = new Object();
arg5.reqStaticQualName();
NNOESubTest.staticfield = new Object();
arg5.reqStaticQualName();
}
}
private @Nullable Object notHidden;
class NNOEHidingTest extends RequiresNonNullTest {
protected @Nullable String field;
public void hidingClient1(NNOEHidingTest arg5) {
arg5.field = "ha!";
// TODO: The error message should say something about the hidden field.
// :: error: (contracts.precondition)
arg5.requiresNonNullField();
// TODO: Add test like:
// arg5.ensuresNonNullField();
// arg5.requiresNonNullField();
}
public void hidingClient2(NNOEHidingTest arg6) {
// :: error: (contracts.precondition)
arg6.requiresNonNullField();
}
protected @Nullable Object notHidden;
@RequiresNonNull("notHidden")
void notHiddenTest() {
// the field in the superclass is private -> don't complain about hiding
}
}
static @Nullable Object o = "m";
@RequiresNonNull("o")
void test() {
o = null;
}
@RequiresNonNull("thisShouldIssue1Error")
// Test case for Issue 1051
// https://github.com/typetools/checker-framework/issues/1051
// :: error: (flowexpr.parse.error)
void testIssue1051() {}
}