private String getTestNameBottomUp(MethodInvocation invocation) {
   String result = "";
   while (invocation != null) {
     MethodInvocation nameInvocation = invocation;
     if (invocation.target().name().equals("taggedAs")
         && invocation.target() instanceof MethodInvocation) {
       nameInvocation = (MethodInvocation) invocation.target();
     }
     if (!nameInvocation.target().canBePartOfTestName()
         || (!invocation.name().equals("in") && invocation.canBePartOfTestName())) return null;
     String targetText =
         (nameInvocation.name().equals("in") || nameInvocation.name().equals("taggedAs"))
             ? nameInvocation.target().toString()
             : (nameInvocation.target().toString() + " " + nameInvocation.name());
     result = targetText + " " + result;
     if (invocation.parent() != null && invocation.parent() instanceof MethodInvocation)
       invocation = (MethodInvocation) invocation.parent();
     else invocation = null;
   }
   return result.trim();
 }
  private List<String> getTestNamesTopDown(MethodInvocation invocation) {
    List<String> results = new ArrayList<String>();
    List<AstNode> nodes = new ArrayList<AstNode>();
    nodes.add(invocation);

    while (nodes.size() > 0) {
      AstNode head = nodes.remove(0);
      if (head instanceof MethodInvocation) {
        MethodInvocation headInvocation = (MethodInvocation) head;
        if (headInvocation.name().equals("in")) {
          String testName = getTestNameBottomUp(headInvocation);
          if (testName != null) {
            results.add(testName);
          }
        } else nodes.addAll(0, Arrays.asList(headInvocation.children()));
      }
    }

    return results;
  }
  public Selection find(AstNode node) {
    Selection result = null;
    while (result == null) {
      if (node instanceof MethodInvocation) {
        MethodInvocation invocation = (MethodInvocation) node;
        String name = invocation.name();
        AstNode parent = invocation.parent();
        if (name.equals("in") && scopeSet.contains(parent.name())) {
          String testName = getTestNameBottomUp(invocation);
          result =
              testName != null
                  ? new Selection(invocation.className(), testName, new String[] {testName})
                  : null;
          if (testName == null) {
            if (node.parent() != null) {
              node = node.parent();
            } else break;
          }
        } else if (scopeSet.contains(name)) {
          String displayName = getDisplayNameBottomUp(invocation);
          List<String> testNames = getTestNamesTopDown(invocation);
          result =
              new Selection(
                  invocation.className(),
                  displayName,
                  testNames.toArray(new String[testNames.size()]));
        }
      }

      if (result == null) {
        if (node.parent() != null) node = node.parent();
        else break;
      }
    }
    return result;
  }