use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class BaseTypeVisitor method parseAndLocalizeContracts.
/**
* Localizes some contracts -- that is, viewpoint-adapts them to some method body, according to
* the value of {@link #methodTree}.
*
* <p>The input is a set of {@link Contract}s, each of which contains an expression string and an
* annotation. In a {@link Contract}, Java expressions are exactly as written in source code, not
* standardized or viewpoint-adapted.
*
* <p>The output is a set of pairs of {@link JavaExpression} (parsed expression string) and
* standardized annotation (with respect to the path of {@link #methodTree}. This method discards
* any contract whose expression cannot be parsed into a JavaExpression.
*
* @param contractSet a set of contracts
* @param methodType the type of the method that the contracts are for
* @return pairs of (expression, AnnotationMirror), which are localized contracts
*/
private Set<Pair<JavaExpression, AnnotationMirror>> parseAndLocalizeContracts(Set<? extends Contract> contractSet, AnnotatedExecutableType methodType) {
if (contractSet.isEmpty()) {
return Collections.emptySet();
}
// This is the path to a place where the contract is being used, which might or might not be
// where the contract was defined. For example, methodTree might be an overriding
// definition, and the contract might be for a superclass.
MethodTree methodTree = this.methodTree;
StringToJavaExpression stringToJavaExpr = expression -> {
JavaExpression javaExpr = StringToJavaExpression.atMethodDecl(expression, methodType.getElement(), checker);
// viewpoint-adapt it to methodTree.
return javaExpr.atMethodBody(methodTree);
};
Set<Pair<JavaExpression, AnnotationMirror>> result = new HashSet<>(contractSet.size());
for (Contract p : contractSet) {
String expressionString = p.expressionString;
AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(atypeFactory, stringToJavaExpr, methodTree);
JavaExpression exprJe;
try {
// TODO: currently, these expressions are parsed many times.
// This could be optimized to store the result the first time.
// (same for other annotations)
exprJe = stringToJavaExpr.toJavaExpression(expressionString);
} catch (JavaExpressionParseException e) {
// report errors here
checker.report(methodTree, e.getDiagMessage());
continue;
}
result.add(Pair.of(exprJe, annotation));
}
return result;
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class ValueAnnotatedTypeFactory method getMinLenFromString.
/**
* Returns the minimum length of an array expression or 0 if the min length is unknown.
*
* @param sequenceExpression Java expression
* @param tree expression tree or variable declaration
* @param currentPath path to local scope
* @return min length of sequenceExpression or 0
*/
public int getMinLenFromString(String sequenceExpression, Tree tree, TreePath currentPath) {
AnnotationMirror lengthAnno;
JavaExpression expressionObj;
try {
expressionObj = parseJavaExpressionString(sequenceExpression, currentPath);
} catch (JavaExpressionParseException e) {
// ignore parse errors and return 0.
return 0;
}
if (expressionObj instanceof ValueLiteral) {
ValueLiteral sequenceLiteral = (ValueLiteral) expressionObj;
Object sequenceLiteralValue = sequenceLiteral.getValue();
if (sequenceLiteralValue instanceof String) {
return ((String) sequenceLiteralValue).length();
}
} else if (expressionObj instanceof ArrayCreation) {
ArrayCreation arrayCreation = (ArrayCreation) expressionObj;
// This is only expected to support array creations in varargs methods
return arrayCreation.getInitializers().size();
} else if (expressionObj instanceof ArrayAccess) {
List<? extends AnnotationMirror> annoList = expressionObj.getType().getAnnotationMirrors();
for (AnnotationMirror anno : annoList) {
String ANNO_NAME = AnnotationUtils.annotationName(anno);
if (ANNO_NAME.equals(MINLEN_NAME)) {
return getMinLenValue(canonicalAnnotation(anno));
} else if (ANNO_NAME.equals(ARRAYLEN_NAME) || ANNO_NAME.equals(ARRAYLENRANGE_NAME)) {
return getMinLenValue(anno);
}
}
}
lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, ArrayLenRange.class);
if (lengthAnno == null) {
lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, ArrayLen.class);
}
if (lengthAnno == null) {
lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, StringVal.class);
}
if (lengthAnno == null) {
// Could not find a more precise type, so return 0;
return 0;
}
return getMinLenValue(lengthAnno);
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class ValueTransfer method addAnnotationToStore.
private void addAnnotationToStore(CFStore store, AnnotationMirror anno, Node node) {
// If node is assignment, iterate over lhs and rhs; otherwise, iterator contains just node.
for (Node internal : splitAssignments(node)) {
JavaExpression je = JavaExpression.fromNode(internal);
CFValue currentValueFromStore;
if (CFAbstractStore.canInsertJavaExpression(je)) {
currentValueFromStore = store.getValue(je);
} else {
// Don't just `continue;` which would skip the calls to refine{Array,String}...
currentValueFromStore = null;
}
AnnotationMirror currentAnno = (currentValueFromStore == null ? atypeFactory.UNKNOWNVAL : getValueAnnotation(currentValueFromStore));
// Combine the new annotations based on the results of the comparison with the existing type.
AnnotationMirror newAnno = hierarchy.greatestLowerBound(anno, currentAnno);
store.insertValue(je, newAnno);
if (node instanceof FieldAccessNode) {
refineArrayAtLengthAccess((FieldAccessNode) internal, store);
} else if (node instanceof MethodInvocationNode) {
MethodInvocationNode miNode = (MethodInvocationNode) node;
refineAtLengthInvocation(miNode, store);
}
}
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class JavaExpressionOptimizer method visitMethodCall.
@Override
protected JavaExpression visitMethodCall(MethodCall methodCallExpr, Void unused) {
JavaExpression optReceiver = convert(methodCallExpr.getReceiver());
List<JavaExpression> optArguments = convert(methodCallExpr.getArguments());
// Length of string literal: convert it to an integer literal.
if (methodCallExpr.getElement().getSimpleName().contentEquals("length") && optReceiver instanceof ValueLiteral) {
Object value = ((ValueLiteral) optReceiver).getValue();
if (value instanceof String) {
return new ValueLiteral(factory.types.getPrimitiveType(TypeKind.INT), ((String) value).length());
}
}
return new MethodCall(methodCallExpr.getType(), methodCallExpr.getElement(), optReceiver, optArguments);
}
use of org.checkerframework.dataflow.expression.JavaExpression in project checker-framework by typetools.
the class I18nFormatterTransfer method visitMethodInvocation.
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode node, TransferInput<CFValue, CFStore> in) {
I18nFormatterAnnotatedTypeFactory atypeFactory = (I18nFormatterAnnotatedTypeFactory) analysis.getTypeFactory();
TransferResult<CFValue, CFStore> result = super.visitMethodInvocation(node, in);
I18nFormatterTreeUtil tu = atypeFactory.treeUtil;
// If hasFormat is called, make sure that the format string is annotated correctly
if (tu.isHasFormatCall(node, atypeFactory)) {
CFStore thenStore = result.getRegularStore();
CFStore elseStore = thenStore.copy();
ConditionalTransferResult<CFValue, CFStore> newResult = new ConditionalTransferResult<>(result.getResultValue(), thenStore, elseStore);
Result<I18nConversionCategory[]> cats = tu.getHasFormatCallCategories(node);
if (cats.value() == null) {
tu.failure(cats, "i18nformat.indirect.arguments");
} else {
JavaExpression firstParam = JavaExpression.fromNode(node.getArgument(0));
AnnotationMirror anno = atypeFactory.treeUtil.categoriesToFormatAnnotation(cats.value());
thenStore.insertValue(firstParam, anno);
}
return newResult;
}
// If isFormat is called, annotate the format string with I18nInvalidFormat
if (tu.isIsFormatCall(node, atypeFactory)) {
CFStore thenStore = result.getRegularStore();
CFStore elseStore = thenStore.copy();
ConditionalTransferResult<CFValue, CFStore> newResult = new ConditionalTransferResult<>(result.getResultValue(), thenStore, elseStore);
JavaExpression firstParam = JavaExpression.fromNode(node.getArgument(0));
AnnotationBuilder builder = new AnnotationBuilder(tu.processingEnv, I18nInvalidFormat.class);
// No need to set a value of @I18nInvalidFormat
builder.setValue("value", "");
elseStore.insertValue(firstParam, builder.build());
return newResult;
}
// corresponding key's value.
if (tu.isMakeFormatCall(node, atypeFactory)) {
Result<I18nConversionCategory[]> cats = tu.makeFormatCallCategories(node, atypeFactory);
if (cats.value() == null) {
tu.failure(cats, "i18nformat.key.not.found");
} else {
AnnotationMirror anno = atypeFactory.treeUtil.categoriesToFormatAnnotation(cats.value());
CFValue newResultValue = analysis.createSingleAnnotationValue(anno, result.getResultValue().getUnderlyingType());
return new RegularTransferResult<>(newResultValue, result.getRegularStore());
}
}
return result;
}
Aggregations