Search in sources :

Example 11 with JavaExpressionParseException

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);
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) HashMap(java.util.HashMap) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) List(java.util.List) ArrayList(java.util.ArrayList) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 12 with JavaExpressionParseException

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));
}
Also used : TypeCastNode(org.checkerframework.dataflow.cfg.node.TypeCastNode) ObjectCreationNode(org.checkerframework.dataflow.cfg.node.ObjectCreationNode) LocalVariableNode(org.checkerframework.dataflow.cfg.node.LocalVariableNode) ThisNode(org.checkerframework.dataflow.cfg.node.ThisNode) AssignmentNode(org.checkerframework.dataflow.cfg.node.AssignmentNode) NullLiteralNode(org.checkerframework.dataflow.cfg.node.NullLiteralNode) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode) ReturnNode(org.checkerframework.dataflow.cfg.node.ReturnNode) MethodInvocationNode(org.checkerframework.dataflow.cfg.node.MethodInvocationNode) Node(org.checkerframework.dataflow.cfg.node.Node) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) FieldAccessNode(org.checkerframework.dataflow.cfg.node.FieldAccessNode)

Example 13 with JavaExpressionParseException

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;
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) MethodTree(com.sun.source.tree.MethodTree) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) TypeSystemError(org.checkerframework.javacutil.TypeSystemError) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) NotOwning(org.checkerframework.checker.mustcall.qual.NotOwning) Owning(org.checkerframework.checker.mustcall.qual.Owning) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess)

Example 14 with JavaExpressionParseException

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);
    }
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) Element(javax.lang.model.element.Element) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ValueLiteral(org.checkerframework.dataflow.expression.ValueLiteral) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference)

Example 15 with JavaExpressionParseException

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;
}
Also used : CFValue(org.checkerframework.framework.flow.CFValue) CFStore(org.checkerframework.framework.flow.CFStore) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)

Aggregations

JavaExpressionParseException (org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException)16 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)13 StringToJavaExpression (org.checkerframework.framework.util.StringToJavaExpression)10 AnnotationMirror (javax.lang.model.element.AnnotationMirror)9 ExecutableElement (javax.lang.model.element.ExecutableElement)9 ArrayList (java.util.ArrayList)8 Element (javax.lang.model.element.Element)8 Nullable (org.checkerframework.checker.nullness.qual.Nullable)8 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)8 MethodTree (com.sun.source.tree.MethodTree)7 HashMap (java.util.HashMap)7 List (java.util.List)7 TypeElement (javax.lang.model.element.TypeElement)7 VariableElement (javax.lang.model.element.VariableElement)7 ClassTree (com.sun.source.tree.ClassTree)6 ExpressionTree (com.sun.source.tree.ExpressionTree)6 Tree (com.sun.source.tree.Tree)6 TreePath (com.sun.source.util.TreePath)6 Collections (java.util.Collections)6 Map (java.util.Map)6