private static boolean doCommentLine(Block block,
                                       int line,
                                       int offset,
                                       int endOffset,
                                       Commenter commenter,
                                       Document document) {
    String prefix = commenter.getLineCommentPrefix();
    int shiftedStartOffset = CharArrayUtil.shiftForward(document.getCharsSequence(), offset, " \t");
    if (prefix != null) {
      if (commenter instanceof CommenterWithLineSuffix) {
        endOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), endOffset, " \t");
        String lineSuffix = ((CommenterWithLineSuffix)commenter).getLineCommentSuffix();
        if (!CharArrayUtil.regionMatches(document.getCharsSequence(), shiftedStartOffset, prefix)) {
          if (!CharArrayUtil.regionMatches(document.getCharsSequence(), endOffset - lineSuffix.length(), lineSuffix)) {
            document.insertString(endOffset, lineSuffix);
          }
          document.insertString(offset, prefix);
        }
      }
      else {
        if (block.addLineSpace &&
            shiftedStartOffset < document.getTextLength() &&
            (block.caretUpdate == CaretUpdate.PUT_AT_COMMENT_START || document.getCharsSequence().charAt(shiftedStartOffset) != '\n')) {
          prefix += ' ';
        }
        InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(block.psiFile.getProject());
        if (!injectedLanguageManager.isInjectedFragment(block.psiFile) ||
            !injectedLanguageManager.intersectWithAllEditableFragments(block.psiFile, new TextRange(offset, offset)).isEmpty()) {
          document.insertString(offset, prefix);
        }
      }
    }
    else {
      prefix = commenter.getBlockCommentPrefix();
      String suffix = commenter.getBlockCommentSuffix();
      String newPrefix = block.addBlockSpace ? prefix + " " : prefix;
      String newSuffix = block.addBlockSpace ? " " + suffix : suffix;
      if (prefix == null || suffix == null) return true;
      if (endOffset == offset && block.startLine != block.endLine) return true;
      final int textLength = document.getTextLength();
      final CharSequence chars = document.getCharsSequence();
      if (endOffset == textLength) {
        final int shifted = CharArrayUtil.shiftBackward(chars, textLength - 1, " \t") + 1;
        if (shifted < textLength) endOffset = shifted;
      }
      else {
        endOffset = CharArrayUtil.shiftBackward(chars, endOffset, " \t");
      }
      if (endOffset < offset ||
          offset == textLength - 1 && line != document.getLineCount() - 1) {
        return true;
      }
      final String text = chars.subSequence(offset, endOffset).toString();
      final IntList prefixes = new IntArrayList();
      final IntList suffixes = new IntArrayList();
      final String commentedSuffix = commenter.getCommentedBlockCommentSuffix();
      final String commentedPrefix = commenter.getCommentedBlockCommentPrefix();
      for (int position = 0; position < text.length(); ) {
        int nearestPrefix = text.indexOf(prefix, position);
        if (nearestPrefix == -1) {
          nearestPrefix = text.length();
        }
        int nearestSuffix = text.indexOf(suffix, position);
        if (nearestSuffix == -1) {
          nearestSuffix = text.length();
        }
        if (Math.min(nearestPrefix, nearestSuffix) == text.length()) {
          break;
        }
        if (nearestPrefix < nearestSuffix) {
          prefixes.add(nearestPrefix);
          position = nearestPrefix + prefix.length();
        }
        else {
          suffixes.add(nearestSuffix);
          position = nearestSuffix + suffix.length();
        }
      }
      if (!(commentedSuffix == null && !suffixes.isEmpty() && offset + suffixes.getInt(suffixes.size() - 1) + suffix.length() >= endOffset)) {
        document.insertString(endOffset, newSuffix);
      }
      int nearestPrefix = prefixes.size() - 1;
      int nearestSuffix = suffixes.size() - 1;
      while (nearestPrefix >= 0 || nearestSuffix >= 0) {
        if (nearestSuffix == -1 || nearestPrefix != -1 && prefixes.getInt(nearestPrefix) > suffixes.getInt(nearestSuffix)) {
          final int position = prefixes.getInt(nearestPrefix);
          nearestPrefix--;
          if (commentedPrefix != null) {
            document.replaceString(offset + position, offset + position + prefix.length(), commentedPrefix);
          }
          else if (position != 0) {
            document.insertString(offset + position, newSuffix);
          }
        }
        else {
          final int position = suffixes.getInt(nearestSuffix);
          nearestSuffix--;
          if (commentedSuffix != null) {
            document.replaceString(offset + position, offset + position + suffix.length(), commentedSuffix);
          }
          else if (offset + position + suffix.length() < endOffset) {
            document.insertString(offset + position + suffix.length(), newPrefix);
          }
        }
      }
      if (!(commentedPrefix == null && !prefixes.isEmpty() && prefixes.getInt(0) == 0)) {
        document.insertString(offset, newPrefix);
      }
    }
    return false;
  }
private static boolean doCommentLine(Block block,
                                       int line,
                                       int offset,
                                       int endOffset,
                                       Commenter commenter,
                                       Document document)