import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.dataflow.qual.Pure;
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.not.satisfied)
method1(); // error, does not satisfy method precondition
}
protected @Nullable Object field;
@RequiresNonNull("field")
public void requiresNonNullField() {}
public void clientFail(RequiresNonNullTest arg1) {
//:: error: (contracts.precondition.not.satisfied)
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.not.satisfied)
arg1.reqStaticName();
//:: error: (contracts.precondition.not.satisfied)
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.not.satisfied)
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!";
/* We should be testing that the Object "field" from the superclass
* is non-null. We currently only match on the field name and do not
* handle hiding correctly. Instead, we output an error, if we
* detect that hiding happened.
* TODO: correctly resolve hidden fields.
*/
arg5.requiresNonNullField();
}
public void hidingClient2(NNOEHidingTest arg6) {
//:: error: (contracts.precondition.not.satisfied)
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() {}
}