void (TextRange range, String commentPrefix, String commentSuffix, Commenter commenter) { if (commenter instanceof SelfManagingCommenter selfManagingCommenter) { selfManagingCommenter.uncommentBlockComment( range.getStartOffset(), range.getEndOffset(), myDocument, mySelfManagedCommenterData ); return; } String text = myDocument.getCharsSequence().subSequence(range.getStartOffset(), range.getEndOffset()).toString(); int startOffset = range.getStartOffset(); //boolean endsProperly = CharArrayUtil.regionMatches(chars, range.getEndOffset() - commentSuffix.length(), commentSuffix); List<Couple<TextRange>> ranges = new ArrayList<>(); if (commenter instanceof CustomUncommenter customUncommenter) { /* In case of custom uncommenter, we need to ask it for list of [commentOpen-start,commentOpen-end], [commentClose-start,commentClose-end] and shift if according to current offset */ for (Couple<TextRange> coupleFromCommenter : customUncommenter.getCommentRangesToDelete(text)) { TextRange openComment = coupleFromCommenter.first.shiftRight(startOffset); TextRange closeComment = coupleFromCommenter.second.shiftRight(startOffset); ranges.add(Couple.of(openComment, closeComment)); } } else { // If commenter is not custom, we need to get this list by our selves int position = 0; while (true) { int start = getNearest(text, commentPrefix, position); if (start == text.length()) { break; } position = start; int end = getNearest(text, commentSuffix, position + commentPrefix.length()) + commentSuffix.length(); position = end; Couple<TextRange> pair = findCommentBlock(new TextRange(start + startOffset, end + startOffset), commentPrefix, commentSuffix); ranges.add(pair); } } RangeMarker marker = myDocument.createRangeMarker(range); try { for (int i = ranges.size() - 1; i >= 0; i--) { Couple<TextRange> toDelete = ranges.get(i); myDocument.deleteString(toDelete.first.getStartOffset(), toDelete.first.getEndOffset()); int shift = toDelete.first.getEndOffset() - toDelete.first.getStartOffset(); myDocument.deleteString(toDelete.second.getStartOffset() - shift, toDelete.second.getEndOffset() - shift); if (commenter.getCommentedBlockCommentPrefix() != null) { commentNestedComments(myDocument, new TextRange(toDelete.first.getEndOffset() - shift, toDelete.second.getStartOffset() - shift), commenter); } } processDocument(myDocument, marker, commenter, false); } finally { marker.dispose(); } }