@Override
  @NotNull
  protected FutureTask<Boolean> prepareTask(
      @NotNull final PsiFile file, final boolean processChangedTextOnly)
      throws IncorrectOperationException {
    return new FutureTask<>(
        () -> {
          FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
          try {
            CharSequence before = null;
            Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
            if (getInfoCollector() != null) {
              LOG.assertTrue(document != null);
              before = document.getImmutableCharSequence();
            }

            CaretVisualPositionKeeper caretPositionKeeper = new CaretVisualPositionKeeper(document);

            if (processChangedTextOnly) {
              ChangedRangesInfo info =
                  FormatChangedTextUtil.getInstance().getChangedRangesInfo(file);
              if (info != null) {
                CodeStyleManager.getInstance(myProject).reformatTextWithContext(file, info);
              }
            } else {
              Collection<TextRange> ranges = getRangesToFormat(file);
              CodeStyleManager.getInstance(myProject).reformatText(file, ranges);
            }

            caretPositionKeeper.restoreOriginalLocation();

            if (before != null) {
              prepareUserNotificationMessage(document, before);
            }

            return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get();
          } catch (FilesTooBigForDiffException e) {
            handleFileTooBigException(LOG, e, file);
            return false;
          } catch (IncorrectOperationException e) {
            LOG.error(e);
            return false;
          } finally {
            myRanges.clear();
          }
        });
  }
  public void processText(
      PsiFile file, final FormatTextRanges ranges, boolean doPostponedFormatting) {
    final Project project = file.getProject();
    Document document = PsiDocumentManager.getInstance(project).getDocument(file);
    final List<FormatTextRanges.FormatTextRange> textRanges = ranges.getRanges();
    if (document instanceof DocumentWindow) {
      file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
      final DocumentWindow documentWindow = (DocumentWindow) document;
      for (FormatTextRanges.FormatTextRange range : textRanges) {
        range.setTextRange(documentWindow.injectedToHost(range.getTextRange()));
      }
      document = documentWindow.getDelegate();
    }

    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);

    if (builder != null) {
      if (file.getTextLength() > 0) {
        try {
          final PsiElement startElement =
              file.findElementAt(textRanges.get(0).getTextRange().getStartOffset());
          final PsiElement endElement =
              file.findElementAt(
                  textRanges.get(textRanges.size() - 1).getTextRange().getEndOffset() - 1);
          final PsiElement commonParent =
              startElement != null && endElement != null
                  ? PsiTreeUtil.findCommonParent(startElement, endElement)
                  : null;
          ASTNode node = null;
          if (commonParent != null) {
            node = commonParent.getNode();
          }
          if (node == null) {
            node = file.getNode();
          }
          for (FormatTextRanges.FormatTextRange range : ranges.getRanges()) {
            TextRange rangeToUse = preprocess(node, range.getTextRange());
            range.setTextRange(rangeToUse);
          }
          if (doPostponedFormatting) {
            RangeMarker[] markers = new RangeMarker[textRanges.size()];
            int i = 0;
            for (FormatTextRanges.FormatTextRange range : textRanges) {
              TextRange textRange = range.getTextRange();
              int start = textRange.getStartOffset();
              int end = textRange.getEndOffset();
              if (start >= 0 && end > start && end <= document.getTextLength()) {
                markers[i] = document.createRangeMarker(textRange);
                markers[i].setGreedyToLeft(true);
                markers[i].setGreedyToRight(true);
                i++;
              }
            }
            final PostprocessReformattingAspect component =
                file.getProject().getComponent(PostprocessReformattingAspect.class);
            FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
            component.doPostponedFormatting(file.getViewProvider());
            i = 0;
            for (FormatTextRanges.FormatTextRange range : textRanges) {
              RangeMarker marker = markers[i];
              if (marker != null) {
                range.setTextRange(TextRange.create(marker));
                marker.dispose();
              }
              i++;
            }
          }
          if (FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get()) {
            return;
          }

          final FormattingModel originalModel =
              CoreFormatterUtil.buildModel(builder, file, mySettings, FormattingMode.REFORMAT);
          final FormattingModel model =
              new DocumentBasedFormattingModel(
                  originalModel.getRootBlock(),
                  document,
                  project,
                  mySettings,
                  file.getFileType(),
                  file);

          FormatterEx formatter = FormatterEx.getInstanceEx();
          if (CodeStyleManager.getInstance(project).isSequentialProcessingAllowed()) {
            formatter.setProgressTask(new FormattingProgressTask(project, file, document));
          }

          CommonCodeStyleSettings.IndentOptions indentOptions = null;
          if (builder instanceof FormattingModelBuilderEx) {
            indentOptions =
                ((FormattingModelBuilderEx) builder)
                    .getIndentOptionsToUse(file, ranges, mySettings);
          }
          if (indentOptions == null) {
            indentOptions = mySettings.getIndentOptions(file.getFileType());
          }

          formatter.format(model, mySettings, indentOptions, ranges);
          for (FormatTextRanges.FormatTextRange range : textRanges) {
            TextRange textRange = range.getTextRange();
            wrapLongLinesIfNecessary(
                file, document, textRange.getStartOffset(), textRange.getEndOffset());
          }
        } catch (IncorrectOperationException e) {
          LOG.error(e);
        }
      }
    }
  }