mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-09 15:41:26 +07:00
[javadoc] Remove redundant abstract classes; make methods static, minor cleaup
GitOrigin-RevId: 3c5af00a75d01c9eba13bb148a33c6d0246e03c9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
76a9727974
commit
7f42c13987
+5
-9
@@ -69,12 +69,12 @@ public abstract class AbstractBasicJavaSmartEnterProcessor extends SmartEnterPro
|
||||
private static class TooManyAttemptsException extends Exception {
|
||||
}
|
||||
|
||||
private final AbstractBasicJavadocFixer myJavadocFixer;
|
||||
private final JavadocFixer myJavadocFixer;
|
||||
|
||||
protected AbstractBasicJavaSmartEnterProcessor(@NotNull List<Fixer> fixers,
|
||||
EnterProcessor @NotNull [] enterProcessors,
|
||||
EnterProcessor @NotNull [] afterCompletionEnterProcessors,
|
||||
@NotNull AbstractBasicJavadocFixer thinJavadocFixer,
|
||||
@NotNull JavadocFixer thinJavadocFixer,
|
||||
@NotNull EnterProcessor breakerEnterProcessor) {
|
||||
myBreakerEnterProcessor = breakerEnterProcessor;
|
||||
ourFixers = fixers;
|
||||
@@ -106,7 +106,7 @@ public abstract class AbstractBasicJavaSmartEnterProcessor extends SmartEnterPro
|
||||
document.replaceString(0, document.getTextLength(), textForRollback);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
editor.putUserData(SMART_ENTER_TIMESTAMP, null);
|
||||
@@ -206,12 +206,12 @@ public abstract class AbstractBasicJavaSmartEnterProcessor extends SmartEnterPro
|
||||
|
||||
if (myFirstErrorOffset != Integer.MAX_VALUE) {
|
||||
editor.getCaretModel().moveToOffset(myFirstErrorOffset);
|
||||
reformat(editor, atCaret);
|
||||
reformat(atCaret);
|
||||
return;
|
||||
}
|
||||
|
||||
final RangeMarker rangeMarker = createRangeMarker(atCaret);
|
||||
reformat(editor, atCaret);
|
||||
reformat(atCaret);
|
||||
commit(editor);
|
||||
|
||||
if (!mySkipEnter) {
|
||||
@@ -357,10 +357,6 @@ public abstract class AbstractBasicJavaSmartEnterProcessor extends SmartEnterPro
|
||||
editor.getCaretModel().moveToOffset(caretOffset - 1);
|
||||
}
|
||||
|
||||
protected void reformat(@NotNull Editor editor, @Nullable PsiElement elt) {
|
||||
reformat(elt);
|
||||
}
|
||||
|
||||
private void reformatBlockParentIfNeeded(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
commit(editor);
|
||||
ASTNode block =
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.editorActions.smartEnter;
|
||||
|
||||
import com.intellij.javadoc.AbstractBasicJavadocHelper;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
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.
|
||||
*/
|
||||
public abstract class AbstractBasicJavadocFixer {
|
||||
|
||||
private final AbstractBasicJavadocHelper myHelper;
|
||||
|
||||
public AbstractBasicJavadocFixer(@NotNull AbstractBasicJavadocHelper helper) { myHelper = helper; }
|
||||
|
||||
/**
|
||||
* 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} if smart completion was performed; {@code false} otherwise
|
||||
*/
|
||||
public boolean process(@NotNull Editor editor, @NotNull PsiFile psiFile) {
|
||||
// Check parameter description completion.
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
final Pair<AbstractBasicJavadocHelper.JavadocParameterInfo,List<AbstractBasicJavadocHelper.JavadocParameterInfo>> pair =
|
||||
myHelper.parse(psiFile, editor, caretModel.getOffset());
|
||||
|
||||
if (pair.first == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AbstractBasicJavadocHelper.JavadocParameterInfo next = findNext(pair.second, pair.first);
|
||||
if (next == null) {
|
||||
final int line = pair.first.lastLine + 1;
|
||||
final Document document = editor.getDocument();
|
||||
if (line < document.getLineCount()) {
|
||||
StringBuilder indent = new StringBuilder();
|
||||
boolean insertIndent = true;
|
||||
final CharSequence text = document.getCharsSequence();
|
||||
for (int i = document.getLineStartOffset(line), max = document.getLineEndOffset(line); i < max; i++) {
|
||||
final char c = text.charAt(i);
|
||||
if (c == ' ' || c == '\t') {
|
||||
indent.append(c);
|
||||
continue;
|
||||
}
|
||||
else if (c == '*') {
|
||||
indent.append("* ");
|
||||
if (i < max - 1 && text.charAt(i + 1) != '/') {
|
||||
insertIndent = false;
|
||||
}
|
||||
}
|
||||
indent.append("\n");
|
||||
break;
|
||||
}
|
||||
if (insertIndent) {
|
||||
document.insertString(document.getLineStartOffset(line), indent);
|
||||
}
|
||||
}
|
||||
moveCaretToTheLineEndIfPossible(editor, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static void moveCaretToTheLineEndIfPossible(@NotNull Editor editor, int line) {
|
||||
final Document document = editor.getDocument();
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
int offset;
|
||||
if (line >= document.getLineCount()) {
|
||||
offset = document.getTextLength();
|
||||
}
|
||||
else {
|
||||
offset = document.getLineEndOffset(line);
|
||||
}
|
||||
caretModel.moveToOffset(offset);
|
||||
}
|
||||
|
||||
private static @Nullable AbstractBasicJavadocHelper.JavadocParameterInfo findNext(@NotNull Collection<? extends AbstractBasicJavadocHelper.JavadocParameterInfo> data,
|
||||
@NotNull AbstractBasicJavadocHelper.JavadocParameterInfo anchor)
|
||||
{
|
||||
boolean returnNow = false;
|
||||
for (AbstractBasicJavadocHelper.JavadocParameterInfo info : data) {
|
||||
if (returnNow) {
|
||||
return info;
|
||||
}
|
||||
returnNow = info == anchor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+95
-3
@@ -1,15 +1,107 @@
|
||||
package com.intellij.codeInsight.editorActions.smartEnter;
|
||||
|
||||
import com.intellij.javadoc.JavadocHelper;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
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.
|
||||
*/
|
||||
public class JavadocFixer extends AbstractBasicJavadocFixer {
|
||||
public class JavadocFixer {
|
||||
|
||||
public JavadocFixer() {
|
||||
super( 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} if smart completion was performed; {@code false} 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 =
|
||||
JavadocHelper.parse(psiFile, editor, caretModel.getOffset());
|
||||
|
||||
if (pair.first == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final JavadocHelper.JavadocParameterInfo next = findNext(pair.second, pair.first);
|
||||
if (next == null) {
|
||||
final int line = pair.first.lastLine + 1;
|
||||
final Document document = editor.getDocument();
|
||||
if (line < document.getLineCount()) {
|
||||
StringBuilder indent = new StringBuilder();
|
||||
boolean insertIndent = true;
|
||||
final CharSequence text = document.getCharsSequence();
|
||||
for (int i = document.getLineStartOffset(line), max = document.getLineEndOffset(line); i < max; i++) {
|
||||
final char c = text.charAt(i);
|
||||
if (c == ' ' || c == '\t') {
|
||||
indent.append(c);
|
||||
continue;
|
||||
}
|
||||
else if (c == '*') {
|
||||
indent.append("* ");
|
||||
if (i < max - 1 && text.charAt(i + 1) != '/') {
|
||||
insertIndent = false;
|
||||
}
|
||||
}
|
||||
indent.append("\n");
|
||||
break;
|
||||
}
|
||||
if (insertIndent) {
|
||||
document.insertString(document.getLineStartOffset(line), indent);
|
||||
}
|
||||
}
|
||||
moveCaretToTheLineEndIfPossible(editor, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (next.parameterDescriptionStartPosition != null) {
|
||||
JavadocHelper.navigate(next.parameterDescriptionStartPosition, editor, psiFile.getProject());
|
||||
}
|
||||
else {
|
||||
final LogicalPosition position = JavadocHelper.calculateDescriptionStartPosition(psiFile, pair.second, next);
|
||||
JavadocHelper.navigate(position, editor, psiFile.getProject());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void moveCaretToTheLineEndIfPossible(@NotNull Editor editor, int line) {
|
||||
final Document document = editor.getDocument();
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
int offset;
|
||||
if (line >= document.getLineCount()) {
|
||||
offset = document.getTextLength();
|
||||
}
|
||||
else {
|
||||
offset = document.getLineEndOffset(line);
|
||||
}
|
||||
caretModel.moveToOffset(offset);
|
||||
}
|
||||
|
||||
private static @Nullable JavadocHelper.JavadocParameterInfo findNext(@NotNull Collection<? extends JavadocHelper.JavadocParameterInfo> data,
|
||||
@NotNull JavadocHelper.JavadocParameterInfo anchor)
|
||||
{
|
||||
boolean returnNow = false;
|
||||
for (JavadocHelper.JavadocParameterInfo info : data) {
|
||||
if (returnNow) {
|
||||
return info;
|
||||
}
|
||||
returnNow = info == anchor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class MissingLambdaBodyFixer implements Fixer {
|
||||
processor.insertBracesWithNewLine(editor, offset);
|
||||
editor.getCaretModel().moveToOffset(offset + 1);
|
||||
processor.commit(editor);
|
||||
processor.reformat(editor, psiElement);
|
||||
processor.reformat(psiElement);
|
||||
processor.setSkipEnter(BasicJavaAstTreeUtil.is(astNode, BASIC_LAMBDA_EXPRESSION));
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.javadoc;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
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.impl.source.BasicJavaAstTreeUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.ParentAwareTokenSet;
|
||||
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;
|
||||
|
||||
import static com.intellij.psi.impl.source.BasicJavaDocElementType.*;
|
||||
|
||||
public abstract class AbstractBasicJavadocHelper {
|
||||
private static final String PARAM_TEXT = "param";
|
||||
|
||||
public static final Pair<JavadocParameterInfo, List<JavadocParameterInfo>> EMPTY
|
||||
= new Pair<>(null, Collections.emptyList());
|
||||
private static final @NotNull ParentAwareTokenSet TAG_TOKEN_SET = ParentAwareTokenSet.create(BASIC_DOC_TAG,
|
||||
BASIC_DOC_SNIPPET_TAG,
|
||||
BASIC_DOC_INLINE_TAG);
|
||||
|
||||
protected AbstractBasicJavadocHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to navigate caret at the given editor to the target position inserting missing white spaces if necessary.
|
||||
*
|
||||
* @param position target caret position
|
||||
* @param editor target editor
|
||||
* @param project target project
|
||||
*/
|
||||
public void navigate(@NotNull LogicalPosition position, @NotNull Editor editor, final @NotNull Project project) {
|
||||
final Document document = editor.getDocument();
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
final int endLineOffset = document.getLineEndOffset(position.line);
|
||||
final LogicalPosition endLinePosition = editor.offsetToLogicalPosition(endLineOffset);
|
||||
if (endLinePosition.column < position.column && !editor.getSettings().isVirtualSpace() && !editor.isViewer()) {
|
||||
final String toInsert = StringUtil.repeat(" ", position.column - endLinePosition.column);
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
document.insertString(endLineOffset, toInsert);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
});
|
||||
}
|
||||
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
|
||||
*/
|
||||
public @NotNull LogicalPosition calculateDescriptionStartPosition(@NotNull PsiFile psiFile,
|
||||
@NotNull Collection<? extends JavadocParameterInfo> data,
|
||||
@NotNull JavadocParameterInfo anchor) {
|
||||
int descriptionStartColumn = -1;
|
||||
int parameterNameEndColumn = -1;
|
||||
for (JavadocParameterInfo parameterInfo : data) {
|
||||
parameterNameEndColumn = Math.max(parameterNameEndColumn, parameterInfo.parameterNameEndPosition.column);
|
||||
if (parameterInfo.parameterDescriptionStartPosition != null) {
|
||||
descriptionStartColumn = Math.max(descriptionStartColumn, parameterInfo.parameterDescriptionStartPosition.column);
|
||||
}
|
||||
}
|
||||
|
||||
int column;
|
||||
|
||||
if (getJdAlignParamComments(psiFile)) {
|
||||
column = Math.max(descriptionStartColumn, parameterNameEndColumn);
|
||||
if (column <= parameterNameEndColumn) {
|
||||
column = parameterNameEndColumn + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
column = anchor.parameterNameEndPosition.column + 1;
|
||||
}
|
||||
return new LogicalPosition(anchor.parameterNameEndPosition.line, column);
|
||||
}
|
||||
|
||||
protected abstract boolean getJdAlignParamComments(@NotNull PsiFile psiFile);
|
||||
|
||||
/**
|
||||
* Returns information about all lines that contain javadoc parameters and are adjacent to the one that holds given offset.
|
||||
*
|
||||
* @param psiFile PSI holder for the document exposed the given editor
|
||||
* @param editor target editor
|
||||
* @param offset target offset that identifies anchor line to check
|
||||
* @return pair like (javadoc info for the line identified by the given offset; list of javadoc parameter infos for
|
||||
* adjacent lines if any
|
||||
*/
|
||||
public @NotNull Pair<JavadocParameterInfo, List<JavadocParameterInfo>> parse(@NotNull PsiFile psiFile,
|
||||
@NotNull Editor editor,
|
||||
int offset) {
|
||||
List<JavadocParameterInfo> result = new ArrayList<>();
|
||||
PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(editor.getDocument());
|
||||
final PsiElement elementAtCaret = psiFile.findElementAt(offset);
|
||||
if (elementAtCaret == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
ASTNode nodeAtCaret = BasicJavaAstTreeUtil.toNode(elementAtCaret);
|
||||
ASTNode tag = BasicJavaAstTreeUtil.getParentOfType(nodeAtCaret, TAG_TOKEN_SET);
|
||||
if (tag == null) {
|
||||
// Due to javadoc PSI specifics.
|
||||
if (BasicJavaAstTreeUtil.isWhiteSpace(nodeAtCaret)) {
|
||||
for (ASTNode e = nodeAtCaret.getTreePrev(); e != null && tag == null; e = e.getTreePrev()) {
|
||||
tag = BasicJavaAstTreeUtil.getParentOfType(e, TAG_TOKEN_SET, false);
|
||||
if (e instanceof PsiWhiteSpace
|
||||
|| (e.getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
JavadocParameterInfo anchorInfo = parse(tag, editor);
|
||||
if (anchorInfo == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
// Parse previous parameters.
|
||||
for (ASTNode n = tag.getTreePrev(); n != null; n = n.getTreePrev()) {
|
||||
JavadocParameterInfo info = parse(n, editor);
|
||||
if (info == null) {
|
||||
break;
|
||||
}
|
||||
result.add(0, info);
|
||||
}
|
||||
|
||||
result.add(anchorInfo);
|
||||
|
||||
// Parse subsequent parameters.
|
||||
for (ASTNode n = tag.getTreeNext(); n != null; n = n.getTreeNext()) {
|
||||
JavadocParameterInfo info = parse(n, editor);
|
||||
if (info == null) {
|
||||
break;
|
||||
}
|
||||
result.add(info);
|
||||
}
|
||||
|
||||
return Pair.create(anchorInfo, result);
|
||||
}
|
||||
|
||||
private static @Nullable JavadocParameterInfo parse(@NotNull ASTNode astNode, @NotNull Editor editor) {
|
||||
final ASTNode tag = BasicJavaAstTreeUtil.getParentOfType(astNode, TAG_TOKEN_SET, false);
|
||||
if (tag == null || !PARAM_TEXT.equals(BasicJavaAstTreeUtil.getTagName(tag))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ASTNode paramRef = BasicJavaAstTreeUtil.findChildByType(tag, BASIC_DOC_TAG_VALUE_ELEMENT,
|
||||
BASIC_DOC_METHOD_OR_FIELD_REF,
|
||||
BASIC_DOC_PARAMETER_REF,
|
||||
BASIC_DOC_SNIPPET_TAG_VALUE);
|
||||
if (paramRef == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ASTNode node = paramRef.getTreeNext(); node != null; node = node.getTreeNext()) {
|
||||
final IElementType elementType = node.getElementType();
|
||||
if (elementType == JavaDocTokenType.DOC_COMMENT_DATA) {
|
||||
return new JavadocParameterInfo(
|
||||
editor.offsetToLogicalPosition(paramRef.getTextRange().getEndOffset()),
|
||||
editor.offsetToLogicalPosition(node.getTextRange().getStartOffset()),
|
||||
editor.getDocument().getLineNumber(node.getTextRange().getEndOffset())
|
||||
);
|
||||
}
|
||||
else if (elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new JavadocParameterInfo(
|
||||
editor.offsetToLogicalPosition(paramRef.getTextRange().getEndOffset()),
|
||||
null,
|
||||
editor.getDocument().getLineNumber(paramRef.getTextRange().getEndOffset())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates information about source code line that holds javadoc parameter.
|
||||
*/
|
||||
public static class JavadocParameterInfo {
|
||||
|
||||
/**
|
||||
* Logical position that points to location just after javadoc parameter name.
|
||||
* <p/>
|
||||
* Example:
|
||||
* <pre>
|
||||
* /**
|
||||
* * @param i[X] description
|
||||
* */
|
||||
* </pre>
|
||||
*/
|
||||
public final @NotNull LogicalPosition parameterNameEndPosition;
|
||||
public final @Nullable LogicalPosition parameterDescriptionStartPosition;
|
||||
/** Last logical line occupied by the current javadoc parameter. */
|
||||
public final int lastLine;
|
||||
|
||||
public JavadocParameterInfo(@NotNull LogicalPosition parameterNameEndPosition,
|
||||
@Nullable LogicalPosition parameterDescriptionStartPosition,
|
||||
int lastLine) {
|
||||
this.parameterNameEndPosition = parameterNameEndPosition;
|
||||
this.parameterDescriptionStartPosition = parameterDescriptionStartPosition;
|
||||
this.lastLine = lastLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "name end: " + parameterNameEndPosition + ", description start: " + parameterDescriptionStartPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,24 +16,236 @@
|
||||
package com.intellij.javadoc;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
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.JavaCodeStyleSettings;
|
||||
import com.intellij.psi.impl.source.BasicJavaAstTreeUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.ParentAwareTokenSet;
|
||||
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;
|
||||
|
||||
import static com.intellij.psi.impl.source.BasicJavaDocElementType.*;
|
||||
|
||||
/**
|
||||
* This class is not singleton but provides {@link #getInstance() single-point-of-usage field}.
|
||||
* Utility methods to support some Javadoc-related operations like formatting or navigation
|
||||
*/
|
||||
public final class JavadocHelper extends AbstractBasicJavadocHelper {
|
||||
private static final JavadocHelper INSTANCE = new JavadocHelper();
|
||||
public final class JavadocHelper {
|
||||
private static final Pair<JavadocParameterInfo, List<JavadocParameterInfo>> EMPTY
|
||||
= new Pair<>(null, Collections.emptyList());
|
||||
private static final String PARAM_TEXT = "param";
|
||||
private static final @NotNull ParentAwareTokenSet TAG_TOKEN_SET =
|
||||
ParentAwareTokenSet.create(BASIC_DOC_TAG, BASIC_DOC_SNIPPET_TAG, BASIC_DOC_INLINE_TAG);
|
||||
|
||||
@Override
|
||||
protected boolean getJdAlignParamComments(@NotNull PsiFile psiFile) {
|
||||
private JavadocHelper() {
|
||||
}
|
||||
|
||||
private static boolean getJdAlignParamComments(@NotNull PsiFile psiFile) {
|
||||
final CodeStyleSettings codeStyleSettings = CodeStyle.getSettings(psiFile);
|
||||
return (codeStyleSettings.getCustomSettings(JavaCodeStyleSettings.class).JD_ALIGN_PARAM_COMMENTS);
|
||||
}
|
||||
|
||||
public static @NotNull JavadocHelper getInstance() {
|
||||
return INSTANCE;
|
||||
/**
|
||||
* Tries to navigate caret at the given editor to the target position, inserting missing white spaces if necessary.
|
||||
*
|
||||
* @param position target caret position
|
||||
* @param editor target editor
|
||||
* @param project target project
|
||||
*/
|
||||
public static void navigate(@NotNull LogicalPosition position, @NotNull Editor editor, final @NotNull Project project) {
|
||||
final Document document = editor.getDocument();
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
final int endLineOffset = document.getLineEndOffset(position.line);
|
||||
final LogicalPosition endLinePosition = editor.offsetToLogicalPosition(endLineOffset);
|
||||
if (endLinePosition.column < position.column && !editor.getSettings().isVirtualSpace() && !editor.isViewer()) {
|
||||
final String toInsert = StringUtil.repeat(" ", position.column - endLinePosition.column);
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
document.insertString(endLineOffset, toInsert);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
});
|
||||
}
|
||||
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
|
||||
*/
|
||||
public static @NotNull LogicalPosition calculateDescriptionStartPosition(@NotNull PsiFile psiFile,
|
||||
@NotNull Collection<? extends JavadocParameterInfo> data,
|
||||
@NotNull JavadocParameterInfo anchor) {
|
||||
int descriptionStartColumn = -1;
|
||||
int parameterNameEndColumn = -1;
|
||||
for (JavadocParameterInfo parameterInfo : data) {
|
||||
parameterNameEndColumn = Math.max(parameterNameEndColumn, parameterInfo.parameterNameEndPosition.column);
|
||||
if (parameterInfo.parameterDescriptionStartPosition != null) {
|
||||
descriptionStartColumn = Math.max(descriptionStartColumn, parameterInfo.parameterDescriptionStartPosition.column);
|
||||
}
|
||||
}
|
||||
|
||||
int column;
|
||||
|
||||
if (getJdAlignParamComments(psiFile)) {
|
||||
column = Math.max(descriptionStartColumn, parameterNameEndColumn);
|
||||
if (column <= parameterNameEndColumn) {
|
||||
column = parameterNameEndColumn + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
column = anchor.parameterNameEndPosition.column + 1;
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @param psiFile PSI holder for the document exposed the given editor
|
||||
* @param editor target editor
|
||||
* @param offset target offset that identifies anchor line to check
|
||||
* @return pair like (javadoc info for the line identified by the given offset; list of javadoc parameter infos for
|
||||
* adjacent lines if any
|
||||
*/
|
||||
public static @NotNull Pair<JavadocParameterInfo, List<JavadocParameterInfo>> parse(@NotNull PsiFile psiFile,
|
||||
@NotNull Editor editor,
|
||||
int offset) {
|
||||
List<JavadocParameterInfo> result = new ArrayList<>();
|
||||
PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(editor.getDocument());
|
||||
final PsiElement elementAtCaret = psiFile.findElementAt(offset);
|
||||
if (elementAtCaret == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
ASTNode nodeAtCaret = BasicJavaAstTreeUtil.toNode(elementAtCaret);
|
||||
ASTNode tag = BasicJavaAstTreeUtil.getParentOfType(nodeAtCaret, TAG_TOKEN_SET);
|
||||
if (tag == null) {
|
||||
// Due to javadoc PSI specifics.
|
||||
if (BasicJavaAstTreeUtil.isWhiteSpace(nodeAtCaret)) {
|
||||
for (ASTNode e = nodeAtCaret.getTreePrev(); e != null && tag == null; e = e.getTreePrev()) {
|
||||
tag = BasicJavaAstTreeUtil.getParentOfType(e, TAG_TOKEN_SET, false);
|
||||
if (e instanceof PsiWhiteSpace
|
||||
|| (e.getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
JavadocParameterInfo anchorInfo = parse(tag, editor);
|
||||
if (anchorInfo == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
// Parse previous parameters.
|
||||
for (ASTNode n = tag.getTreePrev(); n != null; n = n.getTreePrev()) {
|
||||
JavadocParameterInfo info = parse(n, editor);
|
||||
if (info == null) {
|
||||
break;
|
||||
}
|
||||
result.add(0, info);
|
||||
}
|
||||
|
||||
result.add(anchorInfo);
|
||||
|
||||
// Parse subsequent parameters.
|
||||
for (ASTNode n = tag.getTreeNext(); n != null; n = n.getTreeNext()) {
|
||||
JavadocParameterInfo info = parse(n, editor);
|
||||
if (info == null) {
|
||||
break;
|
||||
}
|
||||
result.add(info);
|
||||
}
|
||||
|
||||
return Pair.create(anchorInfo, result);
|
||||
}
|
||||
|
||||
private static @Nullable JavadocParameterInfo parse(@NotNull ASTNode astNode, @NotNull Editor editor) {
|
||||
final ASTNode tag = BasicJavaAstTreeUtil.getParentOfType(astNode, TAG_TOKEN_SET, false);
|
||||
if (tag == null || !PARAM_TEXT.equals(BasicJavaAstTreeUtil.getTagName(tag))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ASTNode paramRef = BasicJavaAstTreeUtil.findChildByType(tag, BASIC_DOC_TAG_VALUE_ELEMENT,
|
||||
BASIC_DOC_METHOD_OR_FIELD_REF,
|
||||
BASIC_DOC_PARAMETER_REF,
|
||||
BASIC_DOC_SNIPPET_TAG_VALUE);
|
||||
if (paramRef == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ASTNode node = paramRef.getTreeNext(); node != null; node = node.getTreeNext()) {
|
||||
final IElementType elementType = node.getElementType();
|
||||
if (elementType == JavaDocTokenType.DOC_COMMENT_DATA) {
|
||||
return new JavadocParameterInfo(
|
||||
editor.offsetToLogicalPosition(paramRef.getTextRange().getEndOffset()),
|
||||
editor.offsetToLogicalPosition(node.getTextRange().getStartOffset()),
|
||||
editor.getDocument().getLineNumber(node.getTextRange().getEndOffset())
|
||||
);
|
||||
}
|
||||
else if (elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new JavadocParameterInfo(
|
||||
editor.offsetToLogicalPosition(paramRef.getTextRange().getEndOffset()),
|
||||
null,
|
||||
editor.getDocument().getLineNumber(paramRef.getTextRange().getEndOffset())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates information about source code line that holds javadoc parameter.
|
||||
*/
|
||||
public static class JavadocParameterInfo {
|
||||
|
||||
/**
|
||||
* Logical position that points to location just after javadoc parameter name.
|
||||
* <p/>
|
||||
* Example:
|
||||
* <pre>
|
||||
* /**
|
||||
* * @param i[X] description
|
||||
* */
|
||||
* </pre>
|
||||
*/
|
||||
public final @NotNull LogicalPosition parameterNameEndPosition;
|
||||
public final @Nullable LogicalPosition parameterDescriptionStartPosition;
|
||||
/** Last logical line occupied by the current javadoc parameter. */
|
||||
public final int lastLine;
|
||||
|
||||
public JavadocParameterInfo(@NotNull LogicalPosition parameterNameEndPosition,
|
||||
@Nullable LogicalPosition parameterDescriptionStartPosition,
|
||||
int lastLine) {
|
||||
this.parameterNameEndPosition = parameterNameEndPosition;
|
||||
this.parameterDescriptionStartPosition = parameterDescriptionStartPosition;
|
||||
this.lastLine = lastLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "name end: " + parameterNameEndPosition + ", description start: " + parameterDescriptionStartPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user