Class DisallowedSideEffects
- All Implemented Interfaces:
TreeVisitor<Void,Void>
SideEffectsOnly annotation, and reports an error for each one.
Clients use the static method checkSideEffectsOnly(com.sun.source.util.TreePath, java.util.List<org.checkerframework.dataflow.expression.JavaExpression>, org.checkerframework.common.basetype.BaseTypeChecker, com.sun.source.tree.MethodTree, boolean, boolean).
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final booleanTrue if "-AassumePureGetters" was passed on the command line.protected final booleanTrue if "-AassumeSideEffectFree" or "-AassumePure" was passed on the command line.protected final BaseTypeCheckerThe checker to use.protected final List<org.plumelib.util.IPair<Tree, JavaExpression>> Expressions the method side-effects that are not in itsSideEffectsOnlyannotation.protected final Set<VariableElement> The local variables that always hold an object that the method being checked created.protected final List<JavaExpression> List of expressions specified as annotation arguments in theSideEffectsOnlyannotation of the method being checked. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedDisallowedSideEffects(List<JavaExpression> sideEffectsOnlyExpressions, Set<VariableElement> freshLocals, BaseTypeChecker checker, boolean assumeSideEffectFree, boolean assumePureGetters) Creates a new DisallowedSideEffects. -
Method Summary
Modifier and TypeMethodDescriptionprotected List<JavaExpression> calleeSideEffectedExpressions(MethodInvocationTree node, ExecutableElement invokedElem, Map<ExecutableElement, List<String>> seOnlyExpressionStrings) Returns the expressions that the invoked method may side-effect: the arguments/elements of itsSideEffectsOnlyannotation, viewpoint-adapted to the given call site.protected static @Nullable ExpressionTreecallSiteTree(JavaExpression atDeclaration, ExecutableElement invokedElem, @Nullable ExpressionTree receiverTree, List<? extends ExpressionTree> argTrees) Returns the tree at the given call site that the given expression denotes in its entirety: the receiver if the expression isthis, or the corresponding argument if the expression is a formal parameter.protected voidcheckImplicitCall(Tree node, ExecutableElement invokedElem, @Nullable JavaExpression receiver) Checks a call that the compiler introduces when it desugars the source code, and records any side effect of it that is beyond what theSideEffectsOnlyannotation of the method being checked permits.protected voidcheckImplicitSuperCall(Tree node, ExecutableElement constructorElt) Checks the call to the superclass's no-argument constructor that the compiler inserts in a constructor that contains no explicitthis(...)orsuper(...)call, and records any side effect of it that is beyond what theSideEffectsOnlyannotation of the constructor being checked permits.protected voidRecords the disallowed side effects of the given method invocation, and reports an error if the callee has no side-effect annotation.static voidcheckSideEffectsOnly(TreePath statement, List<JavaExpression> sideEffectsOnlyExpressions, BaseTypeChecker checker, MethodTree methodTree, boolean assumeSideEffectFree, boolean assumePureGetters) Issues warnings about side effects instatementbeyond the@SideEffectsOnlyannotation.static voidcheckSideEffectsOnly(TreePath statement, List<JavaExpression> sideEffectsOnlyExpressions, BaseTypeChecker checker, CharSequence methodName, boolean assumeSideEffectFree, boolean assumePureGetters) Issues warnings about side effects beyond the given expressions, which come from a@SideEffectsOnlyannotation.protected List<JavaExpression> constructorSideEffectedExpressions(NewClassTree node, ExecutableElement constructorElt, AnnotationMirror seOnlyAnnotation) Returns the expressions that the invoked constructor side-effects: the arguments/elements of itsSideEffectsOnlyannotation, viewpoint-adapted to the given call site.protected static JavaExpressionReturns the JavaExpression for the given tree, with every use ofsuperreplaced bythis.protected static Set<VariableElement> freshLocals(List<? extends Tree> trees) Returns the local variables that always hold an object that the given code created: those that are assigned onlynewexpressions.protected booleanReturns true if the given expression is listed in theSideEffectsOnlyannotation or is reached through one of the listed expressions.protected booleanReturns true if assigning to the given expression is a side effect beyond what is listed in theSideEffectsOnlyannotation.protected booleanReturns true if the given expression is a side-effected expression beyond what is listed in theSideEffectsOnlyannotation.protected booleanReturns true if the given expression always evaluates to an object that the method being checked created: an array creation expression, or a local variable that always holds such an object.protected static booleanReturns true if the given tree is anewexpression for an object, so its value is an object that the code being checked just created.protected booleanReturns true if the given expression is a field or an array element of an object that the method being checked created.protected booleanReturns true if the given method promises to modify nothing that existed before it was called.protected @Nullable ExecutableElementnoArgumentMethod(TypeMirror receiverType, String methodName) Returns the no-argument method with the given name that a call on an expression of the given type invokes, or null if there is no such method.protected voidreport(CharSequence methodName) Reports an error for each side effect that this scanner found and that theSideEffectsOnlyannotation does not permit.visitAnnotation(AnnotationTree node, Void aVoid) visitAssignment(AssignmentTree node, Void aVoid) visitClass(ClassTree node, Void aVoid) visitCompoundAssignment(CompoundAssignmentTree node, Void aVoid) visitEnhancedForLoop(EnhancedForLoopTree node, Void aVoid) visitLambdaExpression(LambdaExpressionTree node, Void aVoid) visitMethodInvocation(MethodInvocationTree node, Void aVoid) visitNewClass(NewClassTree node, Void aVoid) visitUnary(UnaryTree node, Void aVoid) protected static JavaExpressionwithReceiver(JavaExpression expr, JavaExpression receiver) Returns the given expression with every use ofthisreplaced by the given receiver.Methods inherited from class com.sun.source.util.TreePathScanner
getCurrentPath, scan, scanMethods inherited from class com.sun.source.util.TreeScanner
reduce, scan, visitAnnotatedType, visitAnyPattern, visitArrayAccess, visitArrayType, visitAssert, visitBinary, visitBindingPattern, visitBlock, visitBreak, visitCase, visitCatch, visitCompilationUnit, visitConditionalExpression, visitConstantCaseLabel, visitContinue, visitDeconstructionPattern, visitDefaultCaseLabel, visitDoWhileLoop, visitEmptyStatement, visitErroneous, visitExports, visitExpressionStatement, visitForLoop, visitIdentifier, visitIf, visitImport, visitInstanceOf, visitIntersectionType, visitLabeledStatement, visitLiteral, visitMemberReference, visitMemberSelect, visitMethod, visitModifiers, visitModule, visitNewArray, visitOpens, visitOther, visitPackage, visitParameterizedType, visitParenthesized, visitPatternCaseLabel, visitPrimitiveType, visitProvides, visitRequires, visitReturn, visitStringTemplate, visitSwitch, visitSwitchExpression, visitSynchronized, visitThrow, visitTypeCast, visitTypeParameter, visitUnionType, visitUses, visitVariable, visitWhileLoop, visitWildcard, visitYield
-
Field Details
-
disallowedSideEffects
Expressions the method side-effects that are not in itsSideEffectsOnlyannotation. -
sideEffectsOnlyExpressionsFromAnnotation
List of expressions specified as annotation arguments in theSideEffectsOnlyannotation of the method being checked. -
freshLocals
The local variables that always hold an object that the method being checked created. Modifying such an object is not a side effect that is visible to the caller. -
checker
The checker to use. -
assumeSideEffectFree
protected final boolean assumeSideEffectFreeTrue if "-AassumeSideEffectFree" or "-AassumePure" was passed on the command line. -
assumePureGetters
protected final boolean assumePureGettersTrue if "-AassumePureGetters" was passed on the command line.
-
-
Constructor Details
-
DisallowedSideEffects
protected DisallowedSideEffects(List<JavaExpression> sideEffectsOnlyExpressions, Set<VariableElement> freshLocals, BaseTypeChecker checker, boolean assumeSideEffectFree, boolean assumePureGetters) Creates a new DisallowedSideEffects.- Parameters:
sideEffectsOnlyExpressions- the arguments/values of theSideEffectsOnlyannotation of the method being checkedfreshLocals- the local variables that always hold an object that the method being checked createdchecker- the checker to useassumeSideEffectFree- true if every method should be assumed to be side-effect-freeassumePureGetters- true if every getter should be assumed to be side-effect-free
-
-
Method Details
-
checkSideEffectsOnly
public static void checkSideEffectsOnly(TreePath statement, List<JavaExpression> sideEffectsOnlyExpressions, BaseTypeChecker checker, MethodTree methodTree, boolean assumeSideEffectFree, boolean assumePureGetters) Issues warnings about side effects instatementbeyond the@SideEffectsOnlyannotation.- Parameters:
statement- the statement to check; currently, at the only call site it is a method bodysideEffectsOnlyExpressions- the values in theSideEffectsOnlyannotationchecker- the checker to usemethodTree- the method that containsstatementassumeSideEffectFree- true if every method should be assumed to be side-effect-freeassumePureGetters- true if every getter should be assumed to be side-effect-free
-
checkImplicitSuperCall
Checks the call to the superclass's no-argument constructor that the compiler inserts in a constructor that contains no explicitthis(...)orsuper(...)call, and records any side effect of it that is beyond what theSideEffectsOnlyannotation of the constructor being checked permits.- Parameters:
node- the tree to report an error atconstructorElt- the constructor being checked
-
checkSideEffectsOnly
public static void checkSideEffectsOnly(TreePath statement, List<JavaExpression> sideEffectsOnlyExpressions, BaseTypeChecker checker, CharSequence methodName, boolean assumeSideEffectFree, boolean assumePureGetters) Issues warnings about side effects beyond the given expressions, which come from a@SideEffectsOnlyannotation.Unlike the other overload, this one does not treat the code as a constructor body: the caller has already put every permitted expression in
sideEffectsOnlyExpressions.- Parameters:
statement- the statement to check; a method body or the body of a lambdasideEffectsOnlyExpressions- the expressions that the code may side-effect, written in terms of the code being checkedchecker- the checker to usemethodName- the name to use in diagnostics for the code being checkedassumeSideEffectFree- true if every method should be assumed to be side-effect-freeassumePureGetters- true if every getter should be assumed to be side-effect-free
-
report
Reports an error for each side effect that this scanner found and that theSideEffectsOnlyannotation does not permit.- Parameters:
methodName- the name to use in diagnostics for the code that was checked
-
expressionFromTree
Returns the JavaExpression for the given tree, with every use ofsuperreplaced bythis.super.fandthis.fare the same location, so they must be compared alike against theSideEffectsOnlyannotation, which cannot mentionsuper.- Parameters:
tree- an expression tree- Returns:
- the JavaExpression for the tree, written in terms of
thisrather thansuper
-
visitMethodInvocation
- Specified by:
visitMethodInvocationin interfaceTreeVisitor<Void,Void> - Overrides:
visitMethodInvocationin classTreeScanner<Void,Void>
-
checkMethodInvocation
Records the disallowed side effects of the given method invocation, and reports an error if the callee has no side-effect annotation. Does not scan the subtrees of the invocation.- Parameters:
node- a method invocation
-
modifiesNothing
Returns true if the given method promises to modify nothing that existed before it was called.- Parameters:
elt- a method or constructor- Returns:
- true if the given method modifies nothing
-
calleeSideEffectedExpressions
protected List<JavaExpression> calleeSideEffectedExpressions(MethodInvocationTree node, ExecutableElement invokedElem, Map<ExecutableElement, List<String>> seOnlyExpressionStrings) Returns the expressions that the invoked method may side-effect: the arguments/elements of itsSideEffectsOnlyannotation, viewpoint-adapted to the given call site.An expression that denotes an object that the call site allocates, in the sense of
isNewObjectTree(com.sun.source.tree.ExpressionTree), is omitted from the result.- Parameters:
node- a call to a method to which aSideEffectsOnlyannotation appliesinvokedElem- the invoked methodseOnlyExpressionStrings- theSideEffectsOnlyexpressions that apply toinvokedElem, indexed by the method whose declaration contains them- Returns:
- the expressions that the invoked method side-effects, viewpoint-adapted to
node
-
callSiteTree
protected static @Nullable ExpressionTree callSiteTree(JavaExpression atDeclaration, ExecutableElement invokedElem, @Nullable ExpressionTree receiverTree, List<? extends ExpressionTree> argTrees) Returns the tree at the given call site that the given expression denotes in its entirety: the receiver if the expression isthis, or the corresponding argument if the expression is a formal parameter. Returns null if the expression is neither, or if there is no such tree.A larger expression that merely contains
thisor a formal parameter, such asthis.f, has no such tree:this.fdenotes a different object thanthisdoes, and that object may have existed before the call.- Parameters:
atDeclaration- an expression written at the declaration of the invoked methodinvokedElem- the invoked method or constructorreceiverTree- the receiver at the call site, or null if there is noneargTrees- the arguments at the call site- Returns:
- the tree that
atDeclarationdenotes at the call site, or null if there is none
-
isNewObjectTree
Returns true if the given tree is anewexpression for an object, so its value is an object that the code being checked just created. Modifying such an object is not a side effect that is visible to the caller.This test is made on the tree rather than on the
JavaExpression, becauseJavaExpression.fromTree(com.sun.source.tree.ExpressionTree)maps such a tree toUnknown, which does not record that the object is freshly allocated. Anewexpression for an array needs no such treatment:fromTreemaps it to anArrayCreation, whichisFreshlyAllocated(org.checkerframework.dataflow.expression.JavaExpression)recognizes.- Parameters:
tree- an expression tree- Returns:
- true if the given tree is a
newexpression for an object
-
visitEnhancedForLoop
- Specified by:
visitEnhancedForLoopin interfaceTreeVisitor<Void,Void> - Overrides:
visitEnhancedForLoopin classTreeScanner<Void,Void>
-
visitTry
- Specified by:
visitTryin interfaceTreeVisitor<Void,Void> - Overrides:
visitTryin classTreeScanner<Void,Void>
-
checkImplicitCall
protected void checkImplicitCall(Tree node, ExecutableElement invokedElem, @Nullable JavaExpression receiver) Checks a call that the compiler introduces when it desugars the source code, and records any side effect of it that is beyond what theSideEffectsOnlyannotation of the method being checked permits.- Parameters:
node- the tree to report an error atinvokedElem- the implicitly invoked method or constructor, which takes no argumentsreceiver- the receiver of the call, or null if the receiver is an object that no caller can refer to: one that the desugaring created, or one that anewexpression in the code being checked created
-
withReceiver
Returns the given expression with every use ofthisreplaced by the given receiver. This is viewpoint adaptation for a call that takes no arguments, so no formal parameter needs to be replaced.- Parameters:
expr- an expression written at a method's declarationreceiver- the receiver of a call to that method- Returns:
- the expression, written at the call site
-
noArgumentMethod
Returns the no-argument method with the given name that a call on an expression of the given type invokes, or null if there is no such method.- Parameters:
receiverType- the type of the receiver of the callmethodName- the name of the method- Returns:
- the invoked method, or null if the type has no such method
-
visitNewClass
- Specified by:
visitNewClassin interfaceTreeVisitor<Void,Void> - Overrides:
visitNewClassin classTreeScanner<Void,Void>
-
constructorSideEffectedExpressions
protected List<JavaExpression> constructorSideEffectedExpressions(NewClassTree node, ExecutableElement constructorElt, AnnotationMirror seOnlyAnnotation) Returns the expressions that the invoked constructor side-effects: the arguments/elements of itsSideEffectsOnlyannotation, viewpoint-adapted to the given call site.The expression
thisis omitted from the result. In a constructor's annotation,thisis the object being constructed, which did not exist before the call, so modifying it is not a side effect that is visible to the caller. A larger expression that merely containsthis, such asthis.f, gets no such exemption: its value may be an object that existed before the call, as it does for a constructor whose body containsthis.f = p;wherepis a formal parameter.An expression that denotes an object that the call site allocates, in the sense of
isNewObjectTree(com.sun.source.tree.ExpressionTree), is also omitted.If an expression cannot be parsed, this reports
purity.unparseable.sideeffectsonlyand returns an empty list, just ascalleeSideEffectedExpressions(com.sun.source.tree.MethodInvocationTree, javax.lang.model.element.ExecutableElement, java.util.Map<javax.lang.model.element.ExecutableElement, java.util.List<java.lang.String>>)does.- Parameters:
node- a call to a constructor that is annotated withSideEffectsOnlyconstructorElt- the invoked constructorseOnlyAnnotation- the invoked constructor'sSideEffectsOnlyannotation- Returns:
- the expressions that the invoked constructor side-effects, viewpoint-adapted to
node
-
isDisallowedSideEffectedExpression
Returns true if the given expression is a side-effected expression beyond what is listed in theSideEffectsOnlyannotation. That is, all of the following hold:- The expression's value is modifiable by other code.
- The expression is not an object that the method being checked created, in the sense of
isFreshlyAllocated(org.checkerframework.dataflow.expression.JavaExpression). - The expression is not covered by the
SideEffectsOnlyannotation, in the sense ofisCoveredByAnnotation(org.checkerframework.dataflow.expression.JavaExpression).
Use this for an expression whose value is mutated, such as an expression that a callee modifies (e.g., one of the arguments). For an expression that is assigned to, use
isDisallowedAssignmentTarget(org.checkerframework.dataflow.expression.JavaExpression).- Parameters:
expr- the expression to check for side-effecting- Returns:
- true if the given expression is a side-effected expression beyond what is listed in the
SideEffectsOnlyannotation
-
isDisallowedAssignmentTarget
Returns true if assigning to the given expression is a side effect beyond what is listed in theSideEffectsOnlyannotation. That is, all of the following hold:- The expression is assignable by other code; equivalently, the assignment is visible outside the method being checked. (Assigning to a local variable is not.)
- The expression is not part of an object that the method being checked created, in the
sense of
isPartOfFreshlyAllocated(org.checkerframework.dataflow.expression.JavaExpression). - The expression is not covered by the
SideEffectsOnlyannotation, in the sense ofisCoveredByAnnotation(org.checkerframework.dataflow.expression.JavaExpression).
- Parameters:
expr- the expression that is assigned to- Returns:
- true if assigning to the given expression is a side effect beyond what is listed in the
SideEffectsOnlyannotation
-
isFreshlyAllocated
Returns true if the given expression always evaluates to an object that the method being checked created: an array creation expression, or a local variable that always holds such an object. The object did not exist before the call, so modifying it is not a side effect that is visible to the caller.If the object escapes -- if the method stores it into pre-existing state -- then that store is itself a side effect, which is reported unless the annotation covers it. If it is covered, then so is every modification of the object, because the object is then reached through a listed expression.
A
newexpression for an object, rather than for an array, has noJavaExpressionrepresentation; seeisNewObjectTree(com.sun.source.tree.ExpressionTree).- Parameters:
expr- an expression- Returns:
- true if the given expression evaluates to an object that this method created
-
isPartOfFreshlyAllocated
Returns true if the given expression is a field or an array element of an object that the method being checked created. Assigning to it is not visible to the caller.Only the object's own fields and elements qualify. A field of a field does not:
fresh.fmay be an object that existed before the call, so assigning tofresh.f.gis visible to the caller.- Parameters:
expr- an expression- Returns:
- true if the given expression is a field or array element of an object that this method created
-
isCoveredByAnnotation
Returns true if the given expression is listed in theSideEffectsOnlyannotation or is reached through one of the listed expressions.- Parameters:
expr- the expression to look for- Returns:
- true if the given expression is covered by the
SideEffectsOnlyannotation
-
visitLambdaExpression
- Specified by:
visitLambdaExpressionin interfaceTreeVisitor<Void,Void> - Overrides:
visitLambdaExpressionin classTreeScanner<Void,Void>
-
visitClass
- Specified by:
visitClassin interfaceTreeVisitor<Void,Void> - Overrides:
visitClassin classTreeScanner<Void,Void>
-
visitAnnotation
- Specified by:
visitAnnotationin interfaceTreeVisitor<Void,Void> - Overrides:
visitAnnotationin classTreeScanner<Void,Void>
-
visitAssignment
- Specified by:
visitAssignmentin interfaceTreeVisitor<Void,Void> - Overrides:
visitAssignmentin classTreeScanner<Void,Void>
-
visitUnary
- Specified by:
visitUnaryin interfaceTreeVisitor<Void,Void> - Overrides:
visitUnaryin classTreeScanner<Void,Void>
-
visitCompoundAssignment
- Specified by:
visitCompoundAssignmentin interfaceTreeVisitor<Void,Void> - Overrides:
visitCompoundAssignmentin classTreeScanner<Void,Void>
-
freshLocals
Returns the local variables that always hold an object that the given code created: those that are assigned onlynewexpressions.- Parameters:
trees- the code being checked: the body of the method, plus the instance initializers if the method is a constructor- Returns:
- the local variables that always hold an object that
treescreated
-