Skip to content

Commit

Permalink
Add more visit methods
Browse files Browse the repository at this point in the history
  • Loading branch information
matozoid committed Oct 23, 2017
1 parent 8e6034e commit 6019c76
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 24 deletions.
70 changes: 50 additions & 20 deletions javaparser-core/src/main/java/com/github/javaparser/ast/Node.java
Expand Up @@ -728,24 +728,9 @@ public Stream<Node> stream() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(treeIterator(PREORDER), NONNULL | DISTINCT), false);
}

/**
* Walks the AST, applying the function for every node, with traversal algorithm "traversal".
* If the function returns something else than null, the traversal is stopped and the function result is returned.
* <br/>This is the most general walk method. All other walk and find methods are based on this.
*/
public <T> Optional<T> walk(TreeTraversal traversal, Function<Node, T> consumer) {
for (Node node : treeIterable(traversal)) {
T result = consumer.apply(node);
if (result != null) {
return Optional.of(result);
}
}
return Optional.empty();
}


/**
* Walks the AST, calling the consumer for every node, with traversal algorithm "traversal".
* <br/>This is the most general walk method. All other walk and findAll methods are based on this.
*/
public void walk(TreeTraversal traversal, Consumer<Node> consumer) {
// Could be implemented as a call to the above walk method, but this is a little more efficient.
Expand Down Expand Up @@ -792,18 +777,63 @@ public <T extends Node> List<T> findAll(Class<T> nodeType, Predicate<T> predicat
return found;
}

/**
* Walks the AST, applying the function for every node, with traversal algorithm "traversal". If the function
* returns something else than null, the traversal is stopped and the function result is returned. <br/>This is the
* most general findFirst method. All other findFirst methods are based on this.
*/
public <T> Optional<T> findFirst(TreeTraversal traversal, Function<Node, Optional<T>> consumer) {
for (Node node : treeIterable(traversal)) {
final Optional<T> result = consumer.apply(node);
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}

/**
* Walks the AST with pre-order traversal, returning the first node of type "nodeType" or empty() if none is found.
*/
public <N extends Node> Optional<N> findFirst(Class<N> nodeType) {
return walk(TreeTraversal.PREORDER, node -> {
if(nodeType.isAssignableFrom(node.getClass())){
return nodeType.cast(node);
return findFirst(TreeTraversal.PREORDER, node -> {
if (nodeType.isAssignableFrom(node.getClass())) {
return Optional.of(nodeType.cast(node));
}
return null;
return Optional.empty();
});
}

/**
* Walks the AST with pre-order traversal, returning the first node of type "nodeType" that matches "predicate" or empty() if none is
* found.
*/
public <N extends Node> Optional<N> findFirst(Class<N> nodeType, Predicate<N> predicate) {
return findFirst(TreeTraversal.PREORDER, node -> {
if (nodeType.isAssignableFrom(node.getClass())) {
final N castNode = nodeType.cast(node);
if (predicate.test(castNode)) {
return Optional.of(castNode);
}
}
return Optional.empty();
});
}

/**
* Walks the parents of this node, returning the first node of type "nodeType" or empty() if none is found.
*/
public <N extends Node> Optional<N> findParent(Class<N> nodeType) {
Node n = this;
while (n.getParentNode().isPresent()) {
n = n.getParentNode().get();
if (nodeType.isAssignableFrom(n.getClass())) {
return Optional.of(nodeType.cast(n));
}
}
return Optional.empty();
}

/**
* Performs a breadth-first node traversal starting with a given node.
*
Expand Down
Expand Up @@ -31,16 +31,14 @@
import com.github.javaparser.ast.comments.LineComment;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.IntegerLiteralExpr;
import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.ast.observer.AstObserver;
import com.github.javaparser.ast.observer.AstObserverAdapter;
import com.github.javaparser.ast.observer.ObservableProperty;
import com.github.javaparser.ast.type.PrimitiveType;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

import static com.github.javaparser.JavaParser.parse;
Expand Down Expand Up @@ -339,6 +337,13 @@ public void findCompilationUnit() {
assertEquals(cu, x.findCompilationUnit().get());
}

@Test
public void findParent() {
CompilationUnit cu = parse("class X{int x;}");
SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariables().get(0).getName();
assertEquals("int x;", x.findParent(FieldDeclaration.class).get().toString());
}

@Test
public void cantFindCompilationUnit() {
VariableDeclarator x = new VariableDeclarator();
Expand Down Expand Up @@ -382,6 +387,20 @@ public void typeOnlyFindAllMatchesSubclasses() {
assertEquals("[1 + 2 + 3, 1 + 2, 1, 2, 3]", ints.toString());
}

@Test
public void conditionalTypedFindFirst() {
Expression e = parseExpression("1+2+3");
Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class, n -> n.asInt() > 1);
assertEquals("Optional[2]", ints.toString());
}

@Test
public void typeOnlyFindFirst() {
Expression e = parseExpression("1+2+3");
Optional<IntegerLiteralExpr> ints = e.findFirst(IntegerLiteralExpr.class);
assertEquals("Optional[1]", ints.toString());
}

@Test
public void stream() {
Expression e = parseExpression("1+2+3");
Expand Down

0 comments on commit 6019c76

Please sign in to comment.