package org.checkerframework.checker.index.lowerbound; /*>>> import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; */ import com.sun.source.tree.ArrayAccessTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.NewArrayTree; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.index.qual.Positive; import org.checkerframework.common.basetype.BaseTypeChecker; import org.checkerframework.common.basetype.BaseTypeVisitor; import org.checkerframework.framework.source.Result; import org.checkerframework.framework.type.AnnotatedTypeMirror; /** * Implements the actual checks to make sure that array accesses aren't too low. Will issue a * warning if a variable that can't be proved to be either "NonNegative" (i.e. ≥ 0) or "Positive" * (i.e. ≥ 1) is used as an array index. */ public class LowerBoundVisitor extends BaseTypeVisitor<LowerBoundAnnotatedTypeFactory> { /* This is a key into the messages.properties file in the same * directory, which includes the actual text of the warning. */ private static final /*@CompilerMessageKey*/ String LOWER_BOUND = "array.access.unsafe.low"; private static final /*@CompilerMessageKey*/ String NEGATIVE_ARRAY = "array.length.negative"; public LowerBoundVisitor(BaseTypeChecker checker) { super(checker); } @Override public Void visitArrayAccess(ArrayAccessTree tree, Void type) { ExpressionTree index = tree.getIndex(); String arrName = tree.getExpression().toString(); AnnotatedTypeMirror indexType = atypeFactory.getAnnotatedType(index); if (!(indexType.hasAnnotation(NonNegative.class) || indexType.hasAnnotation(Positive.class))) { checker.report(Result.failure(LOWER_BOUND, indexType.toString(), arrName), index); } return super.visitArrayAccess(tree, type); } @Override public Void visitNewArray(NewArrayTree tree, Void type) { if (tree.getDimensions().size() > 0) { for (ExpressionTree dim : tree.getDimensions()) { AnnotatedTypeMirror dimType = atypeFactory.getAnnotatedType(dim); if (!(dimType.hasAnnotation(NonNegative.class) || dimType.hasAnnotation(Positive.class))) { checker.report(Result.failure(NEGATIVE_ARRAY, dimType.toString()), dim); } } } return super.visitNewArray(tree, type); } }