private void doUndoOrRedo(final boolean isUndo) throws UnexpectedUndoException {
    // perform undo action by action, setting bulk update flag if possible
    // if multiple consecutive actions share a document, then set the bulk flag only once
    final UnexpectedUndoException[] exception = {null};
    ApplicationManager.getApplication().runWriteAction(() -> {
      try {
        List<? extends UndoableAction> actionsList = isUndo ? ContainerUtil.reverse(myActions) : myActions;
        int toProcess = 0; // index of first action not yet performed
        int toProcessInBulk = 0; // index of first action that can be executed in bulk mode
        int actionCount = actionsList.size();
        for (int i = 0; i < actionCount; i++) {
          UndoableAction action = actionsList.get(i);
          DocumentEx newDocument = getDocumentToSetBulkMode(action);
          if (newDocument == null) {
            if (i - toProcessInBulk > BULK_MODE_ACTION_THRESHOLD) {
              performActions(actionsList.subList(toProcess, toProcessInBulk), isUndo, false);
              performActions(actionsList.subList(toProcessInBulk, i), isUndo, true);
              toProcess = i;
            }
            toProcessInBulk = i + 1;
          }
        }
        if (actionCount - toProcessInBulk > BULK_MODE_ACTION_THRESHOLD) {
          performActions(actionsList.subList(toProcess, toProcessInBulk), isUndo, false);
          performActions(actionsList.subList(toProcessInBulk, actionCount), isUndo, true);
        }
        else {
          performActions(actionsList.subList(toProcess, actionCount), isUndo, false);
        }
      }
      catch (UnexpectedUndoException e) {
        exception[0] = e;
      }
    });
    if (exception[0] != null) {
      throw exception[0];
    }
  }
private void doUndoOrRedo(final boolean isUndo)