private static void doPasteAction(final Editor editor,
                                    final Project project,
                                    final PsiFile file,
                                    final Document document,
                                    @NotNull final Transferable content,
                                    @NotNull final TypingActionsExtension typingActionsExtension) {
    CopyPasteManager.getInstance().stopKillRings();

    String text = null;
    try {
      text = (String)content.getTransferData(DataFlavor.stringFlavor);
    }
    catch (Exception e) {
      editor.getComponent().getToolkit().beep();
    }
    if (text == null) return;
    int textLength = text.length();
    if (BasePasteHandler.isContentTooLarge(textLength)) {
      BasePasteHandler.contentLengthLimitExceededMessage(textLength);
      return;
    }

    final CodeInsightSettings settings = CodeInsightSettings.getInstance();

    final List<ProcessorAndData<?>> extraData = new ArrayList<>();
    final Collection<TextBlockTransferableData> allValues = new ArrayList<>();

    for (CopyPastePostProcessor<? extends TextBlockTransferableData> processor : CopyPastePostProcessor.EP_NAME.getExtensionList()) {
      ProcessorAndData<? extends TextBlockTransferableData> data = ProcessorAndData.create(processor, content);
      if (data != null) {
        extraData.add(data);
        allValues.addAll(data.data);
      }
    }

    text = TextBlockTransferable.convertLineSeparators(editor, text, allValues);

    final CaretModel caretModel = editor.getCaretModel();
    final SelectionModel selectionModel = editor.getSelectionModel();
    final int col = caretModel.getLogicalPosition().column;

    // There is a possible case that we want to perform paste while there is an active selection at the editor and caret is located
    // inside it (e.g. Ctrl+A is pressed while caret is not at the zero column). We want to insert the text at selection start column
    // then, hence, inserted block of text should be indented according to the selection start as well.
    final int blockIndentAnchorColumn;
    final int caretOffset = caretModel.getOffset();
    if (selectionModel.hasSelection() && caretOffset >= selectionModel.getSelectionStart()) {
      blockIndentAnchorColumn = editor.offsetToLogicalPosition(selectionModel.getSelectionStart()).column;
    }
    else {
      blockIndentAnchorColumn = col;
    }

    // We assume that EditorModificationUtil.insertStringAtCaret() is smart enough to remove currently selected text (if any).

    CopyPasteOptions copyPasteOptions = CopyPasteOptionsTransferableData.valueFromTransferable(content);
    CopiedFromEmptySelectionPasteMode pasteMode = copyPasteOptions.isCopiedFromEmptySelection()
                                                  ? getCopiedFromEmptySelectionPasteMode() : AT_CARET;
    boolean isInsertingEntireLineAboveCaret = pasteMode == ENTIRE_LINE_ABOVE_CARET &&
                                              !selectionModel.hasSelection();
    List<CaretState> caretStateToRestore = null;
    if (isInsertingEntireLineAboveCaret) {
      // Make CopyPastePreProcessors see the caret at the real insertion offset.
      caretStateToRestore = caretModel.getCaretsAndSelections();
      int lineStartOffset = EditorUtil.getNotFoldedLineStartOffset(editor, caretOffset);
      caretModel.moveToOffset(lineStartOffset);
    }

    RawText rawText = RawText.fromTransferable(content);
    String newText = text;
    for (CopyPastePreProcessor preProcessor : CopyPastePreProcessor.EP_NAME.getExtensionList()) {
      newText = preProcessor.preprocessOnPaste(project, file, editor, newText, rawText);
    }

    if (caretStateToRestore != null) {
      caretModel.setCaretsAndSelections(caretStateToRestore);
    }

    final boolean pastedTextWasChanged = !text.equals(newText);
    int indentOptions = pastedTextWasChanged ? CodeInsightSettings.REFORMAT_BLOCK : settings.REFORMAT_ON_PASTE;
    text = newText;

    if (LanguageFormatting.INSTANCE.forContext(file) == null && indentOptions != CodeInsightSettings.NO_REFORMAT) {
      indentOptions = CodeInsightSettings.INDENT_BLOCK;
    }

    final String _text = text;
    final TextRange pastedRange = ApplicationManager.getApplication().runWriteAction((Computable<TextRange>)() -> {
      if (!project.isDisposed()) {
        ((UndoManagerImpl)UndoManager.getInstance(project)).addDocumentAsAffected(editor.getDocument());
      }
      return isInsertingEntireLineAboveCaret ? EditorCopyPasteHelperImpl.insertEntireLineAboveCaret(editor, _text)
                                             : EditorCopyPasteHelperImpl.insertStringAtCaret(editor, _text,
                                                                                             pasteMode == TRIM_IF_MIDDLE_LINE);
    });
    final RangeMarker bounds = document.createRangeMarker(pastedRange);

    // `skipIndentation` is additionally used as marker for changed pasted test
    // Any value, except `null` is a signal that the text was transformed.
    // For the `CopyPasteFoldingProcessor` it means that folding data is not valid and cannot be applied.
    final Ref<Boolean> skipIndentation = new Ref<>(pastedTextWasChanged ? Boolean.FALSE : null);
    for (ProcessorAndData<?> data : extraData) {
      data.process(project, editor, bounds, caretOffset, skipIndentation);
    }

    boolean pastedTextContainsWhiteSpacesOnly =
      CharArrayUtil.shiftForward(document.getCharsSequence(), bounds.getStartOffset(), " \n\t") >= bounds.getEndOffset();

    VirtualFile virtualFile = file.getVirtualFile();
    if (!pastedTextContainsWhiteSpacesOnly &&
        (virtualFile == null || !SingleRootFileViewProvider.isTooLargeForIntelligence(virtualFile))) {
      final int howtoReformat =
        skipIndentation.get() == Boolean.TRUE
        && (indentOptions == CodeInsightSettings.INDENT_BLOCK || indentOptions == CodeInsightSettings.INDENT_EACH_LINE)
        ? CodeInsightSettings.NO_REFORMAT
        : indentOptions;
      ApplicationManager.getApplication().runWriteAction(
        () -> typingActionsExtension
          .format(project, editor, howtoReformat, bounds.getStartOffset(), bounds.getEndOffset(), blockIndentAnchorColumn, true, true)
      );
    }

    if (bounds.isValid()) {
      if (!isInsertingEntireLineAboveCaret) {
        caretModel.moveToOffset(bounds.getEndOffset());
        editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
      }
      editor.putUserData(EditorEx.LAST_PASTED_REGION, bounds.getTextRange());
    }
    // Don't dispose the 'bounds' RangeMarker because the processors
    // from 'extraData' may use it later, for instance, in an invokeLater() block.
  }
private static void doPasteAction(final Editor editor,
                                    final Project project,
                                    final PsiFile file,
                                    final Document document,
                                    @NotNull final Transferable content,
                                    @NotNull final TypingActionsExtension typingActionsExtension)