blob: 6499ed63b394122f6d0a5ac6cd1396f97ee65632 [file] [log] [blame]
package org.checkerframework.dataflow.expression;
import com.sun.source.tree.Tree;
import java.util.Objects;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.UnaryOperationNode;
import org.checkerframework.javacutil.AnnotationProvider;
/** JavaExpression for unary operations. */
public class UnaryOperation extends JavaExpression {
/** The unary operation kind. */
protected final Tree.Kind operationKind;
/** The operand. */
protected final JavaExpression operand;
/**
* Create a unary operation.
*
* @param type the type of the result
* @param operationKind the operator
* @param operand the operand
*/
public UnaryOperation(TypeMirror type, Tree.Kind operationKind, JavaExpression operand) {
super(operand.type);
this.operationKind = operationKind;
this.operand = operand;
}
/**
* Create a unary operation.
*
* @param node the unary operation node
* @param operand the operand
*/
public UnaryOperation(UnaryOperationNode node, JavaExpression operand) {
this(node.getType(), node.getTree().getKind(), operand);
}
/**
* Returns the operator of this unary operation.
*
* @return the unary operation kind
*/
public Tree.Kind getOperationKind() {
return operationKind;
}
/**
* Returns the operand of this unary operation.
*
* @return the operand
*/
public JavaExpression getOperand() {
return operand;
}
@Override
public boolean containsOfClass(Class<? extends JavaExpression> clazz) {
if (getClass() == clazz) {
return true;
}
return operand.containsOfClass(clazz);
}
@Override
public boolean isDeterministic(AnnotationProvider provider) {
return operand.isDeterministic(provider);
}
@Override
public boolean isUnassignableByOtherCode() {
return operand.isUnassignableByOtherCode();
}
@Override
public boolean isUnmodifiableByOtherCode() {
return operand.isUnmodifiableByOtherCode();
}
@Override
public boolean syntacticEquals(JavaExpression je) {
if (!(je instanceof UnaryOperation)) {
return false;
}
UnaryOperation other = (UnaryOperation) je;
return operationKind == other.getOperationKind() && operand.syntacticEquals(other.operand);
}
@Override
public boolean containsSyntacticEqualJavaExpression(JavaExpression other) {
return this.syntacticEquals(other) || operand.containsSyntacticEqualJavaExpression(other);
}
@Override
public boolean containsModifiableAliasOf(Store<?> store, JavaExpression other) {
return operand.containsModifiableAliasOf(store, other);
}
@Override
public int hashCode() {
return Objects.hash(operationKind, operand);
}
@Override
public boolean equals(@Nullable Object other) {
if (!(other instanceof UnaryOperation)) {
return false;
}
UnaryOperation unOp = (UnaryOperation) other;
return operationKind == unOp.getOperationKind() && operand.equals(unOp.operand);
}
@Override
public String toString() {
String operandString = operand.toString();
switch (operationKind) {
case BITWISE_COMPLEMENT:
return "~" + operandString;
case LOGICAL_COMPLEMENT:
return "!" + operandString;
case POSTFIX_DECREMENT:
return operandString + "--";
case POSTFIX_INCREMENT:
return operandString + "++";
case PREFIX_DECREMENT:
return "--" + operandString;
case PREFIX_INCREMENT:
return "++" + operandString;
case UNARY_MINUS:
return "-" + operandString;
case UNARY_PLUS:
return "+" + operandString;
default:
throw new Error("Unrecognized unary operation kind " + operationKind);
}
}
@Override
public <R, P> R accept(JavaExpressionVisitor<R, P> visitor, P p) {
return visitor.visitUnaryOperation(this, p);
}
}