private static void applyMultipleEvents(@NotNull BulkFileListener publisher,
                                          @NotNull List<? extends @NotNull Runnable> applyActions,
                                          @NotNull List<? extends @NotNull VFileEvent> applyEvents,
                                          boolean excludeAsyncListeners) {
    PingProgress.interactWithEdtProgress();
    // defensive copying to cope with ill-written listeners that save the passed list for later processing
    List<VFileEvent> toSend = List.of(applyEvents.toArray(new VFileEvent[0]));
    Throwable x = null;

    try {
      if (excludeAsyncListeners) AsyncEventSupport.markAsynchronouslyProcessedEvents(toSend);

      try {
        fireBeforeEvents(publisher, toSend);
      }
      catch (Throwable t) {
        x = t;
      }

      PingProgress.interactWithEdtProgress();
      for (Runnable runnable : applyActions) {
        try {
          runnable.run();
        }
        catch (Throwable t) {
          if (x != null) t.addSuppressed(x);
          x = t;
        }
      }

      PingProgress.interactWithEdtProgress();
      try {
        fireAfterEvents(publisher, toSend);
      }
      catch (Throwable t) {
        if (x != null) t.addSuppressed(x);
        x = t;
      }
    }
    finally {
      if (excludeAsyncListeners) AsyncEventSupport.unmarkAsynchronouslyProcessedEvents(toSend);
      if (x != null) ExceptionUtil.rethrow(x);
    }
  }
private static void applyMultipleEvents(@NotNull BulkFileListener publisher,
                                          @NotNull List<? extends @NotNull Runnable> applyActions,
                                          @NotNull List<? extends @NotNull VFileEvent> applyEvents,
                                          boolean excludeAsyncListeners)