use of com.sun.source.tree.LambdaExpressionTree 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 com.sun.source.tree.LambdaExpressionTree in project st-js by st-js.
the class LambdaAccessFinalInLoopCheck method checkUsageInLambdas.
private void checkUsageInLambdas(VariableTree tree, GenerationContext<Void> context) {
// this is the block containing the var definition
TreePath blockPath = context.getCurrentPath().getParentPath();
blockPath.getLeaf().accept(new TreeScanner<Void, Void>() {
@Override
public Void visitLambdaExpression(LambdaExpressionTree lambda, Void arg1) {
checkVarInLambda(tree.getName(), lambda, context);
return super.visitLambdaExpression(lambda, arg1);
}
}, null);
}
use of com.sun.source.tree.LambdaExpressionTree in project checker-framework by typetools.
the class GuiEffectVisitor method scanUp.
/**
* This method is called to traverse the path back up from any anonymous inner class or lambda
* which has been inferred to be UI affecting and re-run {@code commonAssignmentCheck} as needed
* on places where the class declaration or lambda expression are being assigned to a variable,
* passed as a parameter or returned from a method. This is necessary because the normal visitor
* traversal only checks assignments on the way down the AST, before inference has had a chance to
* run.
*
* @param path the path to traverse up from a UI-affecting class
*/
private void scanUp(TreePath path) {
Tree tree = path.getLeaf();
switch(tree.getKind()) {
case ASSIGNMENT:
AssignmentTree assignmentTree = (AssignmentTree) tree;
commonAssignmentCheck(atypeFactory.getAnnotatedType(assignmentTree.getVariable()), atypeFactory.getAnnotatedType(assignmentTree.getExpression()), assignmentTree.getExpression(), "assignment");
break;
case VARIABLE:
VariableTree variableTree = (VariableTree) tree;
commonAssignmentCheck(atypeFactory.getAnnotatedType(variableTree), atypeFactory.getAnnotatedType(variableTree.getInitializer()), variableTree.getInitializer(), "assignment");
break;
case METHOD_INVOCATION:
MethodInvocationTree invocationTree = (MethodInvocationTree) tree;
List<? extends ExpressionTree> args = invocationTree.getArguments();
ParameterizedExecutableType mType = atypeFactory.methodFromUse(invocationTree);
AnnotatedExecutableType invokedMethod = mType.executableType;
ExecutableElement method = invokedMethod.getElement();
CharSequence methodName = ElementUtils.getSimpleNameOrDescription(method);
List<? extends VariableElement> methodParams = method.getParameters();
List<AnnotatedTypeMirror> paramTypes = AnnotatedTypes.expandVarArgsParameters(atypeFactory, invokedMethod, invocationTree.getArguments());
for (int i = 0; i < args.size(); ++i) {
if (args.get(i).getKind() == Tree.Kind.NEW_CLASS || args.get(i).getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
commonAssignmentCheck(paramTypes.get(i), atypeFactory.getAnnotatedType(args.get(i)), args.get(i), "argument", methodParams.get(i), methodName);
}
}
break;
case RETURN:
ReturnTree returnTree = (ReturnTree) tree;
if (returnTree.getExpression().getKind() == Tree.Kind.NEW_CLASS || returnTree.getExpression().getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
Tree enclosing = TreePathUtil.enclosingMethodOrLambda(path);
AnnotatedTypeMirror ret = null;
if (enclosing.getKind() == Tree.Kind.METHOD) {
MethodTree enclosingMethod = (MethodTree) enclosing;
boolean valid = validateTypeOf(enclosing);
if (valid) {
ret = atypeFactory.getMethodReturnType(enclosingMethod, returnTree);
}
} else {
ret = atypeFactory.getFunctionTypeFromTree((LambdaExpressionTree) enclosing).getReturnType();
}
if (ret != null) {
commonAssignmentCheck(ret, atypeFactory.getAnnotatedType(returnTree.getExpression()), returnTree.getExpression(), "return");
}
}
break;
case METHOD:
// without either being assigned to a field or returned.
return;
case CLASS:
// boundaries
assert false;
return;
default:
scanUp(path.getParentPath());
}
}
use of com.sun.source.tree.LambdaExpressionTree in project checker-framework by typetools.
the class GuiEffectVisitor method visitMethodInvocation.
// Check that the invoked effect is <= permitted effect (effStack.peek())
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
if (debugSpew) {
System.err.println("For invocation " + node + " in " + currentMethods.peek().getName());
}
// Target method annotations
ExecutableElement methodElt = TreeUtils.elementFromUse(node);
if (debugSpew) {
System.err.println("methodElt found");
}
Tree callerTree = TreePathUtil.enclosingMethodOrLambda(getCurrentPath());
if (callerTree == null) {
// Static initializer; let's assume this is safe to have the UI effect
if (debugSpew) {
System.err.println("No enclosing method: likely static initializer");
}
return super.visitMethodInvocation(node, p);
}
if (debugSpew) {
System.err.println("callerTree found: " + callerTree.getKind());
}
Effect targetEffect = atypeFactory.getComputedEffectAtCallsite(node, receiverType, methodElt);
Effect callerEffect = null;
if (callerTree.getKind() == Tree.Kind.METHOD) {
ExecutableElement callerElt = TreeUtils.elementFromDeclaration((MethodTree) callerTree);
if (debugSpew) {
System.err.println("callerElt found");
}
callerEffect = atypeFactory.getDeclaredEffect(callerElt);
final DeclaredType callerReceiverType = classType.getUnderlyingType();
assert callerReceiverType != null;
final TypeElement callerReceiverElt = (TypeElement) callerReceiverType.asElement();
// long.
if (TypesUtils.isAnonymous(callerReceiverType) && // Skip if already inferred @UI
!effStack.peek().isUI() && // Ignore if explicitly annotated
!atypeFactory.fromElement(callerReceiverElt).hasAnnotation(AlwaysSafe.class) && !atypeFactory.fromElement(callerReceiverElt).hasAnnotation(UI.class)) {
boolean overridesPolymorphic = false;
Map<AnnotatedTypeMirror.AnnotatedDeclaredType, ExecutableElement> overriddenMethods = AnnotatedTypes.overriddenMethods(elements, atypeFactory, callerElt);
for (Map.Entry<AnnotatedTypeMirror.AnnotatedDeclaredType, ExecutableElement> pair : overriddenMethods.entrySet()) {
AnnotatedTypeMirror.AnnotatedDeclaredType overriddenType = pair.getKey();
AnnotatedExecutableType overriddenMethod = AnnotatedTypes.asMemberOf(types, atypeFactory, overriddenType, pair.getValue());
if (atypeFactory.getDeclAnnotation(overriddenMethod.getElement(), PolyUIEffect.class) != null && atypeFactory.getDeclAnnotation(overriddenType.getUnderlyingType().asElement(), PolyUIType.class) != null) {
overridesPolymorphic = true;
break;
}
}
// @UI anon class
if (overridesPolymorphic && targetEffect.isUI()) {
// Mark the anonymous class as @UI
atypeFactory.constrainAnonymousClassToUI(callerReceiverElt);
// Then re-calculate this method's effect (it might still not be an
// @PolyUIEffect method).
callerEffect = atypeFactory.getDeclaredEffect(callerElt);
effStack.pop();
effStack.push(callerEffect);
}
}
// --- the traversal goes straight from the class to the initializer.
assert (currentMethods.peek() == null || callerEffect.equals(effStack.peek()));
} else if (callerTree.getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
callerEffect = atypeFactory.getInferedEffectForLambdaExpression((LambdaExpressionTree) callerTree);
// lambda
if (targetEffect.isUI() && callerEffect.isPoly()) {
atypeFactory.constrainLambdaToUI((LambdaExpressionTree) callerTree);
callerEffect = new Effect(UIEffect.class);
}
}
assert callerEffect != null;
if (!Effect.lessThanOrEqualTo(targetEffect, callerEffect)) {
checker.reportError(node, "call.ui", targetEffect, callerEffect);
if (debugSpew) {
System.err.println("Issuing error for node: " + node);
}
}
if (debugSpew) {
System.err.println("Successfully finished main non-recursive checkinv of invocation " + node);
}
return super.visitMethodInvocation(node, p);
}
use of com.sun.source.tree.LambdaExpressionTree in project checker-framework by typetools.
the class TypeArgInferenceUtil method assignedTo.
/**
* Returns the annotated type that the leaf of path is assigned to, if it is within an assignment
* context. Returns the annotated type that the method invocation at the leaf is assigned to. If
* the result is a primitive, return the boxed version.
*
* @param atypeFactory the type factory, for looking up types
* @param path the path whole leaf to look up a type for
* @return the type of path's leaf
*/
// AST node comparisons
@SuppressWarnings("interning:not.interned")
public static AnnotatedTypeMirror assignedTo(AnnotatedTypeFactory atypeFactory, TreePath path) {
Tree assignmentContext = TreePathUtil.getAssignmentContext(path);
AnnotatedTypeMirror res;
if (assignmentContext == null) {
res = null;
} else if (assignmentContext instanceof AssignmentTree) {
ExpressionTree variable = ((AssignmentTree) assignmentContext).getVariable();
res = atypeFactory.getAnnotatedType(variable);
} else if (assignmentContext instanceof CompoundAssignmentTree) {
ExpressionTree variable = ((CompoundAssignmentTree) assignmentContext).getVariable();
res = atypeFactory.getAnnotatedType(variable);
} else if (assignmentContext instanceof MethodInvocationTree) {
MethodInvocationTree methodInvocation = (MethodInvocationTree) assignmentContext;
// TODO move to getAssignmentContext
if (methodInvocation.getMethodSelect() instanceof MemberSelectTree && ((MemberSelectTree) methodInvocation.getMethodSelect()).getExpression() == path.getLeaf()) {
return null;
}
ExecutableElement methodElt = TreeUtils.elementFromUse(methodInvocation);
AnnotatedTypeMirror receiver = atypeFactory.getReceiverType(methodInvocation);
if (TreeUtils.isSuperConstructorCall(methodInvocation)) {
receiver = atypeFactory.getSelfType(methodInvocation);
}
res = assignedToExecutable(atypeFactory, path, methodElt, receiver, methodInvocation.getArguments());
} else if (assignmentContext instanceof NewArrayTree) {
// TODO: I left the previous implementation below, it definitely caused infinite loops
// TODO: if you called it from places like the TreeAnnotator.
res = null;
// TODO: This may cause infinite loop
// AnnotatedTypeMirror type =
// atypeFactory.getAnnotatedType((NewArrayTree)assignmentContext);
// type = AnnotatedTypes.innerMostType(type);
// return type;
} else if (assignmentContext instanceof NewClassTree) {
// This need to be basically like MethodTree
NewClassTree newClassTree = (NewClassTree) assignmentContext;
if (newClassTree.getEnclosingExpression() instanceof NewClassTree && (newClassTree.getEnclosingExpression() == path.getLeaf())) {
return null;
}
ExecutableElement constructorElt = TreeUtils.constructor(newClassTree);
AnnotatedTypeMirror receiver = atypeFactory.fromNewClass(newClassTree);
res = assignedToExecutable(atypeFactory, path, constructorElt, receiver, newClassTree.getArguments());
} else if (assignmentContext instanceof ReturnTree) {
HashSet<Tree.Kind> kinds = new HashSet<>(Arrays.asList(Tree.Kind.LAMBDA_EXPRESSION, Tree.Kind.METHOD));
Tree enclosing = TreePathUtil.enclosingOfKind(path, kinds);
if (enclosing.getKind() == Tree.Kind.METHOD) {
res = atypeFactory.getAnnotatedType((MethodTree) enclosing).getReturnType();
} else {
AnnotatedExecutableType fninf = atypeFactory.getFunctionTypeFromTree((LambdaExpressionTree) enclosing);
res = fninf.getReturnType();
}
} else if (assignmentContext instanceof VariableTree) {
res = assignedToVariable(atypeFactory, assignmentContext);
} else {
throw new BugInCF("AnnotatedTypes.assignedTo: shouldn't be here");
}
if (res != null && TypesUtils.isPrimitive(res.getUnderlyingType())) {
return atypeFactory.getBoxedType((AnnotatedPrimitiveType) res);
} else {
return res;
}
}
Aggregations