aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java
blob: 69220ea484ff3e6d3ac708eb4566b26fcda06326 (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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package org.checkerframework.dataflow.cfg.node;

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

import org.checkerframework.dataflow.cfg.CFGBuilder;
import org.checkerframework.dataflow.cfg.block.Block;

import java.util.Collection;
import java.util.LinkedList;

import javax.lang.model.type.TypeMirror;

import com.sun.source.tree.Tree;

/**
 * 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}.
     */
    abstract public /*@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;
    }

}