TreeUtils { @CheckForNull public static Tree findAncestorWithKind(Tree tree, Collection<Tree.Kind> kinds) { Tree parent = tree; while (parent != null && !kinds.contains(parent.getKind())) { parent = parent.getParent(); } return parent; } private  TreeUtils(); static boolean isDescendant(Tree tree, Tree potentialParent); @CheckForNull static Tree findAncestorWithKind(Tree tree, Collection<Tree.Kind> kinds); static Stream<Tree> descendants(@Nullable Tree root); static Stream<T> descendants(@Nullable Tree root, Class<T> clazz); static Optional<Tree> firstDescendant(@Nullable Tree root, Predicate<Tree> predicate); static Optional<T> firstDescendant(Tree root, Class<T> clazz);  }
@Test public void test_findAncestorWithKind() { Tree tree = PHPParserBuilder.createParser().parse("<?= function foo() {for(;;) {} } ?>"); FunctionDeclarationTree func = (FunctionDeclarationTree) ((CompilationUnitTreeImpl) tree).script().statements().get(0); StatementTree statementTree = func.body().statements().get(0); assertThat(findAncestorWithKind(statementTree, EnumSet.of(Tree.Kind.FUNCTION_DECLARATION))).isEqualTo(func); assertThat(findAncestorWithKind(statementTree, EnumSet.of(Tree.Kind.SCRIPT, Tree.Kind.FUNCTION_DECLARATION))).isEqualTo(func); assertThat(findAncestorWithKind(statementTree, singletonList(Tree.Kind.WHILE_STATEMENT))).isNull(); assertThat(findAncestorWithKind(func, singletonList(Tree.Kind.FUNCTION_DECLARATION))).isEqualTo(func); }