int (@NotNull List<? extends CompoundVFileEvent> events, int startIndex, @NotNull List<? super Runnable> outApplyActions, @NotNull List<? super VFileEvent> outValidatedEvents, @NotNull MostlySingularMultiMap<String, VFileEvent> filesInvolved, @NotNull Set<? super String> middleDirsInvolved, @NotNull Map<VirtualDirectoryImpl, Object> toCreate, @NotNull Set<VFileEvent> toIgnore, @NotNull Set<? super VirtualFile> toDelete, boolean excludeAsyncListeners) { int endIndex = groupByPath(events, startIndex, filesInvolved, middleDirsInvolved, toDelete, toCreate, toIgnore); assert endIndex > startIndex : events.get(startIndex) + "; files: " + filesInvolved + "; middleDirs: " + middleDirsInvolved; // since all events in the group events[`startIndex`..`endIndex`) are mutually non-conflicting, we can re-arrange creations/deletions together groupCreations(outValidatedEvents, outApplyActions, toCreate); groupDeletions(events, startIndex, endIndex, outValidatedEvents, outApplyActions, toIgnore); groupOthers(events, startIndex, endIndex, outValidatedEvents, outApplyActions); for (int i = startIndex; i < endIndex; i++) { CompoundVFileEvent event = events.get(i); outApplyActions.addAll(event.getApplyActions()); if (excludeAsyncListeners && !event.areInducedEventsCalculated()) { LOG.error("Nested file events must be processed by async file listeners! Event: " + event); } for (VFileEvent jarDeleteEvent : event.getInducedEvents()) { outApplyActions.add((Runnable)() -> applyEvent(jarDeleteEvent)); outValidatedEvents.add(jarDeleteEvent); } } return endIndex; }