Search in sources :

Example 1 with ClassName

use of org.checkerframework.dataflow.expression.ClassName in project checker-framework by typetools.

the class JavaExpressionParseUtil method parse.

/**
 * Parses a string to a {@link JavaExpression}.
 *
 * <p>For most uses, clients should call one of the static methods in {@link
 * StringToJavaExpression} rather than calling this method directly.
 *
 * @param expression the string expression to parse
 * @param enclosingType type of the class that encloses the JavaExpression
 * @param thisReference the JavaExpression to which to parse "this", or null if "this" should not
 *     appear in the expression
 * @param parameters list of JavaExpressions to which to parse formal parameter references such as
 *     "#2", or null if formal parameter references should not appear in the expression
 * @param localVarPath if non-null, the expression is parsed as if it were written at this
 *     location; affects only parsing of local variables
 * @param pathToCompilationUnit required to use the underlying Javac API
 * @param env the processing environment
 * @return {@code expression} as a {@code JavaExpression}
 * @throws JavaExpressionParseException if the string cannot be parsed
 */
public static JavaExpression parse(String expression, TypeMirror enclosingType, @Nullable ThisReference thisReference, @Nullable List<FormalParameter> parameters, @Nullable TreePath localVarPath, TreePath pathToCompilationUnit, ProcessingEnvironment env) throws JavaExpressionParseException {
    // Use the current source version to parse with because a JavaExpression could refer to a
    // variable named "var", which is a keyword in Java 10 and later.
    LanguageLevel currentSourceVersion = JavaParserUtil.getCurrentSourceVersion(env);
    String expressionWithParameterNames = StringsPlume.replaceAll(expression, FORMAL_PARAMETER, PARAMETER_REPLACEMENT);
    Expression expr;
    try {
        expr = JavaParserUtil.parseExpression(expressionWithParameterNames, currentSourceVersion);
    } catch (ParseProblemException e) {
        String extra = ".";
        if (!e.getProblems().isEmpty()) {
            String message = e.getProblems().get(0).getMessage();
            int newLine = message.indexOf(System.lineSeparator());
            if (newLine != -1) {
                message = message.substring(0, newLine);
            }
            extra = ". Error message: " + message;
        }
        throw constructJavaExpressionParseError(expression, "the expression did not parse" + extra);
    }
    JavaExpression result = ExpressionToJavaExpressionVisitor.convert(expr, enclosingType, thisReference, parameters, localVarPath, pathToCompilationUnit, env);
    if (result instanceof ClassName && !expression.endsWith(".class")) {
        throw constructJavaExpressionParseError(expression, String.format("a class name cannot terminate a Java expression string, where result=%s [%s]", result, result.getClass()));
    }
    return result;
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) LanguageLevel(com.github.javaparser.ParserConfiguration.LanguageLevel) Expression(com.github.javaparser.ast.expr.Expression) JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) ClassName(org.checkerframework.dataflow.expression.ClassName) ParseProblemException(com.github.javaparser.ParseProblemException)

Example 2 with ClassName

use of org.checkerframework.dataflow.expression.ClassName in project checker-framework by typetools.

the class InitializationVisitor method checkContract.

@Override
protected boolean checkContract(JavaExpression expr, AnnotationMirror necessaryAnnotation, AnnotationMirror inferredAnnotation, CFAbstractStore<?, ?> store) {
    // also use the information about initialized fields to check contracts
    final AnnotationMirror invariantAnno = atypeFactory.getFieldInvariantAnnotation();
    if (!atypeFactory.getQualifierHierarchy().isSubtype(invariantAnno, necessaryAnnotation) || !(expr instanceof FieldAccess)) {
        return super.checkContract(expr, necessaryAnnotation, inferredAnnotation, store);
    }
    if (expr.containsUnknown()) {
        return false;
    }
    FieldAccess fa = (FieldAccess) expr;
    if (fa.getReceiver() instanceof ThisReference || fa.getReceiver() instanceof ClassName) {
        @SuppressWarnings("unchecked") Store s = (Store) store;
        if (s.isFieldInitialized(fa.getField())) {
            AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(fa.getField());
            // is this an invariant-field?
            if (AnnotationUtils.containsSame(fieldType.getAnnotations(), invariantAnno)) {
                return true;
            }
        }
    } else {
        @SuppressWarnings("unchecked") Value value = (Value) store.getValue(fa.getReceiver());
        Set<AnnotationMirror> receiverAnnoSet;
        if (value != null) {
            receiverAnnoSet = value.getAnnotations();
        } else if (fa.getReceiver() instanceof LocalVariable) {
            Element elem = ((LocalVariable) fa.getReceiver()).getElement();
            AnnotatedTypeMirror receiverType = atypeFactory.getAnnotatedType(elem);
            receiverAnnoSet = receiverType.getAnnotations();
        } else {
            // Is there anything better we could do?
            return false;
        }
        boolean isReceiverInitialized = false;
        for (AnnotationMirror anno : receiverAnnoSet) {
            if (atypeFactory.isInitialized(anno)) {
                isReceiverInitialized = true;
            }
        }
        AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(fa.getField());
        // has the invariant type.
        if (isReceiverInitialized && AnnotationUtils.containsSame(fieldType.getAnnotations(), invariantAnno)) {
            return true;
        }
    }
    return super.checkContract(expr, necessaryAnnotation, inferredAnnotation, store);
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ClassName(org.checkerframework.dataflow.expression.ClassName) CFAbstractValue(org.checkerframework.framework.flow.CFAbstractValue) FieldInitialValue(org.checkerframework.framework.flow.CFAbstractAnalysis.FieldInitialValue) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) CFAbstractStore(org.checkerframework.framework.flow.CFAbstractStore) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) AnnotatedTypeMirror(org.checkerframework.framework.type.AnnotatedTypeMirror)

