org.checkerframework.checker.index.searchindex.SearchIndexTransfer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of checker Show documentation
Show all versions of checker Show documentation
The Checker Framework enhances Java's type system to
make it more powerful and useful. This lets software developers
detect and prevent errors in their Java programs.
The Checker Framework includes compiler plug-ins ("checkers")
that find bugs or verify their absence. It also permits you to
write your own compiler plug-ins.
package org.checkerframework.checker.index.searchindex;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.checker.index.IndexAbstractTransfer;
import org.checkerframework.checker.index.IndexUtil;
import org.checkerframework.checker.index.qual.NegativeIndexFor;
import org.checkerframework.checker.index.qual.SearchIndexFor;
import org.checkerframework.dataflow.analysis.FlowExpressions;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.framework.flow.CFAnalysis;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFValue;
/**
* The transfer function for the SearchIndexFor checker. Allows {@link SearchIndexFor} to be refined
* to {@link NegativeIndexFor}.
*/
public class SearchIndexTransfer extends IndexAbstractTransfer {
// The ATF (Annotated Type Factory).
private SearchIndexAnnotatedTypeFactory aTypeFactory;
public SearchIndexTransfer(CFAnalysis analysis) {
super(analysis);
aTypeFactory = (SearchIndexAnnotatedTypeFactory) analysis.getTypeFactory();
}
/**
* If a {@link SearchIndexFor} value is negative, then refine it to {@link NegativeIndexFor}.
* This method is called by refinement rules for binary comparison operators.
*
* If the left value (in a greater-than or greater-than-or-equal binary comparison) is
* exactly the value of {@code valueToCompareTo}, and the right side has type {@link
* SearchIndexFor}, then the right side's new value in the store should become {@link
* NegativeIndexFor}.
*
*
For example, this allows the following code to typecheck:
*
*
*
* {@literal @}SearchIndexFor("a") int index = Arrays.binarySearch(a, y);
* if (index < 0) {
* {@literal @}NegativeIndexFor("a") int negInsertionPoint = index;
* }
*
*
*
* @param valueToCompareTo this value must be 0 (for greater than or less than) or -1 (for
* greater than or equal or less than or equal)
*/
private void refineSearchIndexToNegativeIndexFor(
Node left, Node right, CFStore store, int valueToCompareTo) {
assert valueToCompareTo == 0 || valueToCompareTo == -1;
Long leftValue =
IndexUtil.getExactValue(
left.getTree(), aTypeFactory.getValueAnnotatedTypeFactory());
if (leftValue != null && leftValue == valueToCompareTo) {
AnnotationMirror rightSI =
aTypeFactory.getAnnotationMirror(right.getTree(), SearchIndexFor.class);
if (rightSI != null) {
List arrays = IndexUtil.getValueOfAnnotationWithStringArgument(rightSI);
AnnotationMirror nif = aTypeFactory.createNegativeIndexFor(arrays);
store.insertValue(
FlowExpressions.internalReprOf(analysis.getTypeFactory(), right), nif);
}
}
}
@Override
protected void refineGT(
Node left,
AnnotationMirror leftAnno,
Node right,
AnnotationMirror rightAnno,
CFStore store,
TransferInput in) {
refineSearchIndexToNegativeIndexFor(left, right, store, 0);
}
@Override
protected void refineGTE(
Node left,
AnnotationMirror leftAnno,
Node right,
AnnotationMirror rightAnno,
CFStore store,
TransferInput in) {
refineSearchIndexToNegativeIndexFor(left, right, store, -1);
}
}