From f95cbb96776424e11b5e887ef0056944d25ca7b3 Mon Sep 17 00:00:00 2001 From: Mathias Boulay Date: Fri, 16 Aug 2024 17:56:28 +0200 Subject: [PATCH] fix(JavaDoc): better autocomplete GitOrigin-RevId: 64cc8794d732cd08566413b0070b371768e47d8f --- .../JavaDocCompletionContributor.java | 36 ++++++++++++++----- .../javadoc/JavaDocInfoGenerator.java | 2 +- .../javadoc/JavaDocMarkdownEnterHandler.java | 4 +-- .../MethodInMarkdownReferenceLink.java | 5 +++ .../MethodInMarkdownReferenceLink_after.java | 5 +++ .../enterhandler/afterEnterAtEdge.java | 2 +- .../javadocIG/markdownCodeBlock.html | 2 +- .../javadocIG/markdownGeneralFeatures.html | 2 +- .../javadocIG/markdownInheritDoc.html | 5 ++- .../javadocIG/markdownJepExample.html | 17 +++++++++ .../javadocIG/markdownJepExample.java | 34 ++++++++++++++++++ .../completion/JavadocCompletionTest.java | 5 +++ .../javadoc/JavaDocInfoGeneratorTest.java | 3 ++ 13 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink.java create mode 100644 java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink_after.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index 1cf6e4a8e416..22bec27fd915 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -604,6 +604,8 @@ public final class JavaDocCompletionContributor extends CompletionContributor im PsiElement element = context.getFile().findElementAt(signatureOffset - 1); final CodeStyleSettings styleSettings = CodeStyle.getSettings(context.getFile()); PsiDocTag tag = PsiTreeUtil.getParentOfType(element, PsiDocTag.class); + final PsiMarkdownReferenceLink link = tag == null ? PsiTreeUtil.getParentOfType(element, PsiMarkdownReferenceLink.class) : null; + if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR && tag != null) { PsiDocTagValue valueElement = tag.getValueElement(); int valueEnd = valueElement != null ? valueElement.getTextRange().getEndOffset() : -1; @@ -620,16 +622,19 @@ public final class JavaDocCompletionContributor extends CompletionContributor im String methodName = method.getName(); int beforeParenth = signatureOffset + methodName.length(); PsiParameter[] parameters = method.getParameterList().getParameters(); - String signature = "(" + - StringUtil.join(parameters, - p -> TypeConversionUtil.erasure(p.getType()).getCanonicalText(), - "," + (styleSettings.getCommonSettings(JavaLanguage.INSTANCE).SPACE_AFTER_COMMA ? " " : "")) + - ")"; + + String signatureSeparator = "," + (styleSettings.getCommonSettings(JavaLanguage.INSTANCE).SPACE_AFTER_COMMA ? " " : ""); + String signatureContent = link == null + ? StringUtil.join(parameters, + p -> TypeConversionUtil.erasure(p.getType()).getCanonicalText(), + signatureSeparator) + : StringUtil.join(parameters, + p -> escapeBrackets(TypeConversionUtil.erasure(p.getType()).getCanonicalText()), + signatureSeparator); + String signature = "(" + signatureContent + ")"; + String insertString = methodName + signature; - if (!(tag instanceof PsiInlineDocTag)) { - insertString += " "; - } - else { + if (tag instanceof PsiInlineDocTag) { if (chars.charAt(signatureOffset) == '}') { afterSharp++; } @@ -637,6 +642,14 @@ public final class JavaDocCompletionContributor extends CompletionContributor im insertString += "} "; } } + else if (link != null) { + if(chars.charAt(signatureOffset) == ']') { + afterSharp++; + } + } + else { + insertString += " "; + } document.insertString(signatureOffset, insertString); RangeMarker paramListMarker = document.createRangeMarker(TextRange.from(beforeParenth, signature.length())); @@ -651,6 +664,11 @@ public final class JavaDocCompletionContributor extends CompletionContributor im } } + /** @return Escaped brackets to conform with the JEP-467 */ + private static String escapeBrackets(String input) { + return input.replace("[", "\\[").replace("]", "\\]"); + } + private static void startParameterListTemplate(@NotNull InsertionContext context, Editor editor, Document document, diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 968096ccbb0f..fa7a896ee127 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -2353,7 +2353,7 @@ public class JavaDocInfoGenerator { } private static String markdownToHtml(String markdownInput) { - return ourMarkdownConverter.convertMarkdownToHtml(markdownInput, null); + return ourMarkdownConverter.convertMarkdownToHtml(markdownInput.stripIndent(), null); } protected boolean isLeadingAsterisks(@Nullable PsiElement element) { diff --git a/java/java-impl/src/com/intellij/javadoc/JavaDocMarkdownEnterHandler.java b/java/java-impl/src/com/intellij/javadoc/JavaDocMarkdownEnterHandler.java index 46b6b4ec21cc..5108fb488ad2 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavaDocMarkdownEnterHandler.java +++ b/java/java-impl/src/com/intellij/javadoc/JavaDocMarkdownEnterHandler.java @@ -37,8 +37,8 @@ public class JavaDocMarkdownEnterHandler extends EnterHandlerDelegateAdapter { } Document document = editor.getDocument(); - document.insertString(caretOffset.get(), "///"); - caretAdvance.set(3); + document.insertString(caretOffset.get(), "/// "); + caretAdvance.set(4); return Result.DefaultForceIndent; } diff --git a/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink.java b/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink.java new file mode 100644 index 000000000000..5a0c76f51acb --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink.java @@ -0,0 +1,5 @@ +/// Some text [Fubar#fo] + +class Fubar { + void foo(char[] data); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink_after.java b/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink_after.java new file mode 100644 index 000000000000..d1fa044567ed --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/javadoc/MethodInMarkdownReferenceLink_after.java @@ -0,0 +1,5 @@ +/// Some text [Fubar#foo(char\[\])] + +class Fubar { + void foo(char[] data); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadoc/markdown/enterhandler/afterEnterAtEdge.java b/java/java-tests/testData/codeInsight/javadoc/markdown/enterhandler/afterEnterAtEdge.java index 97ce3046b9ac..3bdda6bd92b3 100644 --- a/java/java-tests/testData/codeInsight/javadoc/markdown/enterhandler/afterEnterAtEdge.java +++ b/java/java-tests/testData/codeInsight/javadoc/markdown/enterhandler/afterEnterAtEdge.java @@ -4,5 +4,5 @@ /// - [a class][String] /// - [a field][String#CASE_INSENSITIVE_ORDER] /// - [a method][String#chars()] -/// +/// class C{} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/markdownCodeBlock.html b/java/java-tests/testData/codeInsight/javadocIG/markdownCodeBlock.html index ff9dbcd5e285..d8be26274b9f 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/markdownCodeBlock.html +++ b/java/java-tests/testData/codeInsight/javadocIG/markdownCodeBlock.html @@ -1,2 +1,2 @@ -
class MarkdownCodeBlock
new String();
System.out.println("Hello Markdown");
+
class MarkdownCodeBlock
new String();
System.out.println("Hello Markdown");

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/markdownGeneralFeatures.html b/java/java-tests/testData/codeInsight/javadocIG/markdownGeneralFeatures.html index d97d966ba96e..a61533a115fb 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/markdownGeneralFeatures.html +++ b/java/java-tests/testData/codeInsight/javadocIG/markdownGeneralFeatures.html @@ -1,2 +1,2 @@ -
class MarkdownFeatures

Title1

Title2

Title 3

italic strong code

Separate paragraph

System.out.println("Hello there");
+
class MarkdownFeatures

Title1

Title2

Title 3

italic strong code

Separate paragraph

System.out.println("Hello there");

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/markdownInheritDoc.html b/java/java-tests/testData/codeInsight/javadocIG/markdownInheritDoc.html index 3f5b6e07a594..a3785662c80c 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/markdownInheritDoc.html +++ b/java/java-tests/testData/codeInsight/javadocIG/markdownInheritDoc.html @@ -1,3 +1,2 @@ -
void foo()

Markdown variant -

I am legacy javadoc, I hope no one disturbs my _underlines_ and **astrerisks**

More markdown - syntax

Overrides:

foo in class MarkdownInheritDoc

\ No newline at end of file +
void foo()

Markdown variant

I am legacy javadoc, I hope no one disturbs my _underlines_ and **astrerisks**

More markdown +syntax

Overrides:

foo in class MarkdownInheritDoc

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.html b/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.html new file mode 100644 index 000000000000..78a64c09e449 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.html @@ -0,0 +1,17 @@ +
public String longExample()

Returns a hash code value for the object. This method is + supported for the benefit of hash tables such as those provided by + java.util.HashMap.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during + an execution of a Java application, the hashCode method + must consistently return the same integer, provided no information + used in equals comparisons on the object is modified. + This integer need not remain consistent from one execution of an + application to another execution of the same application.
  • If two objects are equal according to the + equals method, then calling the + hashCode method on each of the two objects must produce the + same integer result.
  • It is not required that if two objects are unequal + according to the equals method, then + calling the hashCode method on each of the two objects + must produce distinct integer results. However, the programmer + should be aware that producing distinct integer results for + unequal objects may improve the performance of hash tables.

Returns:

a hash code value for this object.

Implementation
Requirements:

As far as is reasonably practical, the hashCode method defined +by class Object returns distinct integers for distinct objects.

See Also:

Object.equals(Object),
System.identityHashCode

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.java b/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.java new file mode 100644 index 000000000000..f0a1686366f6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/markdownJepExample.java @@ -0,0 +1,34 @@ +class MarkdownJepExample { + + /// Returns a hash code value for the object. This method is + /// supported for the benefit of hash tables such as those provided by + /// [java.util.HashMap]. + /// + /// The general contract of `hashCode` is: + /// + /// - Whenever it is invoked on the same object more than once during + /// an execution of a Java application, the `hashCode` method + /// must consistently return the same integer, provided no information + /// used in `equals` comparisons on the object is modified. + /// This integer need not remain consistent from one execution of an + /// application to another execution of the same application. + /// - If two objects are equal according to the + /// [equals][#equals(Object)] method, then calling the + /// `hashCode` method on each of the two objects must produce the + /// same integer result. + /// - It is _not_ required that if two objects are unequal + /// according to the [equals][#equals(Object)] method, then + /// calling the `hashCode` method on each of the two objects + /// must produce distinct integer results. However, the programmer + /// should be aware that producing distinct integer results for + /// unequal objects may improve the performance of hash tables. + /// + /// @implSpec + /// As far as is reasonably practical, the `hashCode` method defined + /// by class `Object` returns distinct integers for distinct objects. + /// + /// @return a hash code value for this object. + /// @see java.lang.Object#equals(java.lang.Object) + /// @see java.lang.System#identityHashCode + public String longExample() { return null; } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavadocCompletionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavadocCompletionTest.java index 192c7e8fefb0..5a115e44fe9c 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavadocCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/JavadocCompletionTest.java @@ -203,6 +203,9 @@ public class JavadocCompletionTest extends LightFixtureCompletionTestCase { public void testMethodBeforeSharp() { doTest(); } + public void testMethodInMarkdownReferenceLink() { + doTest(); + } public void testFieldReferenceInInnerClassJavadoc() { doTest(); @@ -933,4 +936,6 @@ public class JavadocCompletionTest extends LightFixtureCompletionTestCase { List strings = myFixture.getLookupElementStrings(); assertTrue(strings.containsAll(Arrays.asList("java", "JShellLanguage", "JVM"))); } + + } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index 5a5e58de2ae7..8497b42fd796 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -196,6 +196,9 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase { PsiClass outerClass = ((PsiJavaFile) myFile).getClasses()[0]; verifyJavaDoc(outerClass.getMethods()[0]); } + public void testMarkdownJepExample(){ + doTestMethod(); + } public void testRepeatableAnnotations() { useJava8();