blob: 6b162db6aaeb91091a9e648f05f6f7c51a6ab781 [file] [log] [blame]
package org.checkerframework.dataflow.cfg.node;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.javacutil.TreeUtils;
/**
* A node for an array access:
*
* <pre>
* <em>arrayref</em> [ <em>index</em> ]
* </pre>
*
* We allow array accesses without corresponding AST {@link Tree}s.
*/
public class ArrayAccessNode extends Node {
/** The corresponding ArrayAccessTree. */
protected final Tree tree;
/** The array expression being accessed. */
protected final Node array;
/** The index expresssion used to access the array. */
protected final Node index;
/**
* If this ArrayAccessNode is a node for an array desugared from an enhanced for loop, then the
* {@code arrayExpression} field is the expression in the for loop, e.g., {@code arr} in {@code
* for(Object o: arr}.
*/
protected @Nullable ExpressionTree arrayExpression;
/**
* Create an ArrayAccessNode.
*
* @param t tree for the array access
* @param array the node for the array expression being accessed
* @param index the node for the index used to access the array
*/
public ArrayAccessNode(Tree t, Node array, Node index) {
super(TreeUtils.typeOf(t));
assert t instanceof ArrayAccessTree;
this.tree = t;
this.array = array;
this.index = index;
}
/**
* If this ArrayAccessNode is a node for an array desugared from an enhanced for loop, then return
* the expression in the for loop, e.g., {@code arr} in {@code for(Object o: arr}. Otherwise,
* return null.
*
* @return the array expression, or null if this is not an array desugared from an enhanced for
* loop
*/
public @Nullable ExpressionTree getArrayExpression() {
return arrayExpression;
}
/**
* Set the array expression from a for loop.
*
* @param arrayExpression array expression
* @see #getArrayExpression()
*/
public void setArrayExpression(@Nullable ExpressionTree arrayExpression) {
this.arrayExpression = arrayExpression;
}
/**
* Get the node that represents the array expression being accessed.
*
* @return the array expression node
*/
public Node getArray() {
return array;
}
public Node getIndex() {
return index;
}
@Override
public Tree getTree() {
return tree;
}
@Override
public <R, P> R accept(NodeVisitor<R, P> visitor, P p) {
return visitor.visitArrayAccess(this, p);
}
@Override
public String toString() {
String base = getArray().toString() + "[" + getIndex() + "]";
return base;
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof ArrayAccessNode)) {
return false;
}
ArrayAccessNode other = (ArrayAccessNode) obj;
return getArray().equals(other.getArray()) && getIndex().equals(other.getIndex());
}
@Override
public int hashCode() {
return Objects.hash(getArray(), getIndex());
}
@Override
public Collection<Node> getOperands() {
return Arrays.asList(getArray(), getIndex());
}
}