public static <T> void replaceInjectionsWithUndo(final Project project,
                                                   @Nullable PsiFile hostFile,
                                                   final T add,
                                                   final T remove,
                                                   boolean global,
                                                   final List<? extends PsiElement> psiElementsToRemove,
                                                   final PairProcessor<? super T, ? super T> actualProcessor) {

    PsiFile[] psiFiles = StreamEx.ofNullable(hostFile)
                                 .append(psiElementsToRemove
                                           .stream()
                                           .map(e -> e.getContainingFile()))
                                 .filter(e -> !(e instanceof PsiCompiledElement))
                                 .toArray(PsiFile.class);

    DocumentReference[] documentReferences = ContainerUtil
      .map2Array(psiFiles, DocumentReference.class, file -> DocumentReferenceManager.getInstance().create(file.getVirtualFile()));

    final UndoableAction action = new BasicUndoableAction(documentReferences) {
      @Override
      public void undo() {
        actualProcessor.process(remove, add);
      }

      @Override
      public void redo() {
        actualProcessor.process(add, remove);
      }

      @Override
      public boolean isGlobal() {
        return global;
      }
    };
    WriteCommandAction.writeCommandAction(project, psiFiles)
                      .withName(IntelliLangBundle.message("command.name.language.injection.configuration.update"))
                      .withUndoConfirmationPolicy(UndoConfirmationPolicy.REQUEST_CONFIRMATION)
                      .run(() -> {
                        for (PsiElement annotation : psiElementsToRemove) {
                          if (!annotation.isValid()) continue;
                          annotation.delete();
                        }
                        actualProcessor.process(add, remove);
                        UndoManager.getInstance(project).undoableActionPerformed(action);
                      });
  }
public static <T> void replaceInjectionsWithUndo(final Project project,
                                                   @Nullable PsiFile hostFile,
                                                   final T add,
                                                   final T remove,
                                                   boolean global,
                                                   final List<? extends PsiElement> psiElementsToRemove,
                                                   final PairProcessor<? super T, ? super T> actualProcessor)