private boolean insertDocAsterisk( int lineStart, boolean docAsterisk, boolean previousLineIndentUsed, CodeDocumentationAwareCommenter commenter) { PsiElement atLineStart = myFile.findElementAt(lineStart); if (atLineStart == null) return false; final String linePrefix = commenter.getDocumentationCommentLinePrefix(); final String docPrefix = commenter.getDocumentationCommentPrefix(); final String text = atLineStart.getText(); final TextRange textRange = atLineStart.getTextRange(); if (text.equals(linePrefix) || text.equals(docPrefix) || docPrefix != null && text.regionMatches( lineStart - textRange.getStartOffset(), docPrefix, 0, docPrefix.length()) || linePrefix != null && text.regionMatches( lineStart - textRange.getStartOffset(), linePrefix, 0, linePrefix.length())) { PsiElement element = myFile.findElementAt(myOffset); if (element == null) return false; PsiComment comment = element instanceof PsiComment ? (PsiComment) element : PsiTreeUtil.getParentOfType(element, PsiComment.class, false); if (comment != null) { int commentEnd = comment.getTextRange().getEndOffset(); if (myOffset >= commentEnd) { docAsterisk = false; } else { removeTrailingSpaces(myDocument, myOffset); String toInsert = previousLineIndentUsed ? "*" : CodeDocumentationUtil.createDocCommentLine("", getProject(), commenter); myDocument.insertString(myOffset, toInsert); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); } } else { docAsterisk = false; } } else if (linePrefix != null && atLineStart instanceof PsiComment && ((PsiComment) atLineStart).getTokenType() == commenter.getBlockCommentTokenType()) { // Check if C-Style comment already uses asterisks. boolean usesAstersk = false; int commentLine = myDocument.getLineNumber(textRange.getStartOffset()); if (commentLine < myDocument.getLineCount() - 1 && textRange.getEndOffset() >= myOffset) { int nextLineOffset = myDocument.getLineStartOffset(commentLine + 1); if (nextLineOffset < textRange.getEndOffset()) { final CharSequence chars = myDocument.getCharsSequence(); nextLineOffset = CharArrayUtil.shiftForward(chars, nextLineOffset, " \t"); usesAstersk = CharArrayUtil.regionMatches(chars, nextLineOffset, linePrefix); } } if (usesAstersk) { removeTrailingSpaces(myDocument, myOffset); myDocument.insertString(myOffset, linePrefix + " "); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); } docAsterisk = usesAstersk; } else { docAsterisk = false; } return docAsterisk; }
/** * Generates a comment if possible. * * <p>It's assumed that this method {@link PsiDocumentManager#commitDocument(Document) syncs} all * PSI-document changes during the processing. * * @param anchor target element for which a comment should be generated * @param editor target editor * @param commenter commenter to use * @param project current project */ private static void generateComment( @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(), commentStartOffset - 1, " \t"); 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; // if (CodeStyleSettingsManager.getSettings(project).JD_ADD_BLANK_AFTER_DESCRIPTION) { // buffer.setLength(0); // if (linePrefix != null) { // buffer.append(linePrefix); // } // buffer.append("\n"); // buffer.append(stub); // stub = buffer.toString(); // } document.insertString(insertionOffset, stub); docManager.commitDocument(document); pair = documentationProvider.parseContext(anchor); } if (caretOffsetToSet >= 0) { caretModel.moveToOffset(caretOffsetToSet); } if (pair == null || pair.second == null) { return; } int start = Math.min(calcStartReformatOffset(pair.first), calcStartReformatOffset(pair.second)); int end = pair.second.getTextRange().getEndOffset(); CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); codeStyleManager.reformatText(anchor.getContainingFile(), start, end); 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); } } }
private void generateJavadoc(CodeDocumentationAwareCommenter commenter) throws IncorrectOperationException { CodeInsightSettings settings = CodeInsightSettings.getInstance(); StringBuilder buffer = new StringBuilder(); final String docCommentLinePrefix = commenter.getDocumentationCommentLinePrefix(); if (docCommentLinePrefix == null) { return; } // There are at least two approaches for completing javadoc in case there is a text between // current caret position and line end: // 1. Move that tail text below the javadoc. Use-case: // Before: // /**<caret>public void foo() {} // After: // /** // */ // public void foo() {} // 2. Move the tail text inside the javadoc. Use-case: // Before: // /**This is <caret>javadoc description // After: // /** This is // * javadoc description // */ // The later is most relevant when we have 'auto wrap when typing reaches right margin' option // set, i.e. user starts javadoc // and types until right margin is reached. We want the wrapped text tail to be located inside // javadoc and continue typing // inside it. So, we have a control flow branch below that does the trick. buffer.append(docCommentLinePrefix); if (DataManager.getInstance() .loadFromDataContext( myDataContext, AutoHardWrapHandler.AUTO_WRAP_LINE_IN_PROGRESS_KEY) == Boolean.TRUE) { myDocument.insertString(myOffset, buffer); // We create new buffer here because the one referenced by current 'buffer' variable value // may be already referenced at another // place (e.g. 'undo' processing stuff). buffer = new StringBuilder(LINE_SEPARATOR).append(commenter.getDocumentationCommentSuffix()); int line = myDocument.getLineNumber(myOffset); myOffset = myDocument.getLineEndOffset(line); } else { buffer.append(LINE_SEPARATOR); buffer.append(commenter.getDocumentationCommentSuffix()); } PsiComment comment = createComment(buffer, settings); if (comment == null) { return; } myOffset = comment.getTextRange().getStartOffset(); CharSequence text = myDocument.getCharsSequence(); myOffset = CharArrayUtil.shiftForwardUntil(text, myOffset, LINE_SEPARATOR); myOffset = CharArrayUtil.shiftForward(text, myOffset, LINE_SEPARATOR); myOffset = CharArrayUtil.shiftForwardUntil(text, myOffset, docCommentLinePrefix) + 1; removeTrailingSpaces(myDocument, myOffset); if (!CodeStyleSettingsManager.getSettings(getProject()).JD_LEADING_ASTERISKS_ARE_ENABLED) { LOG.assertTrue( CharArrayUtil.regionMatches( myDocument.getCharsSequence(), myOffset - docCommentLinePrefix.length(), docCommentLinePrefix)); myDocument.deleteString(myOffset - docCommentLinePrefix.length(), myOffset); myOffset--; } else { myDocument.insertString(myOffset, " "); myOffset++; } PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); }