use of org.checkerframework.framework.util.StringToJavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method atFieldAccess.
/**
* Viewpoint-adapts the Java expressions in annotations written on a field declaration to the use
* at {@code fieldAccess}.
*
* @param type its type; is side-effected by this method
* @param fieldAccess a field access
*/
public void atFieldAccess(AnnotatedTypeMirror type, MemberSelectTree fieldAccess) {
if (!hasDependentType(type)) {
return;
}
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atFieldAccess(stringExpr, fieldAccess, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atFieldAccess(%s, %s) created %s%n", type, TreeUtils.toStringTruncated(fieldAccess, 65), stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, type);
}
use of org.checkerframework.framework.util.StringToJavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method delocalize.
/**
* Viewpoint-adapt all dependent type annotations to the method declaration, {@code
* methodDeclTree}. This method changes occurrences of formal parameter names to the "#2" syntax,
* and it removes expressions that contain other local variables.
*
* <p>If a Java expression in {@code atm} references local variables (other than formal
* parameters), the expression is removed from the annotation. This could result in dependent type
* annotations with empty lists of expressions. If this is a problem, a subclass can override
* {@link #buildAnnotation(AnnotationMirror, Map)} to do something besides creating an annotation
* with a empty list.
*
* @param atm type to viewpoint-adapt; is side-effected by this method
* @param methodDeclTree the method declaration to which the annotations are viewpoint-adapted
*/
public void delocalize(AnnotatedTypeMirror atm, MethodTree methodDeclTree) {
if (!hasDependentType(atm)) {
return;
}
TreePath pathToMethodDecl = factory.getPath(methodDeclTree);
ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodDeclTree);
List<FormalParameter> parameters = JavaExpression.getFormalParameters(methodElement);
List<JavaExpression> paramsAsLocals = JavaExpression.getParametersAsLocalVariables(methodElement);
StringToJavaExpression stringToJavaExpr = expression -> {
JavaExpression javaExpr;
try {
javaExpr = StringToJavaExpression.atPath(expression, pathToMethodDecl, factory.getChecker());
} catch (JavaExpressionParseException ex) {
return null;
}
JavaExpressionConverter jec = new JavaExpressionConverter() {
@Override
protected JavaExpression visitLocalVariable(LocalVariable localVarExpr, Void unused) {
int index = paramsAsLocals.indexOf(localVarExpr);
if (index == -1) {
throw new FoundLocalException();
}
return parameters.get(index);
}
};
try {
return jec.convert(javaExpr);
} catch (FoundLocalException ex) {
return null;
}
};
if (debugStringToJavaExpression) {
System.out.printf("delocalize(%s, %s) created %s%n", atm, TreeUtils.toStringTruncated(methodDeclTree, 65), stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, atm);
}
use of org.checkerframework.framework.util.StringToJavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method checkTypeVariablesForErrorExpressions.
/**
* Reports an expression.unparsable error for each Java expression in the given type variables
* that is an expression error string.
*
* @param node a method declaration
* @param methodType annotated type of the method
*/
private void checkTypeVariablesForErrorExpressions(MethodTree node, AnnotatedExecutableType methodType) {
for (int i = 0; i < methodType.getTypeVariables().size(); i++) {
AnnotatedTypeMirror atm = methodType.getTypeVariables().get(i);
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, node, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("checkTypeVariablesForErrorExpressions(%s, %s) created %s%n", node, methodType, stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, atm);
checkTypeForErrorExpressions(atm, node.getTypeParameters().get(i));
}
}
use of org.checkerframework.framework.util.StringToJavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method convertAnnotationMirror.
/**
* Given an annotation {@code anno}, this method builds a new annotation with the Java expressions
* transformed according to {@code stringToJavaExpr}. If {@code anno} is not a dependent type
* annotation, {@code null} is returned.
*
* <p>If {@code stringToJavaExpr} returns {@code null}, then that expression is removed from the
* returned annotation.
*
* <p>Instead of overriding this method, subclasses can override the following methods to change
* the behavior of this class:
*
* <ul>
* <li>{@link #shouldPassThroughExpression(String)}: to control which expressions are skipped.
* If this method returns true, then the expression string is not parsed and is included in
* the new annotation unchanged.
* <li>{@link #transform(JavaExpression)}: make changes to the JavaExpression produced by {@code
* stringToJavaExpr}.
* <li>{@link #buildAnnotation(AnnotationMirror, Map)}: to change the annotation returned by
* this method.
* </ul>
*
* @param stringToJavaExpr function that converts strings to {@code JavaExpression}s
* @param anno annotation mirror
* @return an annotation created by applying {@code stringToJavaExpr} to all expression strings in
* {@code anno}, or null if there would be no effect
*/
@Nullable
public AnnotationMirror convertAnnotationMirror(StringToJavaExpression stringToJavaExpr, AnnotationMirror anno) {
if (!isExpressionAnno(anno)) {
return null;
}
Map<ExecutableElement, List<JavaExpression>> newElements = new HashMap<>();
for (ExecutableElement element : getListOfExpressionElements(anno)) {
List<String> expressionStrings = AnnotationUtils.getElementValueArray(anno, element, String.class, Collections.emptyList());
List<JavaExpression> javaExprs = new ArrayList<>(expressionStrings.size());
newElements.put(element, javaExprs);
for (String expression : expressionStrings) {
JavaExpression result;
if (shouldPassThroughExpression(expression)) {
result = new PassThroughExpression(objectTM, expression);
} else {
try {
result = stringToJavaExpr.toJavaExpression(expression);
} catch (JavaExpressionParseException e) {
result = createError(expression, e);
}
}
if (result != null) {
result = transform(result);
javaExprs.add(result);
}
}
}
return buildAnnotation(anno, newElements);
}
use of org.checkerframework.framework.util.StringToJavaExpression in project checker-framework by typetools.
the class DependentTypesHelper method atVariableDeclaration.
/**
* Standardize the Java expressions in annotations in a variable declaration. Converts the
* parameter syntax, e.g "#1", to the parameter name.
*
* @param type the type of the variable declaration; is side-effected by this method
* @param declarationTree the variable declaration
* @param variableElt the element of the variable declaration
*/
public void atVariableDeclaration(AnnotatedTypeMirror type, Tree declarationTree, VariableElement variableElt) {
if (!hasDependentType(type)) {
return;
}
TreePath pathToVariableDecl = factory.getPath(declarationTree);
if (pathToVariableDecl == null) {
// If this is a synthetic created by dataflow, the path will be null.
return;
}
ElementKind variableKind = variableElt.getKind();
if (ElementUtils.isBindingVariable(variableElt)) {
// Treat binding variables the same as local variables.
variableKind = ElementKind.LOCAL_VARIABLE;
}
switch(variableKind) {
case PARAMETER:
TreePath pathTillEnclTree = TreePathUtil.pathTillOfKind(pathToVariableDecl, METHOD_OR_LAMBDA);
if (pathTillEnclTree == null) {
throw new BugInCF("no enclosing method or lambda found for " + variableElt);
}
Tree enclTree = pathTillEnclTree.getLeaf();
if (enclTree.getKind() == Tree.Kind.METHOD) {
MethodTree methodDeclTree = (MethodTree) enclTree;
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodDeclTree, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atVariableDeclaration(%s, %s, %s) 1 created %s%n", type, TreeUtils.toStringTruncated(declarationTree, 65), variableElt, stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, type);
} else {
// Lambdas can use local variables defined in the enclosing method, so allow
// identifiers to be locals in scope at the location of the lambda.
StringToJavaExpression stringToJavaExpr = stringExpr -> StringToJavaExpression.atLambdaParameter(stringExpr, (LambdaExpressionTree) enclTree, pathToVariableDecl.getParentPath(), factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atVariableDeclaration(%s, %s, %s) 2 created %s%n", type, TreeUtils.toStringTruncated(declarationTree, 65), variableElt, stringToJavaExpr);
}
convertAnnotatedTypeMirror(stringToJavaExpr, type);
}
break;
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
StringToJavaExpression stringToJavaExprVar = stringExpr -> StringToJavaExpression.atPath(stringExpr, pathToVariableDecl, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atVariableDeclaration(%s, %s, %s) 3 created %s%n", type, TreeUtils.toStringTruncated(declarationTree, 65), variableElt, stringToJavaExprVar);
}
convertAnnotatedTypeMirror(stringToJavaExprVar, type);
break;
case FIELD:
case ENUM_CONSTANT:
StringToJavaExpression stringToJavaExprField = stringExpr -> StringToJavaExpression.atFieldDecl(stringExpr, variableElt, factory.getChecker());
if (debugStringToJavaExpression) {
System.out.printf("atVariableDeclaration(%s, %s, %s) 4 created %s%n", type, TreeUtils.toStringTruncated(declarationTree, 65), variableElt, stringToJavaExprField);
}
convertAnnotatedTypeMirror(stringToJavaExprField, type);
break;
default:
throw new BugInCF("unexpected element kind " + variableElt.getKind() + " for " + variableElt);
}
}
Aggregations