Promise<List<TreePath>> (@NotNull JTree tree, @NotNull Stream<? extends TreeVisitor> visitors, @Nullable Consumer<? super List<TreePath>> consumer) { AsyncPromise<List<TreePath>> promise = new AsyncPromise<>(); List<Promise<TreePath>> promises = visitors .filter(Objects::nonNull) .map(visitor -> promiseMakeVisible(tree, visitor, promise)) .collect(toList()); Promises.collectResults(promises, true) .onError(promise::setError) .onSuccess(paths -> { if (promise.isCancelled()) return; if (!ContainerUtil.isEmpty(paths)) { EdtInvocationManager.invokeLaterIfNeeded(() -> { if (promise.isCancelled()) return; List<TreePath> visible = ContainerUtil.filter(paths, tree::isVisible); if (!ContainerUtil.isEmpty(visible)) { if (consumer != null) consumer.accept(visible); promise.setResult(visible); } else { promise.cancel(); } }); } else { promise.cancel(); } }); return promise; }