Skip to content

Commit

Permalink
Add upwards and direct-children-only traversal
Browse files Browse the repository at this point in the history
  • Loading branch information
matozoid committed Oct 21, 2017
1 parent c7311b5 commit b8bb086
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 2 deletions.
Expand Up @@ -686,7 +686,7 @@ protected SymbolResolver getSymbolResolver() {




public enum TreeTraversal { public enum TreeTraversal {
PREORDER, BREADTHFIRST, POSTORDER PREORDER, BREADTHFIRST, POSTORDER, PARENTS, DIRECT_CHILDREN
} }


public Iterator<Node> treeIterator(TreeTraversal traversal) { public Iterator<Node> treeIterator(TreeTraversal traversal) {
Expand All @@ -697,6 +697,10 @@ public Iterator<Node> treeIterator(TreeTraversal traversal) {
return new TreeVisitor.PostOrderIterator(this); return new TreeVisitor.PostOrderIterator(this);
case PREORDER: case PREORDER:
return new TreeVisitor.PreOrderIterator(this); return new TreeVisitor.PreOrderIterator(this);
case DIRECT_CHILDREN:
return new TreeVisitor.DirectChildrenIterator(this);
case PARENTS:
return new TreeVisitor.ParentsVisitor(this);
default: default:
throw new IllegalArgumentException("Unknown traversal choice."); throw new IllegalArgumentException("Unknown traversal choice.");
} }
Expand Down
Expand Up @@ -65,6 +65,47 @@ public Node next() {
} }
} }


public static class DirectChildrenIterator implements Iterator<Node> {
private final Iterator<Node> childrenIterator;

public DirectChildrenIterator(Node node) {
childrenIterator = new ArrayList<>(node.getChildNodes()).iterator();
}

@Override
public boolean hasNext() {
return childrenIterator.hasNext();
}

@Override
public Node next() {
return childrenIterator.next();
}
}

/**
* Iterates over the parent of the node, then the parent's parent, then the parent's parent's parent, until running
* out of parents.
*/
public static class ParentsVisitor implements Iterator<Node> {
private Node node;

public ParentsVisitor(Node node) {
this.node = node;
}

@Override
public boolean hasNext() {
return node.getParentNode().isPresent();
}

@Override
public Node next() {
node = node.getParentNode().orElse(null);
return node;
}
}

public static class PreOrderIterator implements Iterator<Node> { public static class PreOrderIterator implements Iterator<Node> {
private final Stack<Node> stack = new Stack<>(); private final Stack<Node> stack = new Stack<>();


Expand Down Expand Up @@ -177,6 +218,25 @@ public void visitBreadthFirst(Node node) {
new BreadthFirstIterator(node).forEachRemaining(this::process); new BreadthFirstIterator(node).forEachRemaining(this::process);
} }


/**
* Calls "process" for each direct child node of "node"
*
* @param node the parent node.
*/
public void visitDirectChildren(Node node) {
new DirectChildrenIterator(node).forEachRemaining(this::process);
}

/**
* Calls "process" for the parent of "node", then the parent's parent, then the parent's parent's parent, until
* running out of parents. <br/>Note that "node" itself is not processed.
*
* @param node the start node.
*/
public void visitParents(Node node) {
new ParentsVisitor(node).forEachRemaining(this::process);
}

/** /**
* Process the given node. * Process the given node.
* *
Expand Down
Expand Up @@ -22,17 +22,19 @@
package com.github.javaparser.ast.visitor; package com.github.javaparser.ast.visitor;


import com.github.javaparser.JavaParser; import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node; import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.ArrayInitializerExpr; import com.github.javaparser.ast.expr.ArrayInitializerExpr;
import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.IntegerLiteralExpr; import com.github.javaparser.ast.expr.IntegerLiteralExpr;
import com.github.javaparser.ast.expr.SimpleName;
import org.junit.Test; import org.junit.Test;


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;


public class TreeVisitorTest { public class TreeVisitorTest {
@Test @Test
public void breadthFirst() { public void isValidBreadthFirstTraversal() {
Expression expression = JavaParser.parseExpression("(2+3)+(4+5)"); Expression expression = JavaParser.parseExpression("(2+3)+(4+5)");


StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
Expand Down Expand Up @@ -116,4 +118,40 @@ public void process(Node node) {
} }
}.visitPostOrder(JavaParser.parseExpression("new int[]{1,2,3,4}")); }.visitPostOrder(JavaParser.parseExpression("new int[]{1,2,3,4}"));
} }

@Test
public void parents() {
CompilationUnit cu = JavaParser.parse("class X{int x=1;}");
SimpleName x = cu.getClassByName("X").get().getMember(0).asFieldDeclaration().getVariable(0).getName();

TreeVisitor.ParentsVisitor visitor = new TreeVisitor.ParentsVisitor(x);
assertEquals("x = 1", visitor.next().toString());
assertEquals("int x = 1;", visitor.next().toString());
assertEquals("class X {\n" +
"\n" +
" int x = 1;\n" +
"}", visitor.next().toString());
assertEquals("class X {\n" +
"\n" +
" int x = 1;\n" +
"}\n", visitor.next().toString());
assertEquals(false, visitor.hasNext());
}

@Test
public void isValidDirectChildrenTraversal() {
Expression expression = JavaParser.parseExpression("(2+3)+(4+5)");

StringBuilder result = new StringBuilder();

TreeVisitor visitor = new TreeVisitor() {
@Override
public void process(Node node) {
result.append("<").append(node).append("> ");
}
};

visitor.visitDirectChildren(expression);
assertEquals("<(2 + 3)> <(4 + 5)> ", result.toString());
}
} }

0 comments on commit b8bb086

Please sign in to comment.