void (@NotNull PsiElement anchor, @NotNull Editor editor, @NotNull CodeDocumentationProvider documentationProvider, @NotNull CodeDocumentationAwareCommenter commenter, @NotNull Project project) { Document document = editor.getDocument(); int commentStartOffset = anchor.getTextRange().getStartOffset(); int lineStartOffset = document.getLineStartOffset(document.getLineNumber(commentStartOffset)); if (lineStartOffset > 0 && lineStartOffset < commentStartOffset) { // Example: // void test1() { // } // void test2() { // <offset> // } // We want to insert the comment at the start of the line where 'test2()' is declared. int nonWhiteSpaceOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), lineStartOffset, commentStartOffset - 1, " \t") + 1; commentStartOffset = Math.max(nonWhiteSpaceOffset, lineStartOffset); } int commentBodyRelativeOffset = 0; int caretOffsetToSet = -1; StringBuilder buffer = new StringBuilder(); String commentPrefix = commenter.getDocumentationCommentPrefix(); if (commentPrefix != null) { buffer.append(commentPrefix).append("\n"); commentBodyRelativeOffset += commentPrefix.length() + 1; } String linePrefix = commenter.getDocumentationCommentLinePrefix(); if (linePrefix != null) { buffer.append(linePrefix); commentBodyRelativeOffset += linePrefix.length(); caretOffsetToSet = commentStartOffset + commentBodyRelativeOffset; } buffer.append("\n"); commentBodyRelativeOffset++; String commentSuffix = commenter.getDocumentationCommentSuffix(); if (commentSuffix != null) { buffer.append(commentSuffix).append("\n"); } if (buffer.length() <= 0) { return; } document.insertString(commentStartOffset, buffer); PsiDocumentManager docManager = PsiDocumentManager.getInstance(project); docManager.commitDocument(document); Pair<PsiElement, PsiComment> pair = documentationProvider.parseContext(anchor); if (pair == null || pair.second == null) { return; } String stub = documentationProvider.generateDocumentationContentStub(pair.second); CaretModel caretModel = editor.getCaretModel(); if (stub != null) { int insertionOffset = commentStartOffset + commentBodyRelativeOffset; document.insertString(insertionOffset, stub); docManager.commitDocument(document); pair = documentationProvider.parseContext(anchor); } if (caretOffsetToSet >= 0) { caretModel.moveToOffset(caretOffsetToSet); editor.getSelectionModel().removeSelection(); } if (pair == null || pair.second == null) { return; } int start = Math.min(calcStartReformatOffset(pair.first), calcStartReformatOffset(pair.second)); int end = pair.second.getTextRange().getEndOffset(); reformatCommentKeepingEmptyTags(anchor.getContainingFile(), project, start, end); editor.getCaretModel().moveToOffset(document.getLineEndOffset(document.getLineNumber(editor.getCaretModel().getOffset()))); int caretOffset = caretModel.getOffset(); if (caretOffset > 0 && caretOffset <= document.getTextLength()) { char c = document.getCharsSequence().charAt(caretOffset - 1); if (!StringUtil.isWhiteSpace(c)) { document.insertString(caretOffset, " "); caretModel.moveToOffset(caretOffset + 1); } } }