blob: 85c12b5fd44c89ecc2febac186c11264c3b85f6a [file] [log] [blame]
package fieldinvar;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.FieldInvariant;
public class NullnessFieldInvar {
public class Super {
public final @Nullable Object o;
public @Nullable Object nonfinal = null;
public Super(@Nullable Object o) {
this.o = o;
}
}
@FieldInvariant(field = "o", qualifier = NonNull.class)
class Sub extends Super {
public final @Nullable Object subO;
public Sub(@NonNull Object o) {
super(o);
subO = null;
}
public Sub(@NonNull Object o, @Nullable Object subO) {
super(o);
this.subO = subO;
}
void test() {
@NonNull Object x1 = this.o;
@NonNull Object x2 = o;
@NonNull Object x3 = super.o;
}
}
class SubSub1 extends Sub {
public SubSub1(@NonNull Object o) {
super(o);
}
}
@FieldInvariant(
field = {"o", "subO"},
qualifier = NonNull.class)
class SubSub2 extends Sub {
public SubSub2(@NonNull Object o) {
super(o);
}
}
class Use {
void test(Super superO, Sub sub, SubSub1 subSub1, SubSub2 subSub2) {
// :: error: (assignment)
@NonNull Object x1 = superO.o;
@NonNull Object x2 = sub.o;
@NonNull Object x3 = subSub1.o;
// :: error: (assignment)
@NonNull Object x5 = sub.subO;
// :: error: (assignment)
@NonNull Object x6 = subSub1.subO;
@NonNull Object x7 = subSub2.subO;
}
<SP extends Super, SB extends Sub, SS1 extends SubSub1, SS2 extends SubSub2> void test2(
SP superO, SB sub, SS1 subSub1, SS2 subSub2) {
// :: error: (assignment)
@NonNull Object x1 = superO.o;
@NonNull Object x2 = sub.o;
@NonNull Object x3 = subSub1.o;
// :: error: (assignment)
@NonNull Object x5 = sub.subO;
// :: error: (assignment)
@NonNull Object x6 = subSub1.subO;
@NonNull Object x7 = subSub2.subO;
}
}
class SuperWithNonFinal {
@Nullable Object nonfinal = null;
}
// nonfinal isn't final
// :: error: (field.invariant.not.final)
@FieldInvariant(field = "nonfinal", qualifier = NonNull.class)
class SubSubInvalid extends SuperWithNonFinal {}
// field is declared in this class
// :: error: (field.invariant.not.found)
@FieldInvariant(field = "field", qualifier = NonNull.class)
class Invalid {
final Object field = new Object();
}
@FieldInvariant(
field = {"o", "subO"},
qualifier = NonNull.class)
class Shadowing extends SubSub2 {
@Nullable Object o;
@Nullable Object subO;
void test() {
// :: error: (assignment)
@NonNull Object x = o; // error
// :: error: (assignment)
@NonNull Object x2 = subO; // error
@NonNull Object x3 = super.o;
@NonNull Object x4 = super.subO;
}
public Shadowing() {
super("");
}
}
// inherits: @FieldInvariant(field = {"o", "subO"}, qualifier = NonNull.class)
class Inherits extends SubSub2 {
@Nullable Object o;
@Nullable Object subO;
void test() {
// :: error: (assignment)
@NonNull Object x = o; // error
// :: error: (assignment)
@NonNull Object x2 = subO; // error
@NonNull Object x3 = super.o;
@NonNull Object x4 = super.subO;
}
public Inherits() {
super("");
}
}
class Super2 {}
// :: error: (field.invariant.not.wellformed)
@FieldInvariant(
field = {},
qualifier = NonNull.class)
class Invalid1 extends Super2 {}
// :: error: (field.invariant.not.wellformed)
@FieldInvariant(
field = {"a", "b"},
qualifier = {NonNull.class, NonNull.class, NonNull.class})
class Invalid2 extends Super2 {}
// :: error: (field.invariant.not.found)
@FieldInvariant(field = "x", qualifier = NonNull.class)
class NoSuper {}
class SuperManyFields {
public final @Nullable Object field1 = null;
public final @Nullable Object field2 = null;
public final @Nullable Object field3 = null;
public final @Nullable Object field4 = null;
}
@FieldInvariant(
field = {"field1", "field2", "field3", "field4"},
qualifier = NonNull.class)
class SubManyFields extends SuperManyFields {
void test() {
field1.toString();
field2.toString();
field3.toString();
field4.toString();
}
}
}