import net.jcip.annotations.GuardedBy;
import org.checkerframework.checker.lock.qual.GuardSatisfied;
import org.checkerframework.checker.lock.qual.Holding;
import org.checkerframework.checker.lock.qual.LockingFree;
// Smoke test for supporting JCIP and Javax annotations.
// Note that JCIP and Javax @GuardedBy can only be written on fields and methods.
public class JCIPAnnotations {
class MyClass {
Object field;
@LockingFree
void methodWithUnguardedReceiver() {}
@LockingFree
void methodWithGuardedReceiver(
@org.checkerframework.checker.lock.qual.GuardedBy("lock") MyClass this) {}
@LockingFree
void methodWithGuardSatisfiedReceiver(@GuardSatisfied MyClass this) {}
}
final Object lock = new Object();
@GuardedBy("lock") MyClass jcipGuardedField;
@javax.annotation.concurrent.GuardedBy("lock") MyClass javaxGuardedField;
// Tests that Javax and JCIP @GuardedBy(...) typecheck against the Lock Checker @GuardedBy on a receiver.
void testReceivers() {
//:: error: (method.invocation.invalid)
jcipGuardedField.methodWithUnguardedReceiver();
jcipGuardedField.methodWithGuardedReceiver();
//:: error: (lock.not.held)
jcipGuardedField.methodWithGuardSatisfiedReceiver();
//:: error: (method.invocation.invalid)
javaxGuardedField.methodWithUnguardedReceiver();
javaxGuardedField.methodWithGuardedReceiver();
//:: error: (lock.not.held)
javaxGuardedField.methodWithGuardSatisfiedReceiver();
}
void testDereferences() {
//:: error: (lock.not.held)
this.jcipGuardedField.field.toString();
//:: error: (lock.not.held)
this.javaxGuardedField.field.toString();
synchronized (lock) {
this.jcipGuardedField.field.toString();
this.javaxGuardedField.field.toString();
}
}
@GuardedBy("lock")
void testGuardedByAsHolding() {
this.jcipGuardedField.field.toString();
this.javaxGuardedField.field.toString();
jcipGuardedField.field.toString();
javaxGuardedField.field.toString();
}
@GuardedBy("lock") Object testGuardedByAsHolding2(
@org.checkerframework.checker.lock.qual.GuardedBy({}) Object param) {
testGuardedByAsHolding();
// Test that the JCIP GuardedBy applies to the method but not the return type.
return param;
}
void testGuardedByAsHolding3() {
synchronized (lock) {
testGuardedByAsHolding();
}
//:: error: (contracts.precondition.not.satisfied)
testGuardedByAsHolding();
}
@Holding("lock")
@GuardedBy("lock")
//:: error: (multiple.lock.precondition.annotations)
void testMultipleMethodAnnotations1() {}
@Holding("lock")
@javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.lock.precondition.annotations)
void testMultipleMethodAnnotations2() {}
@GuardedBy("lock") @javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.lock.precondition.annotations)
void testMultipleMethodAnnotations3() {}
@Holding("lock")
@GuardedBy("lock") @javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.lock.precondition.annotations)
void testMultipleMethodAnnotations4() {}
@org.checkerframework.checker.lock.qual.GuardedBy("lock") @GuardedBy("lock")
//:: error: (multiple.guardedby.annotations)
Object fieldWithMultipleGuardedByAnnotations1;
@org.checkerframework.checker.lock.qual.GuardedBy("lock") @javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.guardedby.annotations)
Object fieldWithMultipleGuardedByAnnotations2;
@GuardedBy("lock") @javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.guardedby.annotations)
Object fieldWithMultipleGuardedByAnnotations3;
@org.checkerframework.checker.lock.qual.GuardedBy("lock") @GuardedBy("lock") @javax.annotation.concurrent.GuardedBy("lock")
//:: error: (multiple.guardedby.annotations)
Object fieldWithMultipleGuardedByAnnotations4;
}