Java程序  |  81行  |  2.56 KB

package annotator.find;

import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;

public class ReceiverCriterion implements Criterion {

  private final String methodName; // no return type
  private final Criterion isSigMethodCriterion;

  public ReceiverCriterion(String methodName) {
    this.methodName = methodName;
    isSigMethodCriterion = Criteria.isSigMethod(methodName);
  }

  /** {@inheritDoc} */
  @Override
  public boolean isSatisfiedBy(TreePath path, Tree leaf) {
    assert path == null || path.getLeaf() == leaf;
    return isSatisfiedBy(path);
  }

  /** {@inheritDoc} */
  @Override
  public boolean isSatisfiedBy(TreePath path) {
    // want to annotate BlockTree returned by MethodTree.getBody();
    if (path == null) {
      return false;
    }

    if (path.getLeaf().getKind() == Tree.Kind.METHOD) {
      if (isSigMethodCriterion.isSatisfiedBy(path)) {
          MethodTree leaf = (MethodTree) path.getLeaf();
          // If the method already has a receiver, then insert directly on the
          // receiver, not on the method.
          return leaf.getReceiverParameter() == null;
      }
      return false;
    } else {
      // We may be attempting to insert an annotation on a type parameter of an
      // existing receiver, so make sure this is the right receiver parameter:
      // work up the tree to find the method declaration. Store the parameter we
      // pass through up to the method declaration so we can make sure we came up
      // through the receiver. Then check to make sure this is the correct method
      // declaration.
      Tree param = null;
      TreePath parent = path;
      while (parent != null && parent.getLeaf().getKind() != Tree.Kind.METHOD) {
        if (parent.getLeaf().getKind() == Tree.Kind.VARIABLE) {
          if (param == null) {
            param = parent.getLeaf();
          } else {
            // The only variable we should pass through is the receiver parameter.
            // If we pass through more than one then this isn't the right place.
            return false;
          }
        }
        parent = parent.getParentPath();
      }
      if (parent != null && param != null) {
        MethodTree method = (MethodTree) parent.getLeaf();
        if (param == method.getReceiverParameter()) {
          return isSigMethodCriterion.isSatisfiedBy(parent);
        }
      }
      return false;
    }
  }

  @Override
  public Kind getKind() {
    return Kind.RECEIVER;
  }

  @Override
  public String toString() {
    return "ReceiverCriterion for method: " + methodName;
  }
}