From 48ce294241af90bb76cac79a6ce33724c3c1c1fd Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 12 Sep 2016 17:13:22 +0300 Subject: [PATCH] [java] javadoc in modules --- .../javadoc/JavaDocInfoGenerator.java | 20 +++++++- .../src/com/intellij/psi/PsiJavaModule.java | 2 +- .../lang/java/parser/JavaParserUtil.java | 6 ++- .../lang/java/parser/ModuleParser.java | 2 +- .../psi/impl/compiled/ClsJavaModuleImpl.java | 8 +++ .../psi/impl/source/PsiJavaModuleImpl.java | 8 +++ .../psi/parser-partial/modules/Simple2.txt | 4 +- .../javadoc/LightJavadocGeneratorTest.kt | 51 +++++++++++++++++++ .../javadoc/dangling_javadoc/module-info.java | 4 ++ .../DanglingJavadocInspectionTest.java | 13 ++++- 10 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/javadoc/LightJavadocGeneratorTest.kt create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/dangling_javadoc/module-info.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 51e0f897419c..1e101063e50c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -365,7 +365,7 @@ public class JavaDocInfoGenerator { return packageName; } - public boolean generateDocInfoCore (StringBuilder buffer, boolean generatePrologueAndEpilogue) { + public boolean generateDocInfoCore(StringBuilder buffer, boolean generatePrologueAndEpilogue) { if (myElement instanceof PsiClass) { generateClassJavaDoc(buffer, (PsiClass)myElement, generatePrologueAndEpilogue); } @@ -387,7 +387,10 @@ public class JavaDocInfoGenerator { generatePackageJavaDoc(buffer, aPackage, generatePrologueAndEpilogue); } else if (myElement instanceof PsiPackage) { - generatePackageJavaDoc(buffer, (PsiPackage) myElement, generatePrologueAndEpilogue); + generatePackageJavaDoc(buffer, (PsiPackage)myElement, generatePrologueAndEpilogue); + } + else if (myElement instanceof PsiJavaModule) { + generateModuleJavaDoc(buffer, (PsiJavaModule)myElement, generatePrologueAndEpilogue); } else { return false; @@ -723,6 +726,19 @@ public class JavaDocInfoGenerator { } } + private void generateModuleJavaDoc(StringBuilder buffer, PsiJavaModule module, boolean generatePrologueAndEpilogue) { + if (generatePrologueAndEpilogue) generatePrologue(buffer); + + buffer.append("
module ").append(module.getName()).append("
"); + + PsiDocComment comment = module.getDocComment(); + if (comment != null) { + generateCommonSection(buffer, comment); + } + + if (generatePrologueAndEpilogue) generateEpilogue(buffer); + } + /** * Finds doc comment immediately preceding package statement */ diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java index 341cf41343cf..11f3f622b205 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull; * * @since 2016.3 */ -public interface PsiJavaModule extends NavigatablePsiElement, PsiNamedElement { +public interface PsiJavaModule extends NavigatablePsiElement, PsiNamedElement, PsiJavaDocumentedElement { String MODULE_INFO_CLASS = "module-info"; String MODULE_INFO_FILE = MODULE_INFO_CLASS + ".java"; String MODULE_INFO_CLS_FILE = MODULE_INFO_CLASS + ".class"; diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index 572707325034..db152ddea456 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -110,7 +110,9 @@ public class JavaParserUtil { } } - private static final TokenSet PRECEDING_COMMENT_SET = ElementType.FULL_MEMBER_BIT_SET; + private static final TokenSet PRECEDING_COMMENT_SET = TokenSet.orSet( + TokenSet.create(JavaElementType.MODULE), ElementType.FULL_MEMBER_BIT_SET); + private static final TokenSet TRAILING_COMMENT_SET = TokenSet.orSet( TokenSet.create(JavaElementType.PACKAGE_STATEMENT), ElementType.IMPORT_STATEMENT_BASE_BIT_SET, ElementType.FULL_MEMBER_BIT_SET, ElementType.JAVA_STATEMENT_BIT_SET); diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java index 9216f033cb5a..4eac9ca4cb33 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ModuleParser.java @@ -61,7 +61,7 @@ public class ModuleParser { parseModuleContent(builder); } - module.done(JavaElementType.MODULE); + JavaParserUtil.done(module, JavaElementType.MODULE); if (builder.getTokenType() != null) { parseExtras(builder, JavaErrorMessages.message("unexpected.tokens")); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java index 7f23ea99588b..42fbc9ff4b4e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaModuleImpl.java @@ -22,9 +22,11 @@ import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; +import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ClsJavaModuleImpl extends ClsRepositoryPsiElement implements PsiJavaModule { private PsiJavaModuleReferenceElement myReference; @@ -67,6 +69,12 @@ public class ClsJavaModuleImpl extends ClsRepositoryPsiElement implements PsiJavaModule { public PsiJavaModuleImpl(@NotNull PsiJavaModuleStub stub) { @@ -64,6 +66,12 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement imp return this; } + @Nullable + @Override + public PsiDocComment getDocComment() { + return PsiTreeUtil.getChildOfType(this, PsiDocComment.class); + } + @Override public ItemPresentation getPresentation() { return ItemPresentationProviders.getItemPresentation(this); diff --git a/java/java-tests/testData/psi/parser-partial/modules/Simple2.txt b/java/java-tests/testData/psi/parser-partial/modules/Simple2.txt index 0d063633fd88..51cf28e97f97 100644 --- a/java/java-tests/testData/psi/parser-partial/modules/Simple2.txt +++ b/java/java-tests/testData/psi/parser-partial/modules/Simple2.txt @@ -1,7 +1,7 @@ PsiJavaFile:Simple2.java - PsiComment(C_STYLE_COMMENT)('/* comment */') - PsiWhiteSpace('\n') PsiJavaModule:X + PsiComment(C_STYLE_COMMENT)('/* comment */') + PsiWhiteSpace('\n') PsiKeyword:module('module') PsiWhiteSpace(' ') PsiJavaModuleReference diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/LightJavadocGeneratorTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/LightJavadocGeneratorTest.kt new file mode 100644 index 000000000000..385ed3874d52 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/LightJavadocGeneratorTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.javadoc + +import com.intellij.openapi.util.JDOMUtil +import com.intellij.psi.PsiJavaFile +import com.intellij.testFramework.Assertions.assertThat +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +class LightJavadocGeneratorTest : LightCodeInsightFixtureTestCase() { + override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_9 + + fun testPlainModule() = doTestModule("module M.N { }", """ + +
+          module
+          M.N
+        
+ """.trimIndent()) + + fun testDocumentedModule() = doTestModule("/** One humble module. */\nmodule M.N { }", """ + +
+          module
+          M.N
+        
+ One humble module. + """.trimIndent()) + + private fun doTestModule(text: String, expected: String) { + val file = myFixture.configureByText("module-info.java", text) + val module = (file as PsiJavaFile).moduleDeclaration!! + val docInfo = JavaDocInfoGeneratorFactory.create(project, module).generateDocInfo(null)!! + val body = JDOMUtil.loadDocument(docInfo).rootElement.getChild("body") + assertThat(body).isEqualTo(expected) + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/dangling_javadoc/module-info.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/dangling_javadoc/module-info.java new file mode 100644 index 000000000000..6013b8548fdd --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/dangling_javadoc/module-info.java @@ -0,0 +1,4 @@ +/** + * A nice little module. + */ +module M { } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/DanglingJavadocInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/DanglingJavadocInspectionTest.java index 085e134de0fb..77e83552560f 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/DanglingJavadocInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/DanglingJavadocInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,13 @@ package com.siyeh.ig.javadoc; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.openapi.roots.LanguageLevelModuleExtension; +import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.siyeh.ig.LightInspectionTestCase; import org.jetbrains.annotations.Nullable; +import static com.intellij.pom.java.LanguageLevel.JDK_1_9; + /** * @author Bas Leijdekkers */ @@ -32,9 +36,14 @@ public class DanglingJavadocInspectionTest extends LightInspectionTestCase { doNamedTest("package-info"); } + public void testModuleInfo() { + ModuleRootModificationUtil.updateModel(myModule, m -> m.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(JDK_1_9)); + doNamedTest("module-info"); + } + @Nullable @Override protected InspectionProfileEntry getInspection() { return new DanglingJavadocInspection(); } -} +} \ No newline at end of file