use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException 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.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class MustCallConsistencyAnalyzer method checkEnclosingMethodIsCreatesMustCallFor.
/**
* Checks that the method that encloses an assignment is marked with @CreatesMustCallFor
* annotation whose target is the object whose field is being re-assigned.
*
* @param node an assignment node whose lhs is a non-final, owning field
* @param enclosingMethod the MethodTree in which the re-assignment takes place
*/
private void checkEnclosingMethodIsCreatesMustCallFor(AssignmentNode node, MethodTree enclosingMethod) {
Node lhs = node.getTarget();
if (!(lhs instanceof FieldAccessNode)) {
return;
}
String receiverString = receiverAsString((FieldAccessNode) lhs);
if ("this".equals(receiverString) && TreeUtils.isConstructor(enclosingMethod)) {
// be annotated.
return;
}
ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethod);
MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
List<String> cmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
if (cmcfValues.isEmpty()) {
checker.reportError(enclosingMethod, "missing.creates.mustcall.for", enclosingMethodElt.getSimpleName().toString(), receiverString, ((FieldAccessNode) lhs).getFieldName());
return;
}
List<String> checked = new ArrayList<>();
for (String targetStrWithoutAdaptation : cmcfValues) {
String targetStr;
try {
targetStr = StringToJavaExpression.atMethodBody(targetStrWithoutAdaptation, enclosingMethod, checker).toString();
} catch (JavaExpressionParseException e) {
targetStr = targetStrWithoutAdaptation;
}
if (targetStr.equals(receiverString)) {
// This @CreatesMustCallFor annotation matches.
return;
}
checked.add(targetStr);
}
checker.reportError(enclosingMethod, "incompatible.creates.mustcall.for", enclosingMethodElt.getSimpleName().toString(), receiverString, ((FieldAccessNode) lhs).getFieldName(), String.join(", ", checked));
}
use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class MustCallConsistencyAnalyzer method isValidCreatesMustCallForExpression.
/**
* Checks the validity of the given expression from an invoked method's {@link
* org.checkerframework.checker.mustcall.qual.CreatesMustCallFor} annotation. Helper method for
* {@link #checkCreatesMustCallForInvocation(Set, MethodInvocationNode)}.
*
* <p>An expression is valid if one of the following conditions is true: 1) the expression is an
* owning pointer, 2) the expression already has a tracked Obligation (i.e. there is already a
* resource alias in some Obligation's resource alias set that refers to the expression), or 3)
* the method in which the invocation occurs also has an @CreatesMustCallFor annotation, with the
* same expression.
*
* @param obligations the currently-tracked Obligations; this value is side-effected if there is
* an Obligation in it which tracks {@code expression} as one of its resource aliases
* @param expression an element of a method's @CreatesMustCallFor annotation
* @param path the path to the invocation of the method from whose @CreateMustCallFor annotation
* {@code expression} came
* @return true iff the expression is valid, as defined above
*/
private boolean isValidCreatesMustCallForExpression(Set<Obligation> obligations, JavaExpression expression, TreePath path) {
if (expression instanceof FieldAccess) {
Element elt = ((FieldAccess) expression).getField();
if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
// The expression is an Owning field. This satisfies case 1.
return true;
}
} else if (expression instanceof LocalVariable) {
Element elt = ((LocalVariable) expression).getElement();
if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
// This satisfies case 1.
return true;
} else {
Obligation toRemove = null;
Obligation toAdd = null;
for (Obligation obligation : obligations) {
ResourceAlias alias = obligation.getResourceAlias(expression);
if (alias != null) {
// This satisfies case 2 above. Remove all its aliases, then return below.
if (toRemove != null) {
throw new TypeSystemError("tried to remove multiple sets containing a reset expression at once");
}
toRemove = obligation;
toAdd = new Obligation(ImmutableSet.of(alias));
}
}
if (toRemove != null) {
obligations.remove(toRemove);
obligations.add(toAdd);
// This satisfies case 2.
return true;
}
}
}
// TODO: Getting this every time is inefficient if a method has many @CreatesMustCallFor
// annotations, but that should be rare.
MethodTree enclosingMethodTree = TreePathUtil.enclosingMethod(path);
if (enclosingMethodTree == null) {
return false;
}
ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethodTree);
MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
List<String> enclosingCmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
if (enclosingCmcfValues.isEmpty()) {
return false;
}
for (String enclosingCmcfValue : enclosingCmcfValues) {
JavaExpression enclosingTarget;
try {
enclosingTarget = StringToJavaExpression.atMethodBody(enclosingCmcfValue, enclosingMethodTree, checker);
} catch (JavaExpressionParseException e) {
// Do not issue an error here, because it would be a duplicate.
// The error will be issued by the Transfer class of the checker,
// via the CreatesMustCallForElementSupplier interface.
enclosingTarget = null;
}
if (areSame(expression, enclosingTarget)) {
// This satisfies case 3.
return true;
}
}
return false;
}
use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class UpperBoundVisitor method checkEffectivelyFinalAndParsable.
/**
* Reports an error if the Java expression named by s is not effectively final when parsed at the
* declaration of the given class.
*
* @param s a Java expression
* @param classTree the expression is parsed with respect to this class
* @param whereToReportError the tree at which to possibly report an error
*/
private void checkEffectivelyFinalAndParsable(String s, ClassTree classTree, Tree whereToReportError) {
JavaExpression je;
try {
je = StringToJavaExpression.atTypeDecl(s, TreeUtils.elementFromDeclaration(classTree), checker);
} catch (JavaExpressionParseException e) {
checker.report(whereToReportError, e.getDiagMessage());
return;
}
Element element = null;
if (je instanceof LocalVariable) {
element = ((LocalVariable) je).getElement();
} else if (je instanceof FieldAccess) {
element = ((FieldAccess) je).getField();
} else if (je instanceof ThisReference || je instanceof ValueLiteral) {
return;
}
if (element == null || !ElementUtils.isEffectivelyFinal(element)) {
checker.reportError(whereToReportError, NOT_FINAL, je);
}
}
use of org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException in project checker-framework by typetools.
the class UpperBoundAnnotatedTypeFactory method fromLessThanOrEqual.
private UBQualifier fromLessThanOrEqual(Tree tree, TreePath treePath, List<String> lessThanExpressions) {
UBQualifier ubQualifier = null;
for (String expression : lessThanExpressions) {
Pair<JavaExpression, String> exprAndOffset;
try {
exprAndOffset = getExpressionAndOffsetFromJavaExpressionString(expression, treePath);
} catch (JavaExpressionParseException e) {
exprAndOffset = null;
}
if (exprAndOffset == null) {
continue;
}
JavaExpression je = exprAndOffset.first;
String offset = exprAndOffset.second;
if (!CFAbstractStore.canInsertJavaExpression(je)) {
continue;
}
CFStore store = getStoreBefore(tree);
CFValue value = store.getValue(je);
if (value != null && value.getAnnotations().size() == 1) {
UBQualifier newUBQ = UBQualifier.createUBQualifier(qualHierarchy.findAnnotationInHierarchy(value.getAnnotations(), UNKNOWN), AnnotatedTypeFactory.negateConstant(offset), (IndexChecker) checker);
if (ubQualifier == null) {
ubQualifier = newUBQ;
} else {
ubQualifier = ubQualifier.glb(newUBQ);
}
}
}
return ubQualifier;
}
Aggregations