IDEA-70194 Javadoc: Provide support for completing javadoc parameters description

This commit is contained in:
Denis Zhdanov
2011-05-31 14:31:08 +04:00
parent 095e4340d6
commit 62df932d36
9 changed files with 171 additions and 33 deletions
@@ -90,6 +90,8 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
private static final Key<Long> SMART_ENTER_TIMESTAMP = Key.create("smartEnterOriginalTimestamp");
public static class TooManyAttemptsException extends Exception {}
private final JavadocFixer myJavadocFixer = new JavadocFixer();
public boolean process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) {
final Document document = editor.getDocument();
@@ -121,6 +123,9 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor {
PsiElement atCaret = getStatementAtCaret(editor, file);
if (atCaret == null) {
if (myJavadocFixer.process(editor, file)) {
return;
}
if (!new CommentBreakerEnterProcessor().doEnter(editor, file, false)) {
plainEnter(editor);
}
@@ -0,0 +1,73 @@
package com.intellij.codeInsight.editorActions.smartEnter;
import com.intellij.javadoc.JavadocHelper;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
/**
* Serves as a facade for javadoc smart completion.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 5/31/11 1:22 PM
*/
public class JavadocFixer {
private final JavadocHelper myHelper = new JavadocHelper();
/**
* Checks if caret of the given editor is located inside javadoc and tries to perform smart completion there in case of the positive
* answer.
*
* @param editor target editor
* @param psiFile PSI file for the document exposed via the given editor
* @return <code>true</code> if smart completion was performed; <code>false</code> otherwise
*/
public boolean process(@NotNull Editor editor, @NotNull PsiFile psiFile) {
// Check parameter description completion.
final CaretModel caretModel = editor.getCaretModel();
final Pair<JavadocHelper.JavadocParameterInfo,List<JavadocHelper.JavadocParameterInfo>> pair =
myHelper.parse(psiFile, editor, caretModel.getOffset());
if (pair.first == null) {
return false;
}
final JavadocHelper.JavadocParameterInfo next = findNext(pair.second, pair.first);
if (next == null) {
return false;
}
if (next.parameterDescriptionStartPosition != null) {
myHelper.navigate(next.parameterDescriptionStartPosition, editor, psiFile.getProject());
}
else {
final LogicalPosition position = myHelper.calculateDescriptionStartPosition(psiFile, pair.second, next);
myHelper.navigate(position, editor, psiFile.getProject());
}
return true;
}
@Nullable
private static JavadocHelper.JavadocParameterInfo findNext(@NotNull Collection<JavadocHelper.JavadocParameterInfo> data,
@NotNull JavadocHelper.JavadocParameterInfo anchor)
{
boolean returnNow = false;
for (JavadocHelper.JavadocParameterInfo info : data) {
if (returnNow) {
return info;
}
returnNow = info == anchor;
}
return null;
}
}
@@ -22,6 +22,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.javadoc.PsiDocToken;
@@ -31,6 +33,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -77,6 +80,44 @@ public class JavadocHelper {
}
caretModel.moveToLogicalPosition(position);
}
/**
* Calculates desired position of target javadoc parameter's description start.
*
* @param psiFile PSI holder
* @param data parsed adjacent javadoc parameters
* @param anchor descriptor for the target parameter
* @return logical position that points to the desired parameter description start location
*/
@SuppressWarnings("MethodMayBeStatic")
@NotNull
public LogicalPosition calculateDescriptionStartPosition(@NotNull PsiFile psiFile,
@NotNull Collection<JavadocParameterInfo> data,
@NotNull JavadocHelper.JavadocParameterInfo anchor)
{
int descriptionStartColumn = -1;
int parameterNameEndColumn = -1;
for (JavadocHelper.JavadocParameterInfo parameterInfo : data) {
parameterNameEndColumn = Math.max(parameterNameEndColumn, parameterInfo.parameterNameEndPosition.column);
if (parameterInfo.parameterDescriptionStartPosition != null) {
descriptionStartColumn = Math.max(descriptionStartColumn, parameterInfo.parameterDescriptionStartPosition.column);
}
}
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(psiFile.getProject()).getCurrentSettings();
final int indentSize = codeStyleSettings.getIndentSize(psiFile.getFileType());
int column;
if (codeStyleSettings.JD_ALIGN_PARAM_COMMENTS) {
column = Math.max(descriptionStartColumn, parameterNameEndColumn);
if (column <= parameterNameEndColumn) {
column = parameterNameEndColumn + indentSize;
}
}
else {
column = anchor.parameterNameEndPosition.column + indentSize;
}
return new LogicalPosition(anchor.parameterNameEndPosition.line, column);
}
/**
* Returns information about all lines that contain javadoc parameters and are adjacent to the one that holds given offset.
@@ -24,8 +24,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -39,7 +37,7 @@ import java.util.List;
*/
public class JavadocNavigationDelegate extends EditorNavigationDelegateAdapter {
private final JavadocHelper myHelper = JavadocHelper.getInstance();
private static final JavadocHelper ourHelper = JavadocHelper.getInstance();
/**
* Improves navigation in case of incomplete javadoc parameter descriptions.
@@ -94,11 +92,16 @@ public class JavadocNavigationDelegate extends EditorNavigationDelegateAdapter {
}
if (psiFile == null) {
return Result.CONTINUE;
}
}
return navigateToLineEnd(editor, project, psiFile);
}
public static Result navigateToLineEnd(@NotNull Editor editor, @NotNull Project project, @NotNull PsiFile psiFile) {
final Document document = editor.getDocument();
final CaretModel caretModel = editor.getCaretModel();
final int offset = caretModel.getOffset();
final CharSequence text = document.getCharsSequence();
int line = caretModel.getLogicalPosition().line;
final int endLineOffset = document.getLineEndOffset(line);
@@ -110,37 +113,13 @@ public class JavadocNavigationDelegate extends EditorNavigationDelegateAdapter {
return Result.CONTINUE;
}
final Pair<JavadocHelper.JavadocParameterInfo,List<JavadocHelper.JavadocParameterInfo>> pair = myHelper.parse(psiFile, editor, offset);
if (pair.first == null) {
return Result.CONTINUE;
}
int descriptionStartColumn = -1;
int parameterNameEndColumn = -1;
for (JavadocHelper.JavadocParameterInfo parameterInfo : pair.second) {
parameterNameEndColumn = Math.max(parameterNameEndColumn, parameterInfo.parameterNameEndPosition.column);
if (parameterInfo.parameterDescriptionStartPosition != null) {
descriptionStartColumn = Math.max(descriptionStartColumn, parameterInfo.parameterDescriptionStartPosition.column);
}
}
if (pair.first.parameterDescriptionStartPosition != null) {
final Pair<JavadocHelper.JavadocParameterInfo,List<JavadocHelper.JavadocParameterInfo>> pair = ourHelper.parse(psiFile, editor, offset);
if (pair.first == null || pair.first.parameterDescriptionStartPosition != null) {
return Result.CONTINUE;
}
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
final int indentSize = codeStyleSettings.getIndentSize(psiFile.getFileType());
int column;
if (codeStyleSettings.JD_ALIGN_PARAM_COMMENTS) {
column = Math.max(descriptionStartColumn, parameterNameEndColumn);
if (column <= parameterNameEndColumn) {
column = parameterNameEndColumn + indentSize;
}
}
else {
column = pair.first.parameterNameEndPosition.column + indentSize;
}
myHelper.navigate(new LogicalPosition(line, column), editor, psiFile.getProject());
final LogicalPosition position = ourHelper.calculateDescriptionStartPosition(psiFile, pair.second, pair.first);
ourHelper.navigate(position, editor, psiFile.getProject());
return Result.STOP;
}
}
@@ -0,0 +1,9 @@
class Foo {
/**
* @param argument first arg description<caret>
* @param i
*/
void foo(int argument, int i) {
}
}
@@ -0,0 +1,9 @@
class Foo {
/**
* @param argument first arg description
* @param i <caret>
*/
void foo(int argument, int i) {
}
}
@@ -0,0 +1,9 @@
class Foo {
/**
* @param argument first arg <caret>description
* @param i
*/
void foo(int argument, int i) {
}
}
@@ -0,0 +1,9 @@
class Foo {
/**
* @param argument first arg description
* @param i <caret>
*/
void foo(int argument, int i) {
}
}
@@ -220,6 +220,10 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testLeaveValidCodeBlockWithEmptyLineAfterIt() throws Exception { doTest(); }
public void testFromJavadocParameterDescriptionEndToNextParameter() throws Exception { doTest(); }
public void testFromJavadocParameterDescriptionMiddleToNextParameter() throws Exception { doTest(); }
private void doTestBracesNextLineStyle() throws Exception {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;