private static boolean doUncommentLine(int line,
                                         Document document,
                                         Commenter commenter,
                                         int startOffset,
                                         int endOffset,
                                         boolean removeLineSpace,
                                         boolean removeBlockSpace) {
    String prefix = commenter.getLineCommentPrefix();
    if (prefix != null) {
      int originalPrefixLength = prefix.length();
      if (removeLineSpace) prefix += ' ';
      CharSequence chars = document.getCharsSequence();

      if (commenter instanceof CommenterWithLineSuffix commenterWithLineSuffix) {
        String suffix = commenterWithLineSuffix.getLineCommentSuffix();


        int theEnd = endOffset > 0 ? endOffset : document.getLineEndOffset(line);
        while (theEnd > startOffset && Character.isWhitespace(chars.charAt(theEnd - 1))) {
          theEnd--;
        }

        int suffixPos = CharArrayUtil.indexOf(chars, suffix, startOffset + originalPrefixLength, theEnd);
        if (suffixPos != -1) {
          document.deleteString(suffixPos, suffixPos + suffix.length());
        }
      }

      boolean matchesTrimmed = false;
      boolean commented = CharArrayUtil.regionMatches(chars, startOffset, prefix) ||
                          (matchesTrimmed = prefix.endsWith(" ") && CharArrayUtil.regionMatches(chars, startOffset, prefix.trim()));
      assert commented : "Commenter: " + commenter;

      int charsToDelete = matchesTrimmed ? prefix.trim().length() : prefix.length();
      document.deleteString(startOffset, startOffset + charsToDelete);

      // delete whitespace on line if that's all that left after uncommenting
      int lineStartOffset = document.getLineStartOffset(line);
      int lineEndOffset = document.getLineEndOffset(line);
      if (CharArrayUtil.isEmptyOrSpaces(chars, lineStartOffset, lineEndOffset)) document.deleteString(lineStartOffset, lineEndOffset);

      return true;
    }
    String text = document.getCharsSequence().subSequence(startOffset, endOffset).toString();

    prefix = commenter.getBlockCommentPrefix();
    final String suffix = commenter.getBlockCommentSuffix();
    if (prefix == null || suffix == null) {
      return true;
    }

    IntList prefixes = new IntArrayList();
    IntList suffixes = new IntArrayList();
    for (int position = 0; position < text.length(); ) {
      int prefixPos = text.indexOf(prefix, position);
      if (prefixPos == -1) {
        break;
      }
      prefixes.add(prefixPos);
      position = prefixPos + prefix.length();
      int suffixPos = text.indexOf(suffix, position);
      if (suffixPos == -1) {
        suffixPos = text.length() - suffix.length();
      }
      suffixes.add(suffixPos);
      position = suffixPos + suffix.length();
    }

    assert prefixes.size() == suffixes.size();

    for (int i = prefixes.size() - 1; i >= 0; i--) {
      uncommentRange(
        document,
        startOffset + prefixes.getInt(i),
        Math.min(startOffset + suffixes.getInt(i) + suffix.length(), endOffset),
        commenter,
        removeBlockSpace);
    }
    return false;
  }
private static boolean doUncommentLine(int line,
                                         Document document,
                                         Commenter commenter,
                                         int startOffset,
                                         int endOffset,
                                         boolean removeLineSpace,
                                         boolean removeBlockSpace)