diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 597ff2556d85..50e3b7330916 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1618,9 +1618,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(module, Feature.MODULES)); if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileName(module, myFile)); if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileDuplicates(module, myFile)); - if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateRequires(module)); - if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateExports(module)); - if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateUses(module)); + if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateStatements(module)); if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileLocation(module, myFile)); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index e6bc4c0ebd31..649466b31446 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -47,7 +47,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.intellij.codeInsight.daemon.JavaErrorMessages.BUNDLE; import static com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE; import static com.intellij.psi.SyntaxTraverser.psiTraverser; @@ -84,11 +83,45 @@ public class ModuleHighlightUtil { } @NotNull - static List checkDuplicateRequires(@NotNull PsiJavaModule module) { - return checkDuplicateRefs( + static List checkDuplicateStatements(@NotNull PsiJavaModule module) { + List results = ContainerUtil.newSmartList(); + + checkDuplicateRefs( psiTraverser().children(module).filter(PsiRequiresStatement.class), - st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText).orElse(null), - "module.duplicate.requires"); + st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText), + "module.duplicate.requires", results); + + checkDuplicateRefs( + psiTraverser().children(module).filter(PsiExportsStatement.class), + st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText), + "module.duplicate.export", results); + + checkDuplicateRefs( + psiTraverser().children(module).filter(PsiUsesStatement.class), + st -> Optional.ofNullable(st.getClassReference()).map(ModuleHighlightUtil::refText), + "module.duplicate.uses", results); + + return results; + } + + private static void checkDuplicateRefs(Iterable statements, + Function> ref, + @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key, + List results) { + Set filter = ContainerUtil.newHashSet(); + for (T statement : statements) { + String refText = ref.apply(statement).orElse(null); + if (refText != null && !filter.add(refText)) { + String message = JavaErrorMessages.message(key, refText); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).description(message).create(); + QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(statement)); + results.add(info); + } + } + } + + private static String refText(PsiJavaCodeReferenceElement ref) { + return PsiNameHelper.getQualifiedClassName(ref.getText(), true); } @Nullable @@ -189,14 +222,6 @@ public class ModuleHighlightUtil { return results; } - @NotNull - static List checkDuplicateExports(@NotNull PsiJavaModule module) { - return checkDuplicateRefs( - psiTraverser().children(module).filter(PsiExportsStatement.class), - st -> Optional.ofNullable(st.getPackageReference()).map(ref -> PsiNameHelper.getQualifiedClassName(ref.getText(), true)).orElse(null), - "module.duplicate.export"); - } - @Nullable static HighlightInfo checkServiceReference(@Nullable PsiJavaCodeReferenceElement refElement) { if (refElement != null) { @@ -210,34 +235,6 @@ public class ModuleHighlightUtil { return null; } - @NotNull - static List checkDuplicateUses(@NotNull PsiJavaModule module) { - return checkDuplicateRefs( - psiTraverser().children(module).filter(PsiUsesStatement.class), - st -> Optional.ofNullable(st.getClassReference()).map(ref -> PsiNameHelper.getQualifiedClassName(ref.getText(), true)).orElse(null), - "module.duplicate.uses"); - } - - private static List checkDuplicateRefs(Iterable statements, - Function ref, - @PropertyKey(resourceBundle = BUNDLE) String key) { - List results = null; - - Set names = ContainerUtil.newHashSet(); - for (T statement : statements) { - String refText = ref.apply(statement); - if (refText != null && !names.add(refText)) { - String message = JavaErrorMessages.message(key, refText); - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).description(message).create(); - QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(statement)); - if (results == null) results = ContainerUtil.newSmartList(); - results.add(info); - } - } - - return results != null ? results : Collections.emptyList(); - } - private static QuickFixFactory factory() { return QuickFixFactory.getInstance(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt index aa8d37bae175..a38b3287ac38 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt @@ -42,6 +42,19 @@ class ModuleHighlightingTest : LightCodeInsightFixtureTestCase() { myFixture.checkHighlighting() } + fun testDuplicateStatements() { + addFile("pkg/main/C.java", "package pkg.main;\npublic class C { }") + doTest(""" + module M { + requires M2; + requires M2; + exports pkg.main; + exports pkg. main; + uses pkg.main.C; + uses pkg. main . /*...*/ C; + }""".trimIndent(), true) + } + fun testRequires() { doTest(""" module M1 { @@ -51,14 +64,6 @@ class ModuleHighlightingTest : LightCodeInsightFixtureTestCase() { }""".trimIndent(), true) } - fun testDuplicateRequires() { - doTest(""" - module M { - requires M2; - requires M2; - }""".trimIndent(), true) - } - fun testExports() { addFile("pkg/empty/package-info.java", "package pkg.empty;") addFile("pkg/main/C.java", "package pkg.main;\nclass C { }") @@ -72,15 +77,6 @@ class ModuleHighlightingTest : LightCodeInsightFixtureTestCase() { }""".trimIndent()) } - fun testDuplicateExports() { - addFile("pkg/main/C.java", "package pkg.main;\nclass C { }") - doTest(""" - module M { - exports pkg.main; - exports pkg. main; - }""".trimIndent()) - } - fun testUses() { addFile("pkg/main/C.java", "package pkg.main;\nclass C { }") addFile("pkg/main/E.java", "package pkg.main;\npublic enum E { }") @@ -93,15 +89,6 @@ class ModuleHighlightingTest : LightCodeInsightFixtureTestCase() { }""".trimIndent()) } - fun testDuplicateUses() { - addFile("pkg/main/C.java", "package pkg.main;\npublic class C { }") - doTest(""" - module M { - uses pkg.main.C; - uses pkg. main . /*...*/ C; - }""".trimIndent()) - } - // private fun addFile(path: String, text: String) = VfsTestUtil.createFile(LightPlatformTestCase.getSourceRoot(), path, text)