@Override
  public void processTransferableData(final @NotNull Project project,
                                      final @NotNull Editor editor,
                                      final @NotNull RangeMarker bounds,
                                      final int caretOffset,
                                      final @NotNull Ref<? super Boolean> indented,
                                      final @NotNull List<? extends IndentTransferableData> values) {
    if (!CodeInsightSettings.getInstance().INDENT_TO_CARET_ON_PASTE) {
      return;
    }
    assert values.size() == 1;
    if (values.get(0).getOffset() == caretOffset) return;

    final Document document = editor.getDocument();
    final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
    if (psiFile == null || !acceptFileType(psiFile.getFileType())) {
      return;
    }
    //System.out.println("--- before indent ---\n" + document.getText());
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        final boolean useTabs =
          CodeStyle.getSettings(psiFile).useTabCharacter(psiFile.getFileType());
        CharFilter NOT_INDENT_FILTER = ch -> useTabs ? ch != '\t' : ch != ' ';
        String pastedText = document.getText(bounds.getTextRange());

        int startLine = document.getLineNumber(bounds.getStartOffset());
        int endLine = document.getLineNumber(bounds.getEndOffset());

        //calculate from indent
        int fromIndent = StringUtil.findFirst(pastedText, NOT_INDENT_FILTER);
        if (fromIndent < 0) fromIndent = 0;

        //calculate to indent
        String initialText = document.getText(TextRange.create(0, bounds.getStartOffset())) +
                   document.getText(TextRange.create(bounds.getEndOffset(), document.getTextLength()));
        int toIndent = 0;
        if (initialText.length() > 0) {
          final DocumentImpl initialDocument = new DocumentImpl(initialText);
          int lineNumber = initialDocument.getTextLength() > caretOffset? initialDocument.getLineNumber(caretOffset)
                                                                        : initialDocument.getLineCount() - 1;
          final int offset = getLineStartSafeOffset(initialDocument, lineNumber);

          if (bounds.getStartOffset() == offset) {
            String toString = initialDocument.getText(TextRange.create(offset, initialDocument.getLineEndOffset(lineNumber)));
            toIndent = StringUtil.findFirst(toString, NOT_INDENT_FILTER);
            if (toIndent < 0 && StringUtil.isEmptyOrSpaces(toString)) {
              toIndent = toString.length();
            }
            else if ((toIndent < 0 || toString.startsWith("\n")) && initialText.length() >= caretOffset) {
              toIndent = caretOffset - offset;
            }
          }
          else if (isNotApplicable(initialDocument, offset))
            return;
          else {                       // selection
            startLine += 1;
            toIndent = Math.abs(bounds.getStartOffset() - offset);
          }
        }

        // actual difference in indentation level
        int indent = toIndent - fromIndent;
        if (useTabs)       // indent is counted in tab units
          indent *=
            CodeStyle.getSettings(psiFile).getTabSize(psiFile.getFileType());
        // don't indent single-line text
        if (!StringUtil.startsWithWhitespace(pastedText) && !StringUtil.endsWithLineBreak(pastedText) &&
             !(StringUtil.splitByLines(pastedText).length > 1))
          return;

        if (pastedText.endsWith("\n")) endLine -= 1;

        for (int i = startLine; i <= endLine; i++) {
          EditorActionUtil.indentLine(project, editor, i, indent);
        }
        indented.set(Boolean.TRUE);
      }

      private boolean isNotApplicable(DocumentImpl initialDocument, int offset) {
        return caretOffset < initialDocument.getTextLength() && !StringUtil
          .isEmptyOrSpaces(initialDocument.getText(TextRange.create(offset, caretOffset)));
      }
    });
    //System.out.println("--- after indent ---\n" + document.getText());
  }
@Override
  public void processTransferableData(final @NotNull Project project,
                                      final @NotNull Editor editor,
                                      final @NotNull RangeMarker bounds,
                                      final int caretOffset,
                                      final @NotNull Ref<? super Boolean> indented,
                                      final @NotNull List<? extends IndentTransferableData> values)