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;
}
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);
}
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());
}
}
}
}
}
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.
}
}
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.
}
}
Aggregations