aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java
blob: fb5bf5335dbbb3454edf1fcefc3453cb562eb432 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package org.checkerframework.dataflow.cfg.node;

/*>>>
import org.checkerframework.checker.nullness.qual.Nullable;
*/

import com.sun.source.tree.Tree;
import java.util.Collection;
import java.util.LinkedList;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.dataflow.cfg.CFGBuilder;
import org.checkerframework.dataflow.cfg.block.Block;

/**
 * A node in the abstract representation used for Java code inside a basic block.
 *
 * <p>The following invariants hold:
 *
 * <pre>
 * block == null || block instanceof RegularBlock || block instanceof ExceptionBlock
 * block instanceof RegularBlock &rArr; block.getContents().contains(this)
 * block instanceof ExceptionBlock &rArr; block.getNode() == this
 * block == null &hArr; "This object represents a parameter of the method."
 * </pre>
 *
 * <pre>
 * type != null
 * tree != null &rArr; node.getType() == InternalUtils.typeOf(node.getTree())
 * </pre>
 *
 * @author Stefan Heule
 */
public abstract class Node {

    /** The basic block this node belongs to (see invariant about this field above). */
    protected /*@Nullable*/ Block block;

    /** Is this node an l-value? */
    protected boolean lvalue = false;

    /** The assignment context of this node. See {@link AssignmentContext}. */
    protected /*@Nullable*/ AssignmentContext assignmentContext;

    /**
     * Does this node represent a tree that appears in the source code (true) or one that the CFG
     * builder added while desugaring (false).
     */
    protected boolean inSource = true;

    /**
     * The type of this node. For {@link Node}s with {@link Tree}s, this type is the type of the
     * {@link Tree}. Otherwise, it is the type is set by the {@link CFGBuilder}.
     */
    protected final TypeMirror type;

    public Node(TypeMirror type) {
        assert type != null;
        this.type = type;
    }

    /**
     * @return the basic block this node belongs to (or {@code null} if it represents the parameter
     *     of a method).
     */
    public /*@Nullable*/ Block getBlock() {
        return block;
    }

    /** Set the basic block this node belongs to. */
    public void setBlock(Block b) {
        block = b;
    }

    /**
     * Returns the {@link Tree} in the abstract syntax tree, or {@code null} if no corresponding
     * tree exists. For instance, this is the case for an {@link ImplicitThisLiteralNode}.
     *
     * @return the corresponding {@link Tree} or {@code null}.
     */
    public abstract /*@Nullable*/ Tree getTree();

    /**
     * Returns a {@link TypeMirror} representing the type of a {@link Node} A {@link Node} will
     * always have a type even when it has no {@link Tree}.
     *
     * @return a {@link TypeMirror} representing the type of this {@link Node}
     */
    public TypeMirror getType() {
        return type;
    }

    /**
     * Accept method of the visitor pattern
     *
     * @param <R> result type of the operation
     * @param <P> parameter type
     * @param visitor the visitor to be applied to this node
     * @param p the parameter for this operation
     */
    public abstract <R, P> R accept(NodeVisitor<R, P> visitor, P p);

    public boolean isLValue() {
        return lvalue;
    }

    /** Make this node an l-value. */
    public void setLValue() {
        lvalue = true;
    }

    public boolean getInSource() {
        return inSource;
    }

    public void setInSource(boolean inSrc) {
        inSource = inSrc;
    }

    public AssignmentContext getAssignmentContext() {
        return assignmentContext;
    }

    public void setAssignmentContext(AssignmentContext assignmentContext) {
        this.assignmentContext = assignmentContext;
    }

    /** @return a collection containing all of the operand {@link Node}s of this {@link Node}. */
    public abstract Collection<Node> getOperands();

    /**
     * @return a collection containing all of the operand {@link Node}s of this {@link Node}, as
     *     well as (transitively) the operands of its operands
     */
    public Collection<Node> getTransitiveOperands() {
        LinkedList<Node> operands = new LinkedList<>(getOperands());
        LinkedList<Node> transitiveOperands = new LinkedList<>();
        while (!operands.isEmpty()) {
            Node next = operands.removeFirst();
            operands.addAll(next.getOperands());
            transitiveOperands.add(next);
        }
        return transitiveOperands;
    }
}