use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException 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.framework.util.JavaExpressionParseUtil.JavaExpressionParseException 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.framework.util.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class CFAbstractTransfer method addInformationFromPreconditions.
/**
* Add the information from all the preconditions of a method to the initial store in the method
* body.
*
* @param initialStore the initial store for the method body
* @param factory the type factory
* @param methodAst the AST for a method declaration
* @param methodDeclTree the declaration of the method; is a field of {@code methodAst}
* @param methodElement the element for the method
*/
protected void addInformationFromPreconditions(S initialStore, AnnotatedTypeFactory factory, CFGMethod methodAst, MethodTree methodDeclTree, ExecutableElement methodElement) {
ContractsFromMethod contractsUtils = analysis.atypeFactory.getContractsFromMethod();
Set<Precondition> preconditions = contractsUtils.getPreconditions(methodElement);
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
for (Precondition p : preconditions) {
String stringExpr = p.expressionString;
AnnotationMirror annotation = p.viewpointAdaptDependentTypeAnnotation(analysis.atypeFactory, stringToJavaExpr, /*errorTree=*/
null);
JavaExpression exprJe;
try {
// TODO: currently, these expressions are parsed at the declaration (i.e. here) and for
// every use. this could be optimized to store the result the first time.
// (same for other annotations)
exprJe = StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, analysis.checker);
} catch (JavaExpressionParseException e) {
// Errors are reported by BaseTypeVisitor.checkContractsAtMethodDeclaration().
continue;
}
initialStore.insertValuePermitNondeterministic(exprJe, annotation);
}
}
use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class LockVisitor method parseExpressionString.
/**
* Parse a Java expression.
*
* @param expression the Java expression
* @param path the path to the expression
* @param itself the self expression
* @return the parsed expression
*/
private LockExpression parseExpressionString(String expression, TreePath path, JavaExpression itself) {
LockExpression lockExpression = new LockExpression(expression);
if (DependentTypesError.isExpressionError(expression)) {
lockExpression.error = DependentTypesError.unparse(expression);
return lockExpression;
}
Matcher selfReceiverMatcher = SELF_RECEIVER_PATTERN.matcher(expression);
try {
if (selfReceiverMatcher.matches()) {
String remainingExpression = selfReceiverMatcher.group(2);
if (remainingExpression == null || remainingExpression.isEmpty()) {
lockExpression.lockExpression = itself;
if (!atypeFactory.isExpressionEffectivelyFinal(lockExpression.lockExpression)) {
checker.reportError(path.getLeaf(), "lock.expression.not.final", lockExpression.lockExpression);
}
return lockExpression;
} else {
lockExpression.lockExpression = StringToJavaExpression.atPath(itself.toString() + "." + remainingExpression, path, checker);
if (!atypeFactory.isExpressionEffectivelyFinal(lockExpression.lockExpression)) {
checker.reportError(path.getLeaf(), "lock.expression.not.final", lockExpression.lockExpression);
}
return lockExpression;
}
} else {
lockExpression.lockExpression = StringToJavaExpression.atPath(expression, path, checker);
return lockExpression;
}
} catch (JavaExpressionParseException ex) {
lockExpression.error = new DependentTypesError(expression, ex);
return lockExpression;
}
}
use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException 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;
}
Aggregations