Skip to content

Commit 7c6d687

Browse files
committed
fix and test for simple cycle
1 parent bdd01cb commit 7c6d687

File tree

4 files changed

+27
-12
lines changed

4 files changed

+27
-12
lines changed

src/main/java/graphql/util/Traverser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ public <U> Object traverse(Collection<? extends T> roots, TraverserVisitor<? sup
164164
} else {
165165
TraversalControl traversalControl = visitor.enter(currentContext);
166166
assertNotNull(traversalControl, "result of enter must not be null");
167+
this.traverserState.addVisited((T) currentContext.thisNode());
167168
switch (traversalControl) {
168169
case QUIT:
169170
break traverseLoop;

src/main/java/graphql/util/TraverserState.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ public void clear() {
8989
visited.clear();
9090
}
9191

92+
public void addVisited(T visited) {
93+
this.visited.add(visited);
94+
}
95+
9296
public TraverserContext<T> newContext(T o, TraverserContext<T> parent) {
9397
return newContext(o, parent, new ConcurrentHashMap<>());
9498
}

src/main/java/graphql/util/TraverserVisitor.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ public interface TraverserVisitor<T> {
1414
*
1515
* @param context traverser context
1616
*
17-
* @return either a value to pass to next Visitor's method during traversal
18-
* or a marker to control the traversal
19-
*
2017
* @see TraverserContext
2118
*/
2219
TraversalControl enter(TraverserContext<T> context);
@@ -26,9 +23,6 @@ public interface TraverserVisitor<T> {
2623
*
2724
* @param context traverser context
2825
*
29-
* @return either a value to pass to next Visitor's method during traversal
30-
* or a marker to control the traversal
31-
*
3226
* @see TraverserContext
3327
*/
3428
TraversalControl leave(TraverserContext<T> context);
@@ -40,13 +34,10 @@ public interface TraverserVisitor<T> {
4034
*
4135
* @param context traverser context
4236
*
43-
* @return either a value to pass to next Visitor's method during traversal
44-
* or a marker to control the traversal
45-
*
4637
* @see TraverserContext
4738
*/
48-
default TraversalControl backRef(TraverserContext<T> context) {
49-
return null;
39+
default void backRef(TraverserContext<T> context) {
40+
5041
}
5142

5243
}

src/test/groovy/graphql/util/TraverserTest.groovy

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ class TraverserTest extends Specification {
102102
given:
103103
def initialData = new ArrayList()
104104
def leaveCount = 0
105-
106105
def visitor = [
107106
enter: { TraverserContext context ->
108107
context.getInitialData().add(context.thisNode().number)
@@ -169,6 +168,26 @@ class TraverserTest extends Specification {
169168

170169
then:
171170
initialData == [0, 1, 2, 3]
171+
}
172+
173+
static class Node {
174+
int number
175+
List<Node> children
176+
}
177+
178+
def "simple cycle"() {
179+
given:
180+
def cycleRoot = new Node(number: 0, children: [])
181+
cycleRoot.children.add(cycleRoot)
182+
183+
def visitor = Mock(TraverserVisitor)
184+
when:
185+
Traverser.depthFirst({ n -> n.children }).traverse(cycleRoot, visitor)
186+
187+
then:
188+
1 * visitor.enter(_) >> TraversalControl.CONTINUE
189+
1 * visitor.leave(_) >> TraversalControl.CONTINUE
190+
1 * visitor.backRef({ TraverserContext context -> context.thisNode() == cycleRoot })
172191

173192
}
174193

0 commit comments

Comments
 (0)