blob: 8e6bf8a41532fecce2f9d730d1b75f3fd836d507 [file] [log] [blame]
package org.checkerframework.checker.lock;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.Tree.Kind;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.javacutil.TypesUtils;
public class LockTreeAnnotator extends TreeAnnotator {
public LockTreeAnnotator(AnnotatedTypeFactory atypeFactory) {
super(atypeFactory);
}
@Override
public Void visitBinary(BinaryTree node, AnnotatedTypeMirror type) {
// For any binary operation whose LHS or RHS can be a non-boolean type, and whose resulting type
// is necessarily boolean, the resulting annotation on the boolean type must be @GuardedBy({}).
// There is no need to enforce that the annotation on the result of &&, ||, etc. is
// @GuardedBy({}) since for such operators, both operands are of type @GuardedBy({}) boolean to
// begin with.
if (isBinaryComparisonOrInstanceOfOperator(node.getKind())
|| TypesUtils.isString(type.getUnderlyingType())) {
// A boolean or String is always @GuardedBy({}). LockVisitor determines whether
// the LHS and RHS of this operation can be legally dereferenced.
type.replaceAnnotation(((LockAnnotatedTypeFactory) atypeFactory).GUARDEDBY);
return null;
}
return super.visitBinary(node, type);
}
/** Indicates that the result of the operation is a boolean value. */
private static boolean isBinaryComparisonOrInstanceOfOperator(Kind opKind) {
switch (opKind) {
case EQUAL_TO:
case NOT_EQUAL_TO:
// Technically, <=, <, > and >= are irrelevant for visitBinary, since currently
// boxed primitives cannot be annotated with @GuardedBy(...), but they are left here
// in case that rule changes.
case LESS_THAN:
case LESS_THAN_EQUAL:
case GREATER_THAN:
case GREATER_THAN_EQUAL:
case INSTANCE_OF:
return true;
default:
}
return false;
}
@Override
public Void visitCompoundAssignment(CompoundAssignmentTree node, AnnotatedTypeMirror type) {
if (TypesUtils.isString(type.getUnderlyingType())) {
type.replaceAnnotation(((LockAnnotatedTypeFactory) atypeFactory).GUARDEDBY);
}
return super.visitCompoundAssignment(node, type);
}
}