void (@NotNull VirtualFile file) { // Using the same groupId for several file-processing actions allows undoing [format + optimize imports + rearrange code + cleanup code] in one shot. // Using the same groupId for *all* processed files makes this a single undoable action for all processed files. // See docs for #setProcessAllFilesAsSingleUndoRedoCommand(boolean) String groupId = myProcessAllFilesAsSingleUndoStep ? AbstractLayoutCodeProcessor.this.toString() : AbstractLayoutCodeProcessor.this.toString() + file.hashCode(); for (AbstractLayoutCodeProcessor processor : myProcessors) { FutureTask<Boolean> writeTask; if (processor.needsReadActionToPrepareTask()) { writeTask = ReadAction.nonBlocking(() -> { PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file); return psiFile != null ? processor.prepareTask(psiFile, myProcessChangedTextOnly) : null; }) .executeSynchronously(); } else { PsiFile psiFile = ReadAction.compute(() -> PsiManager.getInstance(myProject).findFile(file)); writeTask = psiFile != null ? processor.prepareTask(psiFile, myProcessChangedTextOnly) : null; } if (writeTask == null) continue; ProgressIndicatorProvider.checkCanceled(); WriteCommandAction.writeCommandAction(myProject) .withName(myCommandName) .withGroupId(groupId) .shouldRecordActionForActiveDocument(myProcessAllFilesAsSingleUndoStep) .run(() -> writeTask.run()); checkStop(writeTask, file); } }