Example 3 with ClassName

use of org.checkerframework.dataflow.expression.ClassName in project checker-framework by typetools.

the class InitializationStore method insertValue.

/**
 * {@inheritDoc}
 *
 * <p>If the receiver is a field, and has an invariant annotation, then it can be considered
 * initialized.
 */
@Override
public void insertValue(JavaExpression je, V value, boolean permitNondeterministic) {
    if (!shouldInsert(je, value, permitNondeterministic)) {
        return;
    }
    InitializationAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory = (InitializationAnnotatedTypeFactory<?, ?, ?, ?>) analysis.getTypeFactory();
    QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
    AnnotationMirror invariantAnno = atypeFactory.getFieldInvariantAnnotation();
    // Remember fields that have the 'invariant' annotation in the store.
    if (je instanceof FieldAccess) {
        FieldAccess fieldAccess = (FieldAccess) je;
        if (!fieldValues.containsKey(je)) {
            Set<AnnotationMirror> declaredAnnos = atypeFactory.getAnnotatedType(fieldAccess.getField()).getAnnotations();
            if (AnnotationUtils.containsSame(declaredAnnos, invariantAnno)) {
                if (!invariantFields.containsKey(fieldAccess)) {
                    invariantFields.put(fieldAccess, analysis.createSingleAnnotationValue(invariantAnno, je.getType()));
                }
            }
        }
    }
    super.insertValue(je, value, permitNondeterministic);
    for (AnnotationMirror a : value.getAnnotations()) {
        if (qualifierHierarchy.isSubtype(a, invariantAnno)) {
            if (je instanceof FieldAccess) {
                FieldAccess fa = (FieldAccess) je;
                if (fa.getReceiver() instanceof ThisReference || fa.getReceiver() instanceof ClassName) {
                    addInitializedField(fa.getField());
                }
            }
        }
    }
}
Also used : AnnotationMirror(javax.lang.model.element.AnnotationMirror) QualifierHierarchy(org.checkerframework.framework.type.QualifierHierarchy) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference)

Example 4 with ClassName

use of org.checkerframework.dataflow.expression.ClassName in project checker-framework by typetools.

the class LockStore method insertLockPossiblyHeld.

/*
   * Insert an annotation exactly, without regard to whether an annotation was already present.
   * This is only done for @LockPossiblyHeld. This is not sound for other type qualifiers.
   */
