| package org.checkerframework.dataflow.cfg.node; |
| |
| import java.util.Collection; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.checkerframework.dataflow.cfg.node.AssignmentContext.MethodParameterContext; |
| import org.checkerframework.dataflow.util.HashCodeUtils; |
| |
| import org.checkerframework.javacutil.InternalUtils; |
| |
| import com.sun.source.tree.MethodInvocationTree; |
| import com.sun.source.tree.Tree; |
| import com.sun.source.util.TreePath; |
| |
| /** |
| * A node for method invocation |
| * |
| * <pre> |
| * <em>target(arg1, arg2, ...)</em> |
| * </pre> |
| * |
| * CFGs may contain {@link MethodInvocationNode}s that correspond to no AST |
| * {@link Tree}, in which case, the tree field will be null. |
| * |
| * @author Stefan Heule |
| * @author Charlie Garrett |
| * |
| */ |
| public class MethodInvocationNode extends Node { |
| |
| protected MethodInvocationTree tree; |
| protected MethodAccessNode target; |
| protected List<Node> arguments; |
| protected TreePath treePath; |
| |
| public MethodInvocationNode(MethodInvocationTree tree, |
| MethodAccessNode target, List<Node> arguments, TreePath treePath) { |
| super(tree != null ? InternalUtils.typeOf(tree) : target.getMethod().getReturnType()); |
| this.tree = tree; |
| this.target = target; |
| this.arguments = arguments; |
| this.treePath = treePath; |
| |
| // set assignment contexts for parameters |
| int i = 0; |
| for (Node arg : arguments) { |
| AssignmentContext ctx = new MethodParameterContext(target.getMethod(), i++); |
| arg.setAssignmentContext(ctx); |
| } |
| } |
| |
| public MethodInvocationNode(MethodAccessNode target, List<Node> arguments, |
| TreePath treePath) { |
| this(null, target, arguments, treePath); |
| } |
| |
| public MethodAccessNode getTarget() { |
| return target; |
| } |
| |
| public List<Node> getArguments() { |
| return arguments; |
| } |
| |
| public Node getArgument(int i) { |
| return arguments.get(i); |
| } |
| |
| public TreePath getTreePath() { |
| return treePath; |
| } |
| |
| @Override |
| public MethodInvocationTree getTree() { |
| return tree; |
| } |
| |
| @Override |
| public <R, P> R accept(NodeVisitor<R, P> visitor, P p) { |
| return visitor.visitMethodInvocation(this, p); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuffer sb = new StringBuffer(); |
| sb.append(target); |
| sb.append("("); |
| boolean needComma = false; |
| for (Node arg : arguments) { |
| if (needComma) { |
| sb.append(", "); |
| } |
| sb.append(arg); |
| needComma = true; |
| } |
| sb.append(")"); |
| return sb.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj == null || !(obj instanceof MethodInvocationNode)) { |
| return false; |
| } |
| MethodInvocationNode other = (MethodInvocationNode) obj; |
| |
| return getTarget().equals(other.getTarget()) |
| && getArguments().equals(other.getArguments()); |
| } |
| |
| @Override |
| public int hashCode() { |
| int hash = 0; |
| hash = HashCodeUtils.hash(target); |
| for (Node arg : arguments) { |
| hash = HashCodeUtils.hash(hash, arg.hashCode()); |
| } |
| return hash; |
| } |
| |
| @Override |
| public Collection<Node> getOperands() { |
| List<Node> list = new LinkedList<Node>(); |
| list.add(target); |
| list.addAll(arguments); |
| return list; |
| } |
| } |