fix(JavaDoc): better autocomplete

GitOrigin-RevId: 64cc8794d732cd08566413b0070b371768e47d8f
This commit is contained in:
Mathias Boulay
2024-08-16 17:56:28 +02:00
committed by intellij-monorepo-bot
parent a84875ed35
commit f95cbb9677
13 changed files with 104 additions and 18 deletions

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -0,0 +1,5 @@
/// Some text [Fubar#fo<caret>]
class Fubar {
void foo(char[] data);
}

View File

@@ -0,0 +1,5 @@
/// Some text [Fubar#foo(char\[\])]<caret>
class Fubar {
void foo(char[] data);
}

View File

@@ -4,5 +4,5 @@
/// - [a class][String]
/// - [a field][String#CASE_INSENSITIVE_ORDER]
/// - [a method][String#chars()]
///<caret>
/// <caret>
class C{}

View File

@@ -1,2 +1,2 @@
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownCodeBlock</span></pre></div><div class='content'> <pre><code><span style="color:#000080;font-weight:bold;">new&#32;</span><span style="">String();<br></span><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello&#32;Markdown"</span><span style="">);</span></code></pre>
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownCodeBlock</span></pre></div><div class='content'><pre><code><span style="color:#000080;font-weight:bold;">new&#32;</span><span style="">String();<br></span><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello&#32;Markdown"</span><span style="">);</span></code></pre>
</div><table class='sections'><p></table>

View File

@@ -1,2 +1,2 @@
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownFeatures</span></pre></div><div class='content'><h1>Title1</h1><h2>Title2</h2><h3>Title 3</h3><p><em>italic</em> <strong>strong</strong> <code>code</code></p><p>Separate paragraph</p> <pre><code><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello&#32;there"</span><span style="">);</span></code></pre>
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownFeatures</span></pre></div><div class='content'><h1>Title1</h1><h2>Title2</h2><h3>Title 3</h3><p><em>italic</em> <strong>strong</strong> <code>code</code></p><p>Separate paragraph</p> <pre><code><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello&#32;there"</span><span style="">);</span></code></pre>
</div><table class='sections'><p></table>

View File

@@ -1,3 +1,2 @@
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class">&nbsp;<a href="psi_element://MarkdownInheritedDoc"><code><span style="color:#000000;">MarkdownInheritedDoc</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">void</span>&nbsp;<span style="color:#000000;">foo</span><span style="">(</span><span style="">)</span></pre></div><div class='content'><p>Markdown variant
</p> I am legacy javadoc, I hope no one disturbs my _underlines_ and **astrerisks** <p>More <em>markdown</em>
syntax</p></div><table class='sections'><tr><td valign='top' class='section'><p>Overrides:</td><td valign='top'><p><a href="psi_element://MarkdownInheritDoc#foo()"><code><span style="color:#000000;">foo</span></code></a> in class <a href="psi_element://MarkdownInheritDoc"><code><span style="color:#000000;">MarkdownInheritDoc</span></code></a></td></table>
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class">&nbsp;<a href="psi_element://MarkdownInheritedDoc"><code><span style="color:#000000;">MarkdownInheritedDoc</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">void</span>&nbsp;<span style="color:#000000;">foo</span><span style="">(</span><span style="">)</span></pre></div><div class='content'><p>Markdown variant</p> I am legacy javadoc, I hope no one disturbs my _underlines_ and **astrerisks** <p>More <em>markdown</em>
syntax</p></div><table class='sections'><tr><td valign='top' class='section'><p>Overrides:</td><td valign='top'><p><a href="psi_element://MarkdownInheritDoc#foo()"><code><span style="color:#000000;">foo</span></code></a> in class <a href="psi_element://MarkdownInheritDoc"><code><span style="color:#000000;">MarkdownInheritDoc</span></code></a></td></table>

View File

@@ -0,0 +1,17 @@
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class">&nbsp;<a href="psi_element://MarkdownJepExample"><code><span style="color:#000000;">MarkdownJepExample</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">public</span>&nbsp;<a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a>&nbsp;<span style="color:#000000;">longExample</span><span style="">(</span><span style="">)</span></pre></div><div class='content'><p>Returns a hash code value for the object. This method is
supported for the benefit of hash tables such as those provided by
<a href="psi_element://java.util.HashMap"><code><span style="color:#0000ff;">java.util.HashMap</span></code></a>.</p><p>The general contract of <code>hashCode</code> is:</p><ul><li>Whenever it is invoked on the same object more than once during
an execution of a Java application, the <code>hashCode</code> method
must consistently return the same integer, provided no information
used in <code>equals</code> 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.</li><li>If two objects are equal according to the
<a href="psi_element://java.lang.Object#equals(java.lang.Object)"><span style="color:#0000ff;">equals</span></a> method, then calling the
<code>hashCode</code> method on each of the two objects must produce the
same integer result.</li><li>It is <em>not</em> required that if two objects are unequal
according to the <a href="psi_element://java.lang.Object#equals(java.lang.Object)"><span style="color:#0000ff;">equals</span></a> method, then
calling the <code>hashCode</code> 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.</li></ul></div><table class='sections'><tr><td valign='top' class='section'><p>Returns:</td><td valign='top'><p>a hash code value for this object.</td><tr><td valign='top' class='section'><p>Implementation<br>Requirements:</td><td valign='top'><p><p>As far as is reasonably practical, the <code>hashCode</code> method defined
by class <code>Object</code> returns distinct integers for distinct objects.</p></td><tr><td valign='top' class='section'><p>See Also:</td><td valign='top'><p><a href="psi_element://java.lang.Object#equals(java.lang.Object)"><code><span style="color:#0000ff;">Object</span><span style="">.</span><span style="color:#0000ff;">equals</span><span style="">(Object)</span></code></a>,<br><a href="psi_element://java.lang.System#identityHashCode(java.lang.Object)"><code><span style="color:#0000ff;">System</span><span style="">.</span><span style="color:#0000ff;">identityHashCode</span></code></a></td></table>

View File

@@ -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; }
}

View File

@@ -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<String> strings = myFixture.getLookupElementStrings();
assertTrue(strings.containsAll(Arrays.asList("java", "JShellLanguage", "JVM")));
}
}

View File

@@ -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();