public void insertLockPossiblyHeld(JavaExpression je) {
    if (je.containsUnknown()) {
        // Expressions containing unknown expressions are not stored.
        return;
    }
    if (je instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) je;
        CFValue current = localVariableValues.get(localVar);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            localVariableValues.put(localVar, value);
        }
    } else if (je instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) je;
        CFValue current = fieldValues.get(fieldAcc);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            fieldValues.put(fieldAcc, value);
        }
    } else if (je instanceof MethodCall) {
        MethodCall method = (MethodCall) je;
        CFValue current = methodValues.get(method);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            methodValues.put(method, value);
        }
    } else if (je instanceof ArrayAccess) {
        ArrayAccess arrayAccess = (ArrayAccess) je;
        CFValue current = arrayValues.get(arrayAccess);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            arrayValues.put(arrayAccess, value);
        }
    } else if (je instanceof ThisReference) {
        thisValue = changeLockAnnoToTop(je, thisValue);
    } else if (je instanceof ClassName) {
        ClassName className = (ClassName) je;
        CFValue current = classValues.get(className);
        CFValue value = changeLockAnnoToTop(je, current);
        if (value != null) {
            classValues.put(className, value);
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : CFValue(org.checkerframework.framework.flow.CFValue) ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Example 5 with ClassName

use of org.checkerframework.dataflow.expression.ClassName in project checker-framework by typetools.

the class CFAbstractStore method computeNewValueAndInsert.

/**
 * Inserts the result of applying {@code merger} to {@code value} and the previous value for
 * {@code expr}.
 *
 * @param expr the JavaExpression
 * @param value the value of the JavaExpression
 * @param merger the function used to merge {@code value} and the previous value of {@code expr}
 * @param permitNondeterministic if false, does nothing if {@code expr} is nondeterministic; if
 *     true, permits nondeterministic expressions to be placed in the store
 */
protected void computeNewValueAndInsert(JavaExpression expr, @Nullable V value, BinaryOperator<V> merger, boolean permitNondeterministic) {
    if (!shouldInsert(expr, value, permitNondeterministic)) {
        return;
    }
    if (expr instanceof LocalVariable) {
        LocalVariable localVar = (LocalVariable) expr;
        V oldValue = localVariableValues.get(localVar);
        V newValue = merger.apply(oldValue, value);
        if (newValue != null) {
            localVariableValues.put(localVar, newValue);
        }
    } else if (expr instanceof FieldAccess) {
        FieldAccess fieldAcc = (FieldAccess) expr;
        // Only store information about final fields (where the receiver is
        // also fixed) if concurrent semantics are enabled.
        boolean isMonotonic = isMonotonicUpdate(fieldAcc, value);
        if (sequentialSemantics || isMonotonic || fieldAcc.isUnassignableByOtherCode()) {
            V oldValue = fieldValues.get(fieldAcc);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                fieldValues.put(fieldAcc, newValue);
            }
        }
    } else if (expr instanceof MethodCall) {
        MethodCall method = (MethodCall) expr;
        // Don't store any information if concurrent semantics are enabled.
        if (sequentialSemantics) {
            V oldValue = methodValues.get(method);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                methodValues.put(method, newValue);
            }
        }
    } else if (expr instanceof ArrayAccess) {
        ArrayAccess arrayAccess = (ArrayAccess) expr;
        if (sequentialSemantics) {
            V oldValue = arrayValues.get(arrayAccess);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                arrayValues.put(arrayAccess, newValue);
            }
        }
    } else if (expr instanceof ThisReference) {
        ThisReference thisRef = (ThisReference) expr;
        if (sequentialSemantics || thisRef.isUnassignableByOtherCode()) {
            V oldValue = thisValue;
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                thisValue = newValue;
            }
        }
    } else if (expr instanceof ClassName) {
        ClassName className = (ClassName) expr;
        if (sequentialSemantics || className.isUnassignableByOtherCode()) {
            V oldValue = classValues.get(className);
            V newValue = merger.apply(oldValue, value);
            if (newValue != null) {
                classValues.put(className, newValue);
            }
        }
    } else {
    // No other types of expressions need to be stored.
    }
}
Also used : ArrayAccess(org.checkerframework.dataflow.expression.ArrayAccess) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) ClassName(org.checkerframework.dataflow.expression.ClassName) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess) ThisReference(org.checkerframework.dataflow.expression.ThisReference) MethodCall(org.checkerframework.dataflow.expression.MethodCall)

Aggregations

ClassName (org.checkerframework.dataflow.expression.ClassName)11 FieldAccess (org.checkerframework.dataflow.expression.FieldAccess)9 LocalVariable (org.checkerframework.dataflow.expression.LocalVariable)8 MethodCall (org.checkerframework.dataflow.expression.MethodCall)6 ThisReference (org.checkerframework.dataflow.expression.ThisReference)6 ArrayAccess (org.checkerframework.dataflow.expression.ArrayAccess)5 HashMap (java.util.HashMap)2 Map (java.util.Map)2 AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 JavaExpression (org.checkerframework.dataflow.expression.JavaExpression)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 ParseProblemException (com.github.javaparser.ParseProblemException)1 LanguageLevel (com.github.javaparser.ParserConfiguration.LanguageLevel)1 Expression (com.github.javaparser.ast.expr.Expression)1 ClassTree (com.sun.source.tree.ClassTree)1 MethodTree (com.sun.source.tree.MethodTree)1 Element (javax.lang.model.element.Element)1 ElementKind (javax.lang.model.element.ElementKind)1 TypeElement (javax.lang.model.element.TypeElement)1