void (DefaultMutableTreeNode toExpand, @NotNull List<Object> kidsToExpand, int expandIndex, @NotNull Runnable onDone, boolean canSmartExpand) { Object element = getElementFor(toExpand); if (element == null) { runDone(onDone); return; } addNodeAction(element, true, node -> { if (node.getChildCount() > 0 && !myTree.isExpanded(new TreePath(node.getPath()))) { if (!isAutoExpand(node)) { expand(node, canSmartExpand); } } if (expandIndex <= 0) { runDone(onDone); return; } checkPathAndMaybeRevalidate(kidsToExpand.get(expandIndex - 1), new TreeRunnable("AbstractTreeUi.processExpand") { @Override public void perform() { DefaultMutableTreeNode nextNode = getNodeForElement(kidsToExpand.get(expandIndex - 1), false); processExpand(nextNode, kidsToExpand, expandIndex - 1, onDone, canSmartExpand); } }, false, canSmartExpand); }); boolean childrenToUpdate = areChildrenToBeUpdated(toExpand); boolean expanded = myTree.isExpanded(getPathFor(toExpand)); boolean unbuilt = myUnbuiltNodes.contains(toExpand); if (expanded) { if (unbuilt || childrenToUpdate) { addSubtreeToUpdate(toExpand); } } else { expand(toExpand, canSmartExpand); } if (!unbuilt && !childrenToUpdate) { processNodeActionsIfReady(toExpand); } }