org.checkerframework.dataflow.cfg.node.CaseNode Maven / Gradle / Ivy
package org.checkerframework.dataflow.cfg.node;
import com.sun.source.tree.CaseTree;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.plumelib.util.StringsPlume;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.Types;
/**
* A node for a case in a switch statement. Although a case has no abstract value, it can imply
* facts about the abstract values of its operands.
*
*
* case constant:
*
*/
public class CaseNode extends Node {
/** The tree for this node. */
protected final CaseTree tree;
/**
* The Node for the assignment of the switch selector expression to a synthetic local variable.
*/
protected final AssignmentNode selectorExprAssignment;
/**
* The case expressions to match the switch expression against: the operands of (possibly
* multiple) case labels.
*/
protected final List caseExprs;
/** The guard (the expression in the {@code when} clause) for this case. */
protected final @Nullable Node guard;
/**
* Create a new CaseNode.
*
* @param tree the tree for this node
* @param selectorExprAssignment the Node for the assignment of the switch selector expression
* to a synthetic local variable
* @param caseExprs the case expression(s) to match the switch expression against
* @param guard the guard expression or null
* @param types a factory of utility methods for operating on types
*/
public CaseNode(
CaseTree tree,
AssignmentNode selectorExprAssignment,
List caseExprs,
@Nullable Node guard,
Types types) {
super(types.getNoType(TypeKind.NONE));
this.tree = tree;
this.selectorExprAssignment = selectorExprAssignment;
this.caseExprs = caseExprs;
this.guard = guard;
}
/**
* The Node for the assignment of the switch selector expression to a synthetic local variable.
* This is used to refine the type of the switch selector expression in a case block.
*
* @return the assignment of the switch selector expression to a synthetic local variable
*/
public AssignmentNode getSwitchOperand() {
return selectorExprAssignment;
}
/**
* Gets the nodes corresponding to the case expressions. There can be multiple expressions since
* Java 12.
*
* @return the nodes corresponding to the (potentially multiple) case expressions
*/
public List getCaseOperands() {
return caseExprs;
}
/**
* Gets the node for the guard (the expression in the {@code when} clause).
*
* @return the node for the guard
*/
public @Nullable Node getGuard() {
return guard;
}
@Override
public CaseTree getTree() {
return tree;
}
@Override
public R accept(NodeVisitor visitor, P p) {
return visitor.visitCase(this, p);
}
@Override
public String toString() {
return "case " + StringsPlume.join(", ", getCaseOperands()) + ":";
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof CaseNode)) {
return false;
}
CaseNode other = (CaseNode) obj;
return getSwitchOperand().equals(other.getSwitchOperand())
&& getCaseOperands().equals(other.getCaseOperands());
}
@Override
public int hashCode() {
return Objects.hash(getSwitchOperand(), getCaseOperands());
}
@Override
@SideEffectFree
public Collection getOperands() {
List caseOperands = getCaseOperands();
ArrayList operands = new ArrayList<>(caseOperands.size() + 1);
operands.add(getSwitchOperand());
operands.addAll(caseOperands);
return operands;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy