aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java')
-rw-r--r--third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java491
1 files changed, 0 insertions, 491 deletions
diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java
deleted file mode 100644
index 0b298f1955..0000000000
--- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java
+++ /dev/null
@@ -1,491 +0,0 @@
-package org.checkerframework.dataflow.util;
-
-/*>>>
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
-*/
-
-import com.sun.source.tree.ArrayAccessTree;
-import com.sun.source.tree.AssertTree;
-import com.sun.source.tree.AssignmentTree;
-import com.sun.source.tree.BinaryTree;
-import com.sun.source.tree.BlockTree;
-import com.sun.source.tree.BreakTree;
-import com.sun.source.tree.CaseTree;
-import com.sun.source.tree.CatchTree;
-import com.sun.source.tree.ClassTree;
-import com.sun.source.tree.CompoundAssignmentTree;
-import com.sun.source.tree.ConditionalExpressionTree;
-import com.sun.source.tree.ContinueTree;
-import com.sun.source.tree.DoWhileLoopTree;
-import com.sun.source.tree.EmptyStatementTree;
-import com.sun.source.tree.EnhancedForLoopTree;
-import com.sun.source.tree.ExpressionStatementTree;
-import com.sun.source.tree.ExpressionTree;
-import com.sun.source.tree.ForLoopTree;
-import com.sun.source.tree.IdentifierTree;
-import com.sun.source.tree.IfTree;
-import com.sun.source.tree.InstanceOfTree;
-import com.sun.source.tree.LabeledStatementTree;
-import com.sun.source.tree.LambdaExpressionTree;
-import com.sun.source.tree.LiteralTree;
-import com.sun.source.tree.MemberReferenceTree;
-import com.sun.source.tree.MemberSelectTree;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.NewArrayTree;
-import com.sun.source.tree.NewClassTree;
-import com.sun.source.tree.ParenthesizedTree;
-import com.sun.source.tree.ReturnTree;
-import com.sun.source.tree.SwitchTree;
-import com.sun.source.tree.SynchronizedTree;
-import com.sun.source.tree.ThrowTree;
-import com.sun.source.tree.Tree;
-import com.sun.source.tree.TryTree;
-import com.sun.source.tree.TypeCastTree;
-import com.sun.source.tree.UnaryTree;
-import com.sun.source.tree.VariableTree;
-import com.sun.source.tree.WhileLoopTree;
-import com.sun.source.util.SimpleTreeVisitor;
-import com.sun.tools.javac.tree.TreeScanner;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.List;
-import javax.lang.model.element.Element;
-import org.checkerframework.dataflow.qual.Deterministic;
-import org.checkerframework.dataflow.qual.Pure;
-import org.checkerframework.dataflow.qual.Pure.Kind;
-import org.checkerframework.dataflow.qual.SideEffectFree;
-import org.checkerframework.javacutil.AnnotationProvider;
-import org.checkerframework.javacutil.InternalUtils;
-import org.checkerframework.javacutil.Pair;
-import org.checkerframework.javacutil.TreeUtils;
-
-/**
- * A visitor that determines the purity (as defined by {@link
- * org.checkerframework.dataflow.qual.SideEffectFree}, {@link
- * org.checkerframework.dataflow.qual.Deterministic}, and {@link
- * org.checkerframework.dataflow.qual.Pure}) of a statement or expression. The entry point is method
- * {@link #checkPurity}.
- *
- * @see SideEffectFree
- * @see Deterministic
- * @see Pure
- * @author Stefan Heule
- */
-public class PurityChecker {
-
- /**
- * Compute whether the given statement is side-effect-free, deterministic, or both. Returns a
- * result that can be queried.
- */
- public static PurityResult checkPurity(
- Tree statement, AnnotationProvider annoProvider, boolean assumeSideEffectFree) {
- PurityCheckerHelper helper = new PurityCheckerHelper(annoProvider, assumeSideEffectFree);
- PurityResult res = helper.scan(statement, new PurityResult());
- return res;
- }
-
- /**
- * Result of the {@link PurityChecker}. Can be queried regarding whether a given tree was
- * side-effect-free, deterministic, or both; also gives reasons if the answer is "no".
- */
- public static class PurityResult {
-
- protected final List<Pair<Tree, String>> notSeFreeReasons;
- protected final List<Pair<Tree, String>> notDetReasons;
- protected final List<Pair<Tree, String>> notBothReasons;
- protected EnumSet<Pure.Kind> types;
-
- public PurityResult() {
- notSeFreeReasons = new ArrayList<>();
- notDetReasons = new ArrayList<>();
- notBothReasons = new ArrayList<>();
- types = EnumSet.allOf(Pure.Kind.class);
- }
-
- public EnumSet<Pure.Kind> getTypes() {
- return types;
- }
-
- /** Is the method pure w.r.t. a given set of types? */
- public boolean isPure(Collection<Kind> kinds) {
- return types.containsAll(kinds);
- }
-
- /** Get the {@code reason}s why the method is not side-effect-free. */
- public List<Pair<Tree, String>> getNotSeFreeReasons() {
- return notSeFreeReasons;
- }
-
- /** Add {@code reason} as a reason why the method is not side-effect free. */
- public void addNotSeFreeReason(Tree t, String msgId) {
- notSeFreeReasons.add(Pair.of(t, msgId));
- types.remove(Kind.SIDE_EFFECT_FREE);
- }
-
- /** Get the {@code reason}s why the method is not deterministic. */
- public List<Pair<Tree, String>> getNotDetReasons() {
- return notDetReasons;
- }
-
- /** Add {@code reason} as a reason why the method is not deterministic. */
- public void addNotDetReason(Tree t, String msgId) {
- notDetReasons.add(Pair.of(t, msgId));
- types.remove(Kind.DETERMINISTIC);
- }
-
- /**
- * Get the {@code reason}s why the method is not both side-effect-free and deterministic.
- */
- public List<Pair<Tree, String>> getNotBothReasons() {
- return notBothReasons;
- }
-
- /**
- * Add {@code reason} as a reason why the method is not both side-effect free and
- * deterministic.
- */
- public void addNotBothReason(Tree t, String msgId) {
- notBothReasons.add(Pair.of(t, msgId));
- types.remove(Kind.DETERMINISTIC);
- types.remove(Kind.SIDE_EFFECT_FREE);
- }
- }
-
- /**
- * Helper class to keep {@link PurityChecker}'s interface clean. The implementation is heavily
- * based on {@link TreeScanner}, but some parts of the AST are skipped (such as types or
- * modifiers). Furthermore, scanning works differently in that the input parameter (usually
- * named {@code p}) gets "threaded through", instead of using {@code reduce}.
- */
- protected static class PurityCheckerHelper
- extends SimpleTreeVisitor<PurityResult, PurityResult> {
-
- protected final AnnotationProvider annoProvider;
- /**
- * True if all methods should be assumed to be @SideEffectFree, for the purposes of
- * org.checkerframework.dataflow analysis.
- */
- private final boolean assumeSideEffectFree;
-
- protected /*@Nullable*/ List<Element> methodParameter;
-
- public PurityCheckerHelper(AnnotationProvider annoProvider, boolean assumeSideEffectFree) {
- this.annoProvider = annoProvider;
- this.assumeSideEffectFree = assumeSideEffectFree;
- }
-
- /** Scan a single node. */
- public PurityResult scan(Tree node, PurityResult p) {
- return node == null ? p : node.accept(this, p);
- }
-
- /** Scan a list of nodes. */
- public PurityResult scan(Iterable<? extends Tree> nodes, PurityResult p) {
- PurityResult r = p;
- if (nodes != null) {
- for (Tree node : nodes) {
- r = scan(node, r);
- }
- }
- return r;
- }
-
- @Override
- protected PurityResult defaultAction(Tree node, PurityResult p) {
- assert false : "this type of tree is unexpected here";
- return null;
- }
-
- @Override
- public PurityResult visitClass(ClassTree node, PurityResult p) {
- return p;
- }
-
- @Override
- public PurityResult visitVariable(VariableTree node, PurityResult p) {
- return scan(node.getInitializer(), p);
- }
-
- @Override
- public PurityResult visitEmptyStatement(EmptyStatementTree node, PurityResult p) {
- return p;
- }
-
- @Override
- public PurityResult visitBlock(BlockTree node, PurityResult p) {
- return scan(node.getStatements(), p);
- }
-
- @Override
- public PurityResult visitDoWhileLoop(DoWhileLoopTree node, PurityResult p) {
- PurityResult r = scan(node.getStatement(), p);
- r = scan(node.getCondition(), r);
- return r;
- }
-
- @Override
- public PurityResult visitWhileLoop(WhileLoopTree node, PurityResult p) {
- PurityResult r = scan(node.getCondition(), p);
- r = scan(node.getStatement(), r);
- return r;
- }
-
- @Override
- public PurityResult visitForLoop(ForLoopTree node, PurityResult p) {
- PurityResult r = scan(node.getInitializer(), p);
- r = scan(node.getCondition(), r);
- r = scan(node.getUpdate(), r);
- r = scan(node.getStatement(), r);
- return r;
- }
-
- @Override
- public PurityResult visitEnhancedForLoop(EnhancedForLoopTree node, PurityResult p) {
- PurityResult r = scan(node.getVariable(), p);
- r = scan(node.getExpression(), r);
- r = scan(node.getStatement(), r);
- return r;
- }
-
- @Override
- public PurityResult visitLabeledStatement(LabeledStatementTree node, PurityResult p) {
- return scan(node.getStatement(), p);
- }
-
- @Override
- public PurityResult visitSwitch(SwitchTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- r = scan(node.getCases(), r);
- return r;
- }
-
- @Override
- public PurityResult visitCase(CaseTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- r = scan(node.getStatements(), r);
- return r;
- }
-
- @Override
- public PurityResult visitSynchronized(SynchronizedTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- r = scan(node.getBlock(), r);
- return r;
- }
-
- @Override
- public PurityResult visitTry(TryTree node, PurityResult p) {
- PurityResult r = scan(node.getResources(), p);
- r = scan(node.getBlock(), r);
- r = scan(node.getCatches(), r);
- r = scan(node.getFinallyBlock(), r);
- return r;
- }
-
- @Override
- public PurityResult visitCatch(CatchTree node, PurityResult p) {
- p.addNotDetReason(node, "catch");
- PurityResult r = scan(node.getParameter(), p);
- r = scan(node.getBlock(), r);
- return r;
- }
-
- @Override
- public PurityResult visitConditionalExpression(
- ConditionalExpressionTree node, PurityResult p) {
- PurityResult r = scan(node.getCondition(), p);
- r = scan(node.getTrueExpression(), r);
- r = scan(node.getFalseExpression(), r);
- return r;
- }
-
- @Override
- public PurityResult visitIf(IfTree node, PurityResult p) {
- PurityResult r = scan(node.getCondition(), p);
- r = scan(node.getThenStatement(), r);
- r = scan(node.getElseStatement(), r);
- return r;
- }
-
- @Override
- public PurityResult visitExpressionStatement(ExpressionStatementTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitBreak(BreakTree node, PurityResult p) {
- return p;
- }
-
- @Override
- public PurityResult visitContinue(ContinueTree node, PurityResult p) {
- return p;
- }
-
- @Override
- public PurityResult visitReturn(ReturnTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitThrow(ThrowTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitAssert(AssertTree node, PurityResult p) {
- PurityResult r = scan(node.getCondition(), p);
- r = scan(node.getDetail(), r);
- return r;
- }
-
- @Override
- public PurityResult visitMethodInvocation(MethodInvocationTree node, PurityResult p) {
- Element elt = TreeUtils.elementFromUse(node);
- String reason = "call";
- if (!PurityUtils.hasPurityAnnotation(annoProvider, elt)) {
- p.addNotBothReason(node, reason);
- } else {
- boolean det = PurityUtils.isDeterministic(annoProvider, elt);
- boolean seFree =
- (assumeSideEffectFree || PurityUtils.isSideEffectFree(annoProvider, elt));
- if (!det && !seFree) {
- p.addNotBothReason(node, reason);
- } else if (!det) {
- p.addNotDetReason(node, reason);
- } else if (!seFree) {
- p.addNotSeFreeReason(node, reason);
- }
- }
- PurityResult r = scan(node.getMethodSelect(), p);
- r = scan(node.getArguments(), r);
- return r;
- }
-
- @Override
- public PurityResult visitNewClass(NewClassTree node, PurityResult p) {
- Element methodElement = InternalUtils.symbol(node);
- boolean sideEffectFree =
- (assumeSideEffectFree
- || PurityUtils.isSideEffectFree(annoProvider, methodElement));
- if (sideEffectFree) {
- p.addNotDetReason(node, "object.creation");
- } else {
- p.addNotBothReason(node, "object.creation");
- }
- PurityResult r = scan(node.getEnclosingExpression(), p);
- r = scan(node.getArguments(), r);
- r = scan(node.getClassBody(), r);
- return r;
- }
-
- @Override
- public PurityResult visitNewArray(NewArrayTree node, PurityResult p) {
- PurityResult r = scan(node.getDimensions(), p);
- r = scan(node.getInitializers(), r);
- return r;
- }
-
- @Override
- public PurityResult visitLambdaExpression(LambdaExpressionTree node, PurityResult p) {
- PurityResult r = scan(node.getParameters(), p);
- r = scan(node.getBody(), r);
- return r;
- }
-
- @Override
- public PurityResult visitParenthesized(ParenthesizedTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitAssignment(AssignmentTree node, PurityResult p) {
- ExpressionTree variable = node.getVariable();
- p = assignmentCheck(p, variable);
- PurityResult r = scan(variable, p);
- r = scan(node.getExpression(), r);
- return r;
- }
-
- protected PurityResult assignmentCheck(PurityResult p, ExpressionTree variable) {
- if (TreeUtils.isFieldAccess(variable)) {
- // rhs is a field access
- p.addNotBothReason(variable, "assign.field");
- } else if (variable instanceof ArrayAccessTree) {
- // rhs is array access
- p.addNotBothReason(variable, "assign.array");
- } else {
- // rhs is a local variable
- assert isLocalVariable(variable);
- }
- return p;
- }
-
- protected boolean isLocalVariable(ExpressionTree variable) {
- return variable instanceof IdentifierTree && !TreeUtils.isFieldAccess(variable);
- }
-
- @Override
- public PurityResult visitCompoundAssignment(CompoundAssignmentTree node, PurityResult p) {
- ExpressionTree variable = node.getVariable();
- p = assignmentCheck(p, variable);
- PurityResult r = scan(variable, p);
- r = scan(node.getExpression(), r);
- return r;
- }
-
- @Override
- public PurityResult visitUnary(UnaryTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitBinary(BinaryTree node, PurityResult p) {
- PurityResult r = scan(node.getLeftOperand(), p);
- r = scan(node.getRightOperand(), r);
- return r;
- }
-
- @Override
- public PurityResult visitTypeCast(TypeCastTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- return r;
- }
-
- @Override
- public PurityResult visitInstanceOf(InstanceOfTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- return r;
- }
-
- @Override
- public PurityResult visitArrayAccess(ArrayAccessTree node, PurityResult p) {
- PurityResult r = scan(node.getExpression(), p);
- r = scan(node.getIndex(), r);
- return r;
- }
-
- @Override
- public PurityResult visitMemberSelect(MemberSelectTree node, PurityResult p) {
- return scan(node.getExpression(), p);
- }
-
- @Override
- public PurityResult visitMemberReference(MemberReferenceTree node, PurityResult p) {
- assert false : "this type of tree is unexpected here";
- return null;
- }
-
- @Override
- public PurityResult visitIdentifier(IdentifierTree node, PurityResult p) {
- return p;
- }
-
- @Override
- public PurityResult visitLiteral(LiteralTree node, PurityResult p) {
- return p;
- }
- }
-}