void (@NotNull LighterAST tree, @NotNull LighterASTNode root, @NotNull StubElement<?> rootStub) { Stack<LighterASTNode> parents = new Stack<>(); IntStack childNumbers = new IntArrayList(); BooleanStack parentsStubbed = new BooleanStack(); Stack<List<LighterASTNode>> kinderGarden = new Stack<>(); Stack<StubElement<?>> parentStubs = new Stack<>(); LighterASTNode parent = null; LighterASTNode element = root; List<LighterASTNode> children = null; int childNumber = 0; StubElement<?> parentStub = rootStub; boolean immediateParentStubbed = true; nextElement: while (element != null) { ProgressManager.checkCanceled(); StubElement<?> stub = createStub(tree, element, parentStub); boolean hasStub = stub != parentStub || parent == null; if (hasStub && !immediateParentStubbed) { ((ObjectStubBase<?>)stub).markDangling(); } if (parent == null || !skipNode(tree, parent, element)) { List<LighterASTNode> kids = tree.getChildren(element); if (!kids.isEmpty()) { if (parent != null) { parents.push(parent); childNumbers.push(childNumber); kinderGarden.push(children); parentStubs.push(parentStub); parentsStubbed.push(immediateParentStubbed); } parent = element; immediateParentStubbed = hasStub; element = (children = kids).get(childNumber = 0); parentStub = stub; if (!skipNode(tree, parent, element)) continue; } } while (children != null && ++childNumber < children.size()) { element = children.get(childNumber); if (!skipNode(tree, parent, element)) continue nextElement; } element = null; while (!parents.isEmpty()) { parent = parents.pop(); childNumber = childNumbers.popInt(); children = kinderGarden.pop(); parentStub = parentStubs.pop(); immediateParentStubbed = parentsStubbed.pop(); while (++childNumber < children.size()) { element = children.get(childNumber); if (!skipNode(tree, parent, element)) continue nextElement; } element = null; } } }