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 e10d3ca574c7..f5d8e650f74d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -689,7 +689,16 @@ public class JavaDocInfoGenerator { @NlsSafe String ownerLink = null; String ownerIcon = null; - if (element instanceof PsiClass) { + if (element instanceof PsiPackage pkg) { + return HtmlChunk.div() + .setClass("bottom") + .children( + HtmlChunk.tag("icon").attr("src", "AllIcons.Nodes.Package"), + HtmlChunk.nbsp(), + HtmlChunk.tag("code").addText(pkg.getQualifiedName()) + ); + } + else if (element instanceof PsiClass) { PsiFile file = element.getContainingFile(); if (file instanceof PsiJavaFile javaFile) { String packageName = javaFile.getPackageName(); @@ -1041,6 +1050,7 @@ public class JavaDocInfoGenerator { } private void generatePackageJavaDoc(StringBuilder buffer, PsiPackage psiPackage, boolean generatePrologue) { + boolean hasInfo = false; for (PsiDirectory directory : psiPackage.getDirectories(GlobalSearchScope.everythingScope(myProject))) { PsiFile packageInfoFile = directory.findFile(PsiPackage.PACKAGE_INFO_FILE); if (packageInfoFile != null) { @@ -1049,6 +1059,7 @@ public class JavaDocInfoGenerator { ASTNode docCommentNode = findRelevantCommentNode(node); if (docCommentNode != null) { generatePackageJavaDoc(buffer, (PsiDocComment)docCommentNode.getPsi(), generatePrologue); + hasInfo = true; break; } } @@ -1056,9 +1067,43 @@ public class JavaDocInfoGenerator { PsiFile packageHtmlFile = directory.findFile("package.html"); if (packageHtmlFile != null) { generatePackageHtmlJavaDoc(buffer, packageHtmlFile, generatePrologue); + hasInfo = true; break; } } + if (!hasInfo) { + generateDefaultPackageDoc(buffer, psiPackage, generatePrologue); + } + } + + private void generateDefaultPackageDoc(StringBuilder buffer, PsiPackage aPackage, boolean generatePrologue) { + if (generatePrologue) generatePrologue(buffer); + HtmlBuilder hb = new HtmlBuilder(); + hb.append(HtmlChunk.tag("h3").addText(JavaBundle.message("package.classes"))); + Comparator comparator = Comparator.comparing(PsiClass::getName, Comparator.nullsLast(Comparator.naturalOrder())); + Arrays.stream(aPackage.getClasses()).sorted(comparator).forEach(psiClass -> { + String link = generateLink(psiClass, psiClass.getName(), false, false); + if (link != null) { + hb.append(HtmlChunk.tag("div") + .children( + HtmlChunk.tag("icon").attr("src", getIcon(psiClass)), + HtmlChunk.nbsp(), + HtmlChunk.raw(link) + )); + } + }); + buffer.append(hb); + buffer.append(DocumentationMarkup.SECTIONS_END); + } + + @NotNull + private static String getIcon(@NotNull PsiClass psiClass) { + return psiClass.isEnum() ? "AllIcons.Nodes.Enum" : + psiClass.isRecord() ? "AllIcons.Nodes.Record" : + psiClass.isAnnotationType() ? "AllIcons.Nodes.Annotationtype" : + psiClass.isInterface() ? "AllIcons.Nodes.Interface" : + psiClass.hasModifierProperty(PsiModifier.ABSTRACT) ? "AllIcons.Nodes.AbstractClass" : + "AllIcons.Nodes.Class"; } private void generatePackageJavaDoc(StringBuilder buffer, PsiDocComment comment, boolean generatePrologue) { @@ -2456,7 +2501,10 @@ public class JavaDocInfoGenerator { appendMaybeUnresolvedLink(buffer, target, label, target.getProject(), false); } - private static @Nullable String generateLink(@NotNull PsiElement element, String label, boolean plainLink, boolean isRenderedDoc) { + private static @Nullable @NlsSafe String generateLink(@NotNull PsiElement element, + String label, + boolean plainLink, + boolean isRenderedDoc) { String refText = JavaDocUtil.getReferenceText(element.getProject(), element); if (refText != null) { StringBuilder linkBuilder = new StringBuilder(); diff --git a/java/java-tests/testData/codeInsight/javadocIG/libraryPackageDocumentation.html b/java/java-tests/testData/codeInsight/javadocIG/libraryPackageDocumentation.html index d3b6a189087a..30f583a089f5 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/libraryPackageDocumentation.html +++ b/java/java-tests/testData/codeInsight/javadocIG/libraryPackageDocumentation.html @@ -1,3 +1,3 @@ -
+
 com.jetbrains
Description of com.jetbrains package

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageHtml/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageHtml/packageInfo.html index e68a268b083e..8e41998695fc 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/packageHtml/packageInfo.html +++ b/java/java-tests/testData/codeInsight/javadocIG/packageHtml/packageInfo.html @@ -1,3 +1,3 @@ -
+
 packageHtml
Some text.

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html index 4d5cf0b19ca1..c4932c71dacd 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html @@ -1,3 +1,3 @@ -
+
 packageInfo
This package contains nothing but package-info.java

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfoFromComment/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfoFromComment/packageInfo.html index abaaaec2bd86..e54727761804 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/packageInfoFromComment/packageInfo.html +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfoFromComment/packageInfo.html @@ -1,3 +1,3 @@ -
+
 packageInfoFromComment
some text
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html index 85cd5e526aa7..4a2a1969bca9 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html @@ -1,3 +1,3 @@ -
+
 packageInfoWithCopyright
This package contains nothing but package-info.java
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/A.java b/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/A.java new file mode 100644 index 000000000000..8e8a7542a60c --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/A.java @@ -0,0 +1,7 @@ +package packageWithoutPackageInfo; + +class A {} +interface B {} +enum C {} +@interface D{} +abstract class E{} diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/packageInfo.html new file mode 100644 index 000000000000..e18d500be59e --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/packageWithoutPackageInfo/packageInfo.html @@ -0,0 +1 @@ +
 packageWithoutPackageInfo

Package classes:

 A
 B
 C
 D
 E
\ 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 9358ee5ed517..d1fb63a6ea4c 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 @@ -109,6 +109,7 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase { public void testSuperJavadocExactResolve() { doTestAtCaret(); } public void testSuperJavadocErasureResolve() { doTestAtCaret(); } public void testPackageInfo() { doTestPackageInfo(); } + public void testPackageWithoutPackageInfo() { doTestPackageInfo(); } public void testPackageHtml() { doTestPackageInfo(); } public void testSyntheticEnumValues() { doTestAtCaret(); } public void testVariableDoc() { doTestAtCaret(); } diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties index 760eba241746..9a63cdefbb5f 100644 --- a/java/openapi/resources/messages/JavaBundle.properties +++ b/java/openapi/resources/messages/JavaBundle.properties @@ -1785,3 +1785,4 @@ adds.library.preview=Adds {0, choice, 1#library ''''{1}''''|2#one of {2}} to mod notification.content.added.annotations=Added {0} {0, choice, 1#annotation|2#annotations} intention.make.final.fixer.stream=Make ''{0}'' effectively final using stream API intention.make.final.fixer.if=Make ''{0}'' effectively final by moving initializer to the ''if'' statement +package.classes=Package classes: