From f2593c7a3d602a60d216a2ff010f9791b5c02c3d Mon Sep 17 00:00:00 2001 From: Louis Vignier Date: Fri, 26 Apr 2024 13:29:55 +0200 Subject: [PATCH] [javadoc] Add javadoc for type parameters #IDEA-326131 Fixed GitOrigin-RevId: 940612c4c8a335e1607c5db596e10fccb575ebea --- .../javadoc/JavaDocInfoGenerator.java | 45 ++++++++++++++++++- .../javadocIG/classTypeParameter2.html | 2 + .../javadocIG/classTypeParameter2.java | 6 +++ .../javadocIG/methodTypeParameter2.html | 2 + .../javadocIG/methodTypeParameter2.java | 7 +++ .../codeInsight/javadocIG/paramInMethod.html | 2 + .../codeInsight/javadocIG/paramInMethod.java | 6 +++ .../javadoc/JavaDocInfoGeneratorTest.java | 3 ++ 8 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/paramInMethod.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/paramInMethod.java 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 c644972454e7..cc71ed9e6511 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -544,7 +544,10 @@ public class JavaDocInfoGenerator { } public boolean generateDocInfoCore(StringBuilder buffer, boolean generatePrologue) { - if (myElement instanceof PsiClass cls) { + if (myElement instanceof PsiTypeParameter parameter) { + generateTypeParameterJavaDoc(buffer, parameter, generatePrologue); + } + else if (myElement instanceof PsiClass cls) { generateClassJavaDoc(buffer, cls, generatePrologue); } else if (myElement instanceof PsiMethod method) { @@ -834,6 +837,33 @@ public class JavaDocInfoGenerator { buffer.append(DocumentationMarkup.SECTIONS_END); } + private void generateTypeParameterJavaDoc(StringBuilder buffer, PsiTypeParameter parameter, boolean generatePrologue) { + if (parameter instanceof PsiAnonymousClass) return; + + if (generatePrologue) generatePrologue(buffer); + + if (!isRendered()) { + buffer.append(DocumentationMarkup.DEFINITION_START); + generateTypeParameterSignature(buffer, parameter, SignaturePlace.Javadoc); + buffer.append(DocumentationMarkup.DEFINITION_END); + } + + if (parameter.getOwner() instanceof PsiJavaDocumentedElement documentedElement) { + final PsiDocComment docComment = getDocComment(documentedElement); + PsiDocTag[] localTags = docComment != null ? docComment.getTags() : PsiDocTag.EMPTY_ARRAY; + PsiDocTag tag = getTagByName(localTags, "<" + parameter.getName() + ">"); + if (tag != null) { + buffer.append("

"); + final PsiElement[] elements = Arrays.stream(tag.getChildren()) + .skip(1) + .filter(e -> e.getNode().getElementType() != JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS && + e.getNode().getElementType() != JavaDocElementType.DOC_PARAMETER_REF) + .toArray(PsiElement[]::new); + generateValue(buffer, elements, ourEmptyElementsProvider); + } + } + } + private void generateRecordParametersSection(StringBuilder buffer, PsiClass recordClass, PsiDocComment comment) { if (!recordClass.isRecord() || comment == null) return; PsiDocTag[] localTags = comment.findTagsByName("param"); @@ -899,6 +929,19 @@ public class JavaDocInfoGenerator { return false; } + private void generateTypeParameterSignature(StringBuilder buffer, PsiTypeParameter parameter, SignaturePlace place) { + boolean generateLink = place == SignaturePlace.Javadoc; + + appendPlainText(buffer, generateOneTypeParameterPresentableName(parameter)); + + buffer.append('\n'); + + PsiClassType[] refs = parameter.getExtendsListTypes(); + if (refs.length > 0) { + generateRefList(buffer, parameter, generateLink, refs, "extends"); + } + } + private void generateRefList(StringBuilder buffer, PsiClass aClass, boolean generateLink, PsiClassType[] refs, String keyword) { appendStyledSpan(buffer, getHighlightingManager().getKeywordAttributes(), keyword); buffer.append(" "); diff --git a/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.html b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.html new file mode 100644 index 000000000000..c5126116cd44 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.html @@ -0,0 +1,2 @@ +

<T>
+extends Runnable

param description

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.java b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.java new file mode 100644 index 000000000000..969a67f1b569 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter2.java @@ -0,0 +1,6 @@ +/** + * @param param description + */ +class MethodTypeParam<T extends Runnable, K extends String> { + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.html b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.html new file mode 100644 index 000000000000..cbf207265ea0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.html @@ -0,0 +1,2 @@ +
<T>
+

type param

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.java b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.java new file mode 100644 index 000000000000..2f9fee6f99c7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter2.java @@ -0,0 +1,7 @@ +class MethodTypeParam2 { + /** + * @param type param + */ + <T> void foo(T t) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.html b/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.html new file mode 100644 index 000000000000..cd613f4503d9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.html @@ -0,0 +1,2 @@ +
<T>
+

parameter

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.java b/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.java new file mode 100644 index 000000000000..689f2450e46c --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/paramInMethod.java @@ -0,0 +1,6 @@ +class C { + /** + * @param parameter + */ + void m(T i) {} +} \ No newline at end of file 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 088b0bf8bea1..d4ab2b14b428 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 @@ -77,11 +77,13 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase { public void testEscapingStringValue() { doTestMethod(); } public void testIdeadev2326() { doTestMethod(); } public void testMethodTypeParameter() { doTestMethod(); } + public void testMethodTypeParameter2() { doTestAtCaret(); } public void testInheritedDocInThrows() { doTestMethod(); } public void testInheritedDocInThrows1() { doTestMethod(); } public void testEscapeValues() { doTestClass(); } public void testClassTypeParameter() { doTestClass(); } public void testClassTypeParameter1() { doTestClass(); } + public void testClassTypeParameter2() { doTestAtCaret(); } public void testUnicodeEscapes() { doTestClass(); } public void testEnumValueOf() { doTestMethod(); } public void testMethodFormatting() { doTestMethod(); } @@ -119,6 +121,7 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase { public void testDocumentationForUncheckedExceptionsInSupers() { doTestAtCaret(); } public void testDocumentationForGetterByField() { doTestAtCaret(); } public void testParamInJavadoc() { doTestAtCaret(); } + public void testParamInMethod() { doTestAtCaret(); } public void testExternalLinksInJavadoc() { doTestAtCaret(); } public void testLiteralInsideCode() { useJava8(); doTestClass(); } public void testSuperJavadocExactResolve() { doTestAtCaret(); }