package checkers.linear; import javax.lang.model.element.Element; import com.sun.source.tree.*; import checkers.basetype.BaseTypeVisitor; import checkers.linear.quals.Unusable; import checkers.source.Result; import checkers.types.AnnotatedTypeMirror.AnnotatedExecutableType; import checkers.util.TreeUtils; /** * A type-checking visitor for the Linear type system. The visitor reports * an error ("unsafe.use") for any use of a reference of {@link Unusable} * type. In other words, it reports an error for any {@code Linear} * references that is used more than once, or is used after it has been * "used up". * * @see LinearChecker */ public class LinearVisitor extends BaseTypeVisitor<Void, Void> { public LinearVisitor(LinearChecker checker, CompilationUnitTree root) { super(checker, root); } /** * Return true if the node represents a reference to a local variable * or parameter. * * In Linear Checker, only local variables and method parameters can be * of {@link Linear} or {@link Unusable} types. * * @param node a tree * @return true if node is a local variable or parameter reference */ static boolean isLocalVarOrParam(ExpressionTree node) { Element elem = TreeUtils.elementFromUse(node); if (elem == null) return false; switch (elem.getKind()) { case PARAMETER: case LOCAL_VARIABLE: return true; default: return false; } } /** * Issue an error if the node represents a reference that has been used up. */ private void checkLegality(ExpressionTree node) { if (isLocalVarOrParam(node)) { if (atypeFactory.getAnnotatedType(node).hasAnnotation(Unusable.class)) { checker.report(Result.failure("use.unsafe", TreeUtils.elementFromUse(node), node), node); } } } @Override public Void visitIdentifier(IdentifierTree node, Void p) { checkLegality(node); return super.visitIdentifier(node, p); } @Override public Void visitMemberSelect(MemberSelectTree node, Void p) { checkLegality(node); return super.visitMemberSelect(node, p); } /** * Linear Checker does not contain a rule for method invocation. */ // Premature optimization: Don't check method invocability protected boolean checkMethodInvocability(AnnotatedExecutableType method, MethodInvocationTree node) { return true; } }