public TraverserResult traverse()

in src/main/com/intellij/lang/jsgraphql/types/util/Traverser.java [111:186]


  public TraverserResult traverse(Collection<? extends T> roots, TraverserVisitor<? super T> visitor) {
    assertNotNull(roots);
    assertNotNull(visitor);


    // "artificial" parent context for all roots with rootVars
    DefaultTraverserContext<T> rootContext = traverserState.newRootContext(rootVars);
    traverserState.addNewContexts(roots, rootContext);

    DefaultTraverserContext currentContext;
    Object currentAccValue = initialAccumulate;
    traverseLoop:
    while (!traverserState.isEmpty()) {
      Object top = traverserState.pop();

      if (top instanceof TraverserState.EndList) {
        Map<String, List<TraverserContext<T>>> childrenContextMap = ((TraverserState.EndList<T>)top).childrenContextMap;
        // end-of-list marker, we are done recursing children,
        // mark the current node as fully visited
        currentContext = (DefaultTraverserContext)traverserState.pop();
        currentContext.setCurAccValue(currentAccValue);
        currentContext.setChildrenContexts(childrenContextMap);
        currentContext.setPhase(TraverserContext.Phase.LEAVE);
        TraversalControl traversalControl = visitor.leave(currentContext);
        currentAccValue = currentContext.getNewAccumulate();
        assertNotNull(traversalControl, () -> "result of leave must not be null");
        assertTrue(CONTINUE_OR_QUIT.contains(traversalControl), () -> "result can only return CONTINUE or QUIT");

        switch (traversalControl) {
          case QUIT:
            break traverseLoop;
          case CONTINUE:
            continue;
          default:
            assertShouldNeverHappen();
        }
      }

      currentContext = (DefaultTraverserContext)top;

      if (currentContext.isVisited()) {
        currentContext.setCurAccValue(currentAccValue);
        currentContext.setPhase(TraverserContext.Phase.BACKREF);
        TraversalControl traversalControl = visitor.backRef(currentContext);
        currentAccValue = currentContext.getNewAccumulate();
        assertNotNull(traversalControl, () -> "result of backRef must not be null");
        assertTrue(CONTINUE_OR_QUIT.contains(traversalControl), () -> "backRef can only return CONTINUE or QUIT");
        if (traversalControl == QUIT) {
          break traverseLoop;
        }
      }
      else {
        currentContext.setCurAccValue(currentAccValue);
        Object nodeBeforeEnter = currentContext.thisNode();
        currentContext.setPhase(TraverserContext.Phase.ENTER);
        TraversalControl traversalControl = visitor.enter(currentContext);
        currentAccValue = currentContext.getNewAccumulate();
        assertNotNull(traversalControl, () -> "result of enter must not be null");
        this.traverserState.addVisited((T)nodeBeforeEnter);
        switch (traversalControl) {
          case QUIT:
            break traverseLoop;
          case ABORT:
            continue;
          case CONTINUE:
            traverserState.pushAll(currentContext, getChildren);
            continue;
          default:
            assertShouldNeverHappen();
        }
      }
    }

    TraverserResult traverserResult = new TraverserResult(currentAccValue);
    return traverserResult;
  }