@Override
  public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file) {
    myEditor = editor;
    myCaret = caret;
    myFile = file;
    myWarning = null;
    myWarningLocation = null;

    myDocument = editor.getDocument();
    myLanguage = getLanguage(caret, file);

    final Commenter commenter = findCommenter(myFile, myEditor, caret);
    if (commenter == null) return;
    myCommenter = commenter;

    final String prefix;
    final String suffix;

    if (commenter instanceof SelfManagingCommenter selfManagingCommenter) {
      mySelfManagedCommenterData = selfManagingCommenter.createBlockCommentingState(
        caret.getSelectionStart(),
        caret.getSelectionEnd(),
        myDocument,
        myFile
      );
      if (mySelfManagedCommenterData == null) {
        mySelfManagedCommenterData = SelfManagingCommenter.EMPTY_STATE;
      }

      prefix = selfManagingCommenter.getBlockCommentPrefix(
        caret.getSelectionStart(),
        myDocument,
        mySelfManagedCommenterData
      );
      suffix = selfManagingCommenter.getBlockCommentSuffix(
        caret.getSelectionEnd(),
        myDocument,
        mySelfManagedCommenterData
      );
    }
    else {
      prefix = commenter.getBlockCommentPrefix();
      suffix = commenter.getBlockCommentSuffix();
    }

    if (prefix == null || suffix == null) return;

    TextRange commentedRange = findCommentedRange(commenter);
    if (commentedRange != null) {
      final int commentStart = commentedRange.getStartOffset();
      final int commentEnd = commentedRange.getEndOffset();
      int selectionStart = commentStart;
      int selectionEnd = commentEnd;
      if (myCaret.hasSelection()) {
        selectionStart = myCaret.getSelectionStart();
        selectionEnd = myCaret.getSelectionEnd();
      }
      if ((commentStart < selectionStart || commentStart >= selectionEnd) && (commentEnd <= selectionStart || commentEnd > selectionEnd)) {
        commentRange(selectionStart, selectionEnd, prefix, suffix, commenter);
      }
      else {
        uncommentRange(commentedRange, trim(prefix), trim(suffix), commenter);
      }
    }
    else {
      if (!myCaret.hasSelection()) {
        EditorUtil.fillVirtualSpaceUntilCaret(editor);
      }
      int selectionStart = myCaret.getSelectionStart();
      int selectionEnd = myCaret.getSelectionEnd();
      if (commenter.blockCommentRequiresFullLineSelection()) {
        selectionStart = myDocument.getLineStartOffset(myDocument.getLineNumber(selectionStart));
        selectionEnd = myDocument.getLineEndOffset(myDocument.getLineNumber(selectionEnd));
      }
      else if (commenter instanceof IndentedCommenter
               && ((IndentedCommenter)commenter).forceIndentedBlockComment() == Boolean.FALSE) {
        int lineStart = myDocument.getLineStartOffset(myDocument.getLineNumber(selectionStart));
        if (StringUtil.isEmptyOrSpaces(new CharSequenceSubSequence(myDocument.getCharsSequence(), lineStart, selectionStart))) {
          selectionStart = lineStart;
        }
      }
      if (selectionStart == selectionEnd) {
        CommonCodeStyleSettings settings = getLanguageSettings();
        int offset = settings.BLOCK_COMMENT_ADD_SPACE ? prefix.length() + 1 : prefix.length();
        String comment = settings.BLOCK_COMMENT_ADD_SPACE ? prefix + "  " + suffix : prefix + suffix;
        myDocument.insertString(selectionStart, comment);
        myCaret.moveToOffset(selectionStart + offset);
      }
      else {
        commentRange(selectionStart, selectionEnd, prefix, suffix, commenter);
      }
    }

    showMessageIfNeeded();
  }
@Override
  public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file)