use of org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext in project checker-framework by typetools.
the class DependentTypesHelper method viewpointAdaptExecutable.
private void viewpointAdaptExecutable(ExpressionTree tree, ExpressionTree receiverTree, AnnotatedExecutableType typeFromUse, List<? extends ExpressionTree> args) {
Element element = TreeUtils.elementFromUse(tree);
AnnotatedExecutableType viewpointAdaptedType = (AnnotatedExecutableType) factory.getAnnotatedType(element);
if (!hasDependentType(viewpointAdaptedType)) {
return;
}
FlowExpressions.Receiver receiver;
if (receiverTree == null) {
receiver = FlowExpressions.internalReprOfImplicitReceiver(TreeUtils.elementFromUse(tree));
} else {
receiver = FlowExpressions.internalReprOf(factory, receiverTree);
}
List<FlowExpressions.Receiver> argReceivers = new ArrayList<>(args.size());
for (ExpressionTree argTree : args) {
argReceivers.add(FlowExpressions.internalReprOf(factory, argTree));
}
TreePath currentPath = factory.getPath(tree);
FlowExpressionContext context = new FlowExpressionContext(receiver, argReceivers, factory.getContext());
// typeForUse cannot be viewpoint adapted directly because it is the type post type variable
// substitution. Dependent type annotations on type arguments do not (and cannot) be
// viewpoint adapted along with the dependent type annotations that are on the method
// declaration. For example:
// Map<String, String> map = ...;
// List<@KeyFor("map") String> list = ...;
// list.get(0)
// If the type of List.get is viewpoint adapted for the invocation "list.get(0)", then
// typeFromUse would be @KeyFor("map") String get(int).
// Instead, use the type for the method (viewpointAdaptedType) and viewpoint adapt that
// type.
// Then copy annotations from the viewpoint adapted type to typeFromUse, if that annotation
// is not on a type that was substituted for a type variable.
standardizeDoNotUseLocals(context, currentPath, viewpointAdaptedType);
new ViewpointAdaptedCopier().visit(viewpointAdaptedType, typeFromUse);
}
use of org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext in project checker-framework by typetools.
the class DependentTypesHelper method standardizeVariable.
public void standardizeVariable(Tree node, AnnotatedTypeMirror type, Element ele) {
if (!hasDependentType(type)) {
return;
}
TreePath path = factory.getPath(node);
if (path == null) {
return;
}
switch(ele.getKind()) {
case PARAMETER:
Tree enclTree = TreeUtils.enclosingOfKind(path, new HashSet<>(Arrays.asList(Kind.METHOD, Kind.LAMBDA_EXPRESSION)));
if (enclTree.getKind() == Kind.METHOD) {
// If the most enclosing tree is a method, the parameter is a method parameter
MethodTree methodTree = (MethodTree) enclTree;
TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, enclosingType, factory.getContext());
standardizeDoNotUseLocals(parameterContext, path, type);
} else {
// Otherwise, the parameter is a lambda parameter
LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclTree;
FlowExpressionContext parameterContext = FlowExpressionContext.buildContextForLambda(lambdaTree, path, factory.getContext());
// TODO: test this.
// TODO: use path.getParentPath to prevent a StackOverflowError, see Issue
// #1027.
standardizeUseLocals(parameterContext, path.getParentPath(), type);
}
break;
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
case EXCEPTION_PARAMETER:
TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType();
FlowExpressions.Receiver receiver = FlowExpressions.internalReprOfPseudoReceiver(path, enclosingType);
List<Receiver> params = FlowExpressions.getParametersOfEnclosingMethod(factory, path);
FlowExpressionContext localContext = new FlowExpressionContext(receiver, params, factory.getContext());
standardizeUseLocals(localContext, path, type);
break;
case FIELD:
FlowExpressions.Receiver receiverF;
if (node.getKind() == Tree.Kind.IDENTIFIER) {
FlowExpressions.Receiver r = FlowExpressions.internalReprOf(factory, (IdentifierTree) node);
receiverF = r instanceof FlowExpressions.FieldAccess ? ((FlowExpressions.FieldAccess) r).getReceiver() : r;
} else {
receiverF = FlowExpressions.internalReprOfImplicitReceiver(ele);
}
FlowExpressionContext fieldContext = new FlowExpressionContext(receiverF, null, factory.getContext());
standardizeDoNotUseLocals(fieldContext, path, type);
break;
default:
}
}
use of org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext in project checker-framework by typetools.
the class BaseTypeVisitor method resolveContracts.
/**
* Takes a set of contracts identified by their expression and annotation strings and resolves
* them to the correct {@link Receiver} and {@link AnnotationMirror}.
*/
private Set<Pair<Receiver, AnnotationMirror>> resolveContracts(Set<? extends Contract> contractSet, AnnotatedExecutableType method) {
Set<Pair<Receiver, AnnotationMirror>> result = new HashSet<>();
MethodTree methodTree = visitorState.getMethodTree();
TreePath path = atypeFactory.getPath(methodTree);
FlowExpressionContext flowExprContext = null;
for (Contract p : contractSet) {
String expression = p.expression;
AnnotationMirror annotation = p.annotation;
if (flowExprContext == null) {
flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(methodTree, method.getReceiverType().getUnderlyingType(), checker.getContext());
}
annotation = standardizeAnnotationFromContract(annotation, flowExprContext, path);
try {
// TODO: currently, these expressions are parsed many times.
// this could
// be optimized to store the result the first time.
// (same for other annotations)
FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, path, false);
result.add(Pair.of(expr, annotation));
} catch (FlowExpressionParseException e) {
// report errors here
checker.report(e.getResult(), methodTree);
}
}
return result;
}
use of org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext in project checker-framework by typetools.
the class BaseTypeVisitor method checkPreconditions.
/**
* Checks that all the given {@code preconditions} hold true immediately prior to the method
* invocation or variable access at {@code tree}.
*
* @param tree the Tree immediately prior to which the preconditions must hold true
* @param preconditions the preconditions to be checked
*/
protected void checkPreconditions(MethodInvocationTree tree, Set<Precondition> preconditions) {
// TODO: Remove this check and investigate the root cause.
if (preconditions.isEmpty()) {
return;
}
FlowExpressionContext flowExprContext = FlowExpressionContext.buildContextForMethodUse(tree, checker.getContext());
if (flowExprContext == null) {
checker.report(Result.failure("flowexpr.parse.context.not.determined", tree), tree);
return;
}
for (Precondition p : preconditions) {
String expression = p.expression;
AnnotationMirror anno = p.annotation;
anno = standardizeAnnotationFromContract(anno, flowExprContext, getCurrentPath());
try {
FlowExpressions.Receiver expr = FlowExpressionParseUtil.parse(expression, flowExprContext, getCurrentPath(), false);
CFAbstractStore<?, ?> store = atypeFactory.getStoreBefore(tree);
CFAbstractValue<?> value = store.getValue(expr);
AnnotationMirror inferredAnno = null;
if (value != null) {
QualifierHierarchy hierarchy = atypeFactory.getQualifierHierarchy();
Set<AnnotationMirror> annos = value.getAnnotations();
inferredAnno = hierarchy.findAnnotationInSameHierarchy(annos, anno);
}
if (!checkContract(expr, anno, inferredAnno, store)) {
checker.report(Result.failure("contracts.precondition.not.satisfied", tree.toString(), expr == null ? expression : expr.toString()), tree);
}
} catch (FlowExpressionParseException e) {
// report errors here
checker.report(e.getResult(), tree);
}
}
}
use of org.checkerframework.framework.util.FlowExpressionParseUtil.FlowExpressionContext in project checker-framework by typetools.
the class BaseTypeVisitor method checkContractsAtMethodDeclaration.
private void checkContractsAtMethodDeclaration(MethodTree node, ExecutableElement methodElement, List<String> formalParamNames, boolean abstractMethod) {
FlowExpressionContext flowExprContext = null;
List<Contract> contracts = contractsUtils.getContracts(methodElement);
for (Contract contract : contracts) {
String expression = contract.expression;
AnnotationMirror annotation = contract.annotation;
if (flowExprContext == null) {
flowExprContext = FlowExpressionContext.buildContextForMethodDeclaration(node, getCurrentPath(), checker.getContext());
}
annotation = standardizeAnnotationFromContract(annotation, flowExprContext, getCurrentPath());
FlowExpressions.Receiver expr = null;
try {
expr = FlowExpressionParseUtil.parse(expression, flowExprContext, getCurrentPath(), false);
} catch (FlowExpressionParseException e) {
checker.report(e.getResult(), node);
}
if (expr != null && !abstractMethod) {
switch(contract.kind) {
case POSTCONDTION:
checkPostcondition(node, annotation, expr);
break;
case CONDITIONALPOSTCONDTION:
checkConditionalPostcondition(node, annotation, expr, ((ConditionalPostcondition) contract).annoResult);
break;
case PRECONDITION:
// Preconditions are checked at method invocations, not declarations
break;
}
}
if (formalParamNames != null && formalParamNames.contains(expression)) {
@SuppressWarnings("CompilerMessages") @CompilerMessageKey String key = "contracts." + contract.kind.errorKey + ".expression.parameter.name";
checker.report(Result.warning(key, node.getName().toString(), expression, formalParamNames.indexOf(expression) + 1, expression), node);
}
checkParametersAreEffectivelyFinal(node, methodElement, expression);
}
}
Aggregations