// Note that this file is a near duplicate in /nullness and /nullness-uninit
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.*;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
class RawTypes {
class Bad {
@NonNull String field;
public Bad() {
//:: error: (method.invocation.invalid)
this.init(); // error
//:: error: (method.invocation.invalid)
init(); // error
this.field = "field"; // valid
//:: error: (assignment.type.incompatible)
this.field = null; // error
field = "field"; // valid
//:: error: (assignment.type.incompatible)
field = null; // error
}
void init() {
output(this.field.length()); // valid
}
}
class A {
@NonNull String field;
public A() {
this.field = "field"; // valid
field = "field"; // valid
this.init(); // valid
init(); // valid
}
public void init(@Raw @UnknownInitialization A this) {
//:: error: (dereference.of.nullable)
output(this.field.length());
}
public void initExpl2(@Raw @UnknownInitialization A this) {
//:: error: (argument.type.incompatible)
output(this.field);
}
public void initImpl1(@Raw @UnknownInitialization A this) {
//:: error: (dereference.of.nullable)
output(field.length());
}
public void initImpl2(@Raw @UnknownInitialization A this) {
//:: error: (argument.type.incompatible)
output(field);
}
}
class B extends A {
@NonNull String otherField;
public B() {
super();
//:: error: (assignment.type.incompatible)
this.otherField = null; // error
this.otherField = "otherField"; // valid
}
@Override
public void init(@Raw @UnknownInitialization B this) {
//:: error: (dereference.of.nullable)
output(this.field.length()); // error (TODO: substitution)
super.init(); // valid
}
public void initImpl1(@Raw @UnknownInitialization B this) {
//:: error: (dereference.of.nullable)
output(field.length()); // error (TODO: substitution)
}
public void initExpl2(@Raw @UnknownInitialization B this) {
//:: error: (dereference.of.nullable)
output(this.otherField.length()); // error
}
public void initImpl2(@Raw @UnknownInitialization B this) {
//:: error: (dereference.of.nullable)
output(otherField.length()); // error
}
void other() {
init(); // valid
this.init(); // valid
}
void otherRaw(@Raw @UnknownInitialization B this) {
init(); // valid
this.init(); // valid
}
}
//:: error: (initialization.fields.uninitialized)
class C extends B {
@NonNull String[] strings;
@Override
public void init(@Raw @UnknownInitialization C this) {
//:: error: (dereference.of.nullable)
output(this.strings.length); // error
System.out.println(); // valid
}
}
// To test whether the argument is @NonNull and @NonRaw
static void output(@NonNull Object o) {}
class D extends C {
@Override
public void init(@Raw @UnknownInitialization D this) {
this.field = "s";
output(this.field.length());
}
}
class MyTest {
Integer i;
MyTest(int i) {
this.i = i;
}
void myTest(@Raw @UnknownInitialization MyTest this) {
//:: error: (unboxing.of.nullable)
i = i + 1;
}
}
class AllFieldsInitialized {
Integer elapsedMillis = 0;
Integer startTime = 0;
public AllFieldsInitialized() {
//:: error: (method.invocation.invalid)
nonRawMethod();
}
public void nonRawMethod() {}
}
//:: error: (initialization.fields.uninitialized)
class AFSIICell {
AllFieldsSetInInitializer afsii;
}
class AllFieldsSetInInitializer {
Integer elapsedMillis;
Integer startTime;
public AllFieldsSetInInitializer() {
elapsedMillis = 0;
//:: error: (method.invocation.invalid)
nonRawMethod(); // error
startTime = 0;
//:: error: (method.invocation.invalid)
nonRawMethod(); // error
//:: error: (initialization.invalid.field.write.initialized)
new AFSIICell().afsii = this;
}
//:: error: (initialization.fields.uninitialized)
public AllFieldsSetInInitializer(boolean b) {
//:: error: (method.invocation.invalid)
nonRawMethod(); // error
}
public void nonRawMethod() {}
}
class ConstructorInvocations {
Integer v;
public ConstructorInvocations(int v) {
this.v = v;
}
public ConstructorInvocations() {
this(0);
//:: error: (method.invocation.invalid)
nonRawMethod(); // invalid
}
public void nonRawMethod() {}
}
class MethodAccess {
public MethodAccess() {
@NonNull String s = string();
}
public @NonNull String string(@Raw @UnknownInitialization MethodAccess this) {
return "nonnull";
}
}
void cast(@Raw @UnknownInitialization Object... args) {
@SuppressWarnings("rawtypes")
//:: error: (assignment.type.incompatible)
Object[] argsNonRaw1 = args;
@SuppressWarnings("cast")
Object[] argsNonRaw2 = (Object[]) args;
}
class RawAfterConstructorBad {
Object o;
//:: error: (initialization.fields.uninitialized)
RawAfterConstructorBad() {}
}
class RawAfterConstructorOK1 {
@Nullable Object o;
RawAfterConstructorOK1() {}
}
class RawAfterConstructorOK2 {
Integer a;
//:: error: (initialization.fields.uninitialized)
RawAfterConstructorOK2() {}
}
// TODO: reinstate. This shows desired features, for initialization in
// a helper method rather than in the constructor.
class InitInHelperMethod {
Integer a;
Integer b;
InitInHelperMethod(short constructor_inits_ab) {
a = 1;
b = 1;
//:: error: (method.invocation.invalid)
nonRawMethod();
}
InitInHelperMethod(boolean constructor_inits_a) {
a = 1;
init_b();
//:: error: (method.invocation.invalid)
nonRawMethod();
}
@RequiresNonNull("a")
@EnsuresNonNull("b")
void init_b(@Raw @UnknownInitialization InitInHelperMethod this) {
b = 2;
//:: error: (method.invocation.invalid)
nonRawMethod();
}
InitInHelperMethod(int constructor_inits_none) {
init_ab();
//:: error: (method.invocation.invalid)
nonRawMethod();
}
@EnsuresNonNull({"a", "b"})
void init_ab(@Raw @UnknownInitialization InitInHelperMethod this) {
a = 1;
b = 2;
//:: error: (method.invocation.invalid)
nonRawMethod();
}
void nonRawMethod() {}
}
}