void (@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); } }