Collection<PsiElement> (@NotNull final SliceNode root, @NotNull AbstractTreeStructure treeStructure, @NotNull final Map<SliceNode, Collection<PsiElement>> map) { final SliceNodeGuide guide = new SliceNodeGuide(treeStructure); AtomicInteger depth = new AtomicInteger(); boolean printToLog = LOG.isTraceEnabled(); WalkingState<SliceNode> walkingState = new WalkingState<>(guide) { @Override public void elementStarted(@NotNull SliceNode element) { depth.incrementAndGet(); super.elementStarted(element); } @Override public void visit(@NotNull final SliceNode element) { element.calculateDupNode(); node(element, map).clear(); SliceNode duplicate = element.getDuplicate(); if (duplicate != null) { node(element, map).addAll(node(duplicate, map)); } else { ApplicationManager.getApplication().runReadAction(() -> { final SliceUsage sliceUsage = element.getValue(); Collection<SliceNode> children = element.getChildren(); if (printToLog) { LOG.trace(StringUtil.repeat(" ", Math.max(depth.get(), 0)) + "analyzing usages of " + sliceUsage + " (in " + (sliceUsage == null ? "null" : sliceUsage.getFile().getName() + ":" + sliceUsage.getLine()) + ")"); } if (children.isEmpty() && sliceUsage != null && sliceUsage.canBeLeaf()) { PsiElement value = sliceUsage.getElement(); if (value != null) { node(element, map).add(value); } } }); super.visit(element); } } @Override public void elementFinished(@NotNull SliceNode element) { depth.decrementAndGet(); SliceNode parent = guide.getParent(element); if (parent != null) { node(parent, map).addAll(node(element, map)); } } }; walkingState.visit(root); return node(root, map); }