use of org.checkerframework.dataflow.expression.Unknown in project checker-framework by typetools.
the class LockVisitor method getLockExpressions.
private List<LockExpression> getLockExpressions(boolean implicitThis, AnnotationMirror gbAnno, Tree tree) {
List<String> expressions = AnnotationUtils.getElementValueArray(gbAnno, atypeFactory.guardedByValueElement, String.class, Collections.emptyList());
if (expressions.isEmpty()) {
return Collections.emptyList();
}
TreePath currentPath = getCurrentPath();
TypeMirror enclosingType = TreeUtils.typeOf(TreePathUtil.enclosingClass(currentPath));
JavaExpression pseudoReceiver = JavaExpression.getPseudoReceiver(currentPath, enclosingType);
JavaExpression self;
if (implicitThis) {
self = pseudoReceiver;
} else if (TreeUtils.isExpressionTree(tree)) {
self = JavaExpression.fromTree((ExpressionTree) tree);
} else {
self = new Unknown(tree);
}
return CollectionsPlume.mapList(expression -> parseExpressionString(expression, currentPath, self), expressions);
}
use of org.checkerframework.dataflow.expression.Unknown in project checker-framework by typetools.
the class CreatesMustCallForElementSupplier method getCreatesMustCallForExpression.
/**
* Parses a single CreatesMustCallFor annotation. Clients should use {@link
* #getCreatesMustCallForExpressions(MethodInvocationNode, GenericAnnotatedTypeFactory,
* CreatesMustCallForElementSupplier)}, which handles the possibility of multiple such
* annotations, instead.
*
* @param createsMustCallFor a @CreatesMustCallFor annotation
* @param n the invocation of a reset method
* @param atypeFactory the type factory
* @param supplier a type factory that can supply the executable elements for CreatesMustCallFor
* and CreatesMustCallFor.List's value elements. Usually, you should just pass atypeFactory
* again. The arguments are different so that the given type factory's adherence to both
* protocols are checked by the type system.
* @return the Java expression representing the target, or null if the target is unparseable
*/
@Nullable
static JavaExpression getCreatesMustCallForExpression(AnnotationMirror createsMustCallFor, MethodInvocationNode n, GenericAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory, CreatesMustCallForElementSupplier supplier) {
// Unfortunately, there is no way to avoid passing the default string "this" here. The default
// must be hard-coded into the client, such as here. That is the price for the efficiency of not
// having to query the annotation definition (such queries are expensive).
String targetStrWithoutAdaptation = AnnotationUtils.getElementValue(createsMustCallFor, supplier.getCreatesMustCallForValueElement(), String.class, "this");
// TODO: find a way to also check if the target is a known tempvar, and if so return that. That
// should improve the quality of the error messages we give.
JavaExpression targetExpr;
try {
targetExpr = StringToJavaExpression.atMethodInvocation(targetStrWithoutAdaptation, n, atypeFactory.getChecker());
if (targetExpr instanceof Unknown) {
issueUnparseableError(n, atypeFactory, targetStrWithoutAdaptation);
return null;
}
} catch (JavaExpressionParseException e) {
issueUnparseableError(n, atypeFactory, targetStrWithoutAdaptation);
return null;
}
return targetExpr;
}
use of org.checkerframework.dataflow.expression.Unknown in project checker-framework by typetools.
the class LockAnnotatedTypeFactory method createDependentTypesHelper.
@Override
protected DependentTypesHelper createDependentTypesHelper() {
return new DependentTypesHelper(this) {
@Override
protected void reportErrors(Tree errorTree, List<DependentTypesError> errors) {
// If the error message is NOT_EFFECTIVELY_FINAL, then report
// lock.expression.not.final instead of expression.unparsable .
List<DependentTypesError> superErrors = new ArrayList<>(errors.size());
for (DependentTypesError error : errors) {
if (error.error.equals(NOT_EFFECTIVELY_FINAL)) {
checker.reportError(errorTree, "lock.expression.not.final", error.expression);
} else {
superErrors.add(error);
}
}
super.reportErrors(errorTree, superErrors);
}
@Override
protected boolean shouldPassThroughExpression(String expression) {
// There is no expression to use to replace <self> here, so just pass the expression along.
return super.shouldPassThroughExpression(expression) || LockVisitor.SELF_RECEIVER_PATTERN.matcher(expression).matches();
}
@Override
@Nullable
protected JavaExpression transform(JavaExpression javaExpr) {
if (javaExpr instanceof Unknown || isExpressionEffectivelyFinal(javaExpr)) {
return javaExpr;
}
// string.
return createError(javaExpr.toString(), NOT_EFFECTIVELY_FINAL);
}
};
}
use of org.checkerframework.dataflow.expression.Unknown in project checker-framework by typetools.
the class OffsetEquation method createOffsetFromNode.
/**
* Updates an offset equation from a Node.
*
* @param node the Node from which to create an offset equation
* @param factory an AnnotationTypeFactory
* @param eq an OffsetEquation to update
* @param op '+' or '-'
*/
private static void createOffsetFromNode(Node node, AnnotationProvider factory, OffsetEquation eq, char op) {
JavaExpression je = JavaExpression.fromNode(node);
if (je instanceof Unknown || je == null) {
if (node instanceof NumericalAdditionNode) {
createOffsetFromNode(((NumericalAdditionNode) node).getLeftOperand(), factory, eq, op);
createOffsetFromNode(((NumericalAdditionNode) node).getRightOperand(), factory, eq, op);
} else if (node instanceof NumericalSubtractionNode) {
createOffsetFromNode(((NumericalSubtractionNode) node).getLeftOperand(), factory, eq, op);
char other = op == '+' ? '-' : '+';
createOffsetFromNode(((NumericalSubtractionNode) node).getRightOperand(), factory, eq, other);
} else {
eq.error = node.toString();
}
} else {
eq.addTerm(op, je.toString());
}
}
use of org.checkerframework.dataflow.expression.Unknown in project checker-framework by typetools.
the class ValueTransfer method refineAtLengthAccess.
/**
* Transform @IntVal or @IntRange annotations of a array or string length into an @ArrayLen
* or @ArrayLenRange annotation for the array or string.
*
* @param lengthNode an invocation of method {@code length} or an access of the {@code length}
* field
* @param receiverNode the receiver of {@code lengthNode}
* @param store the store to update
*/
private void refineAtLengthAccess(Node lengthNode, Node receiverNode, CFStore store) {
JavaExpression lengthExpr = JavaExpression.fromNode(lengthNode);
// not marked @Pure, then do not refine.
if (lengthExpr instanceof Unknown) {
return;
}
CFValue value = store.getValue(lengthExpr);
if (value == null) {
return;
}
AnnotationMirror lengthAnno = getValueAnnotation(value);
if (lengthAnno == null) {
return;
}
if (AnnotationUtils.areSameByName(lengthAnno, ValueAnnotatedTypeFactory.BOTTOMVAL_NAME)) {
// If the length is bottom, then this is dead code, so the receiver type
// should also be bottom.
JavaExpression receiver = JavaExpression.fromNode(receiverNode);
store.insertValue(receiver, lengthAnno);
return;
}
RangeOrListOfValues rolv;
if (atypeFactory.isIntRange(lengthAnno)) {
rolv = new RangeOrListOfValues(atypeFactory.getRange(lengthAnno));
} else if (AnnotationUtils.areSameByName(lengthAnno, ValueAnnotatedTypeFactory.INTVAL_NAME)) {
List<Long> lengthValues = atypeFactory.getIntValues(lengthAnno);
rolv = new RangeOrListOfValues(RangeOrListOfValues.convertLongsToInts(lengthValues));
} else {
return;
}
AnnotationMirror newRecAnno = rolv.createAnnotation(atypeFactory);
AnnotationMirror oldRecAnno = getArrayOrStringAnnotation(receiverNode);
AnnotationMirror combinedRecAnno;
// with the facts known about its length using GLB.
if (oldRecAnno == null) {
combinedRecAnno = newRecAnno;
} else {
combinedRecAnno = hierarchy.greatestLowerBound(oldRecAnno, newRecAnno);
}
JavaExpression receiver = JavaExpression.fromNode(receiverNode);
store.insertValue(receiver, combinedRecAnno);
}
Aggregations