private @NotNull Promise<TreePath> rebuildAndSelect(boolean refilterOnly, Object selection, @Nullable Long rebuildStartTime) {
    if (rebuildStartTime == null) {
      rebuildStartTime = System.nanoTime();
    }

    AsyncPromise<TreePath> result = new AsyncPromise<>();
    Long finalLastRebuildStartTime = rebuildStartTime;
    myStructureTreeModel.getInvoker().invoke(() -> {
      if (refilterOnly) {
        myFilteringStructure.refilter();
        myStructureTreeModel.invalidateAsync().thenRun(() -> {
          (selection == null ? myAsyncTreeModel.accept(o -> TreeVisitor.Action.CONTINUE) : select(selection))
            .onError(ignore2 -> {
              result.setError("rejected");
              mySpeedSearch.refreshSelection(); // Selection failed, let the speed search reflect that by coloring itself red.
            })
            .onSuccess(p -> EdtInvocationManager.invokeLaterIfNeeded(() -> {
              TreeUtil.expand(getTree(),
                              myTreeModel instanceof StructureViewCompositeModel
                              ? 3
                              : 2);
              TreeUtil.ensureSelection(myTree);
              mySpeedSearch.refreshSelection();
              result.setResult(p);
              FileStructurePopupTimeTracker.logRebuildTime(System.nanoTime() - finalLastRebuildStartTime);
            }));
        });
      }
      else {
        myTreeStructure.rebuildTree();
        myStructureTreeModel.invalidateAsync().thenRun(() -> rebuildAndSelect(true, selection, finalLastRebuildStartTime).processed(result));
      }
    }).onError(throwable -> result.setError(throwable));
    return result;
  }
private @NotNull Promise<TreePath> rebuildAndSelect(boolean refilterOnly, Object selection, @Nullable Long rebuildStartTime)