private static Promise<List<TreePath>> promiseVisitAll(@NotNull JTree tree,
                                                               @NotNull Stream<? extends TreeVisitor> visitors,
                                                               @NotNull AsyncPromise<List<TreePath>> promise,
                                                               @NotNull Function<? super TreeVisitor, Promise<TreePath>> visitAction,
                                                               @Nullable Consumer<? super List<TreePath>> consumer) {
    List<Promise<TreePath>> promises = visitors
      .filter(Objects::nonNull)
      .map(visitAction)
      .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;
  }
private static Promise<List<TreePath>> promiseVisitAll(@NotNull JTree tree,
                                                               @NotNull Stream<? extends TreeVisitor> visitors,
                                                               @NotNull AsyncPromise<List<TreePath>> promise,
                                                               @NotNull Function<? super TreeVisitor, Promise<TreePath>> visitAction,
                                                               @Nullable Consumer<? super List<TreePath>> consumer)