diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java index b577279aad72..0ed7bc667da0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java @@ -92,7 +92,7 @@ public class JavaModuleGraphUtil { private static List> findCycles(Project project) { Set projectModules = ContainerUtil.newHashSet(); for (Module module : ModuleManager.getInstance(project).getModules()) { - Collection files = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope(false)); + Collection files = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope()); if (files.size() > 1) return Collections.emptyList(); // aborts the process when there are incorrect modules in the project Optional.ofNullable(ContainerUtil.getFirstItem(files)) .map(PsiManager.getInstance(project)::findFile) @@ -146,7 +146,7 @@ public class JavaModuleGraphUtil { MultiMap relations = MultiMap.create(); Set transitiveEdges = ContainerUtil.newTroveSet(); for (Module module : ModuleManager.getInstance(project).getModules()) { - Collection files = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope(false)); + Collection files = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope()); Optional.ofNullable(ContainerUtil.getFirstItem(files)) .map(PsiManager.getInstance(project)::findFile) .map(f -> f instanceof PsiJavaFile ? ((PsiJavaFile)f).getModuleDeclaration() : null) 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 c9beed1c3ce2..dc4da03fa5c0 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 @@ -79,18 +79,24 @@ public class ModuleHighlightUtil { return LightJavaModule.getModule(PsiManager.getInstance(project), classRoot); } } - - return null; } else { Module module = index.getModuleForFile(file); - return Optional.ofNullable(module) - .map(m -> FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, m.getModuleScope(false))) - .map(c -> c.size() == 1 ? c.iterator().next() : null) - .map(f -> PsiManager.getInstance(project).findFile(f)) - .map(f -> f instanceof PsiJavaFile ? ((PsiJavaFile)f).getModuleDeclaration() : null) - .orElse(null); + if (module != null) { + boolean isTest = index.isInTestSourceContent(file); + List files = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope()).stream() + .filter(f -> index.isInTestSourceContent(f) == isTest) + .collect(Collectors.toList()); + if (files.size() == 1) { + PsiFile psiFile = PsiManager.getInstance(project).findFile(files.get(0)); + if (psiFile instanceof PsiJavaFile) { + return ((PsiJavaFile)psiFile).getModuleDeclaration(); + } + } + } } + + return null; } static HighlightInfo checkPackageStatement(@NotNull PsiPackageStatement statement, @NotNull PsiFile file, @Nullable PsiJavaModule module) { 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 7ff5110f22e2..52dd549f2935 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt @@ -246,6 +246,80 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { """.trimIndent()) } + fun testPackageAccessibilityInNonModularTest() { + addFile("module-info.java", "module M { }") + addFile("module-info.java", "module M2 { exports pkg.m2; exports pkg.m2.impl to close.friends.only; }", M2) + addFile("pkg/m2/C2.java", "package pkg.m2;\npublic class C2 { }", M2) + addFile("pkg/m2/impl/C2Impl.java", "package pkg.m2.impl;\nimport pkg.m2.C2;\npublic class C2Impl { public static C2 make() {} }", M2) + addFile("pkg/m4/C4.java", "package pkg.m4;\npublic class C4 { }", M4) + addFile("module-info.java", "module M5 { exports pkg.m5; }", M5) + addFile("pkg/m5/C5.java", "package pkg.m5;\npublic class C5 { }", M5) + addFile("module-info.java", "module M6 { requires transitive M7; }", M6) + addFile("module-info.java", "module M7 { exports pkg.m7; }", M7) + addFile("pkg/m7/C7.java", "package pkg.m7;\npublic class C7 { }", M7) + highlight("test.java", """ + import pkg.m2.C2; + import pkg.m2.*; + import pkg.m2.impl.C2Impl; + import pkg.m2.impl.*; + import pkg.m4.C4; + import pkg.m5.C5; + import pkg.m7.C7; + + import pkg.lib1.LC1; + import pkg.lib1.impl.LC1Impl; + import pkg.lib1.impl.*; + + import pkg.lib2.LC2; + import pkg.lib2.impl.LC2Impl; + + import static pkg.m2.impl.C2Impl.make; + + /** See also {@link C2Impl#make} */ + class C {{ + C2Impl.make(); + pkg.m2.impl.C2Impl.make(); + }} + """.trimIndent(), true) + } + + fun testPackageAccessibilityInModularTest() { + addTestFile("module-info.java", "module M { requires M2; requires M6; requires lib.named; requires lib.auto; }") + addFile("module-info.java", "module M2 { exports pkg.m2; exports pkg.m2.impl to close.friends.only; }", M2) + addFile("pkg/m2/C2.java", "package pkg.m2;\npublic class C2 { }", M2) + addFile("pkg/m2/impl/C2Impl.java", "package pkg.m2.impl;\nimport pkg.m2.C2;\npublic class C2Impl { public static C2 make() {} }", M2) + addFile("pkg/m4/C4.java", "package pkg.m4;\npublic class C4 { }", M4) + addFile("module-info.java", "module M5 { exports pkg.m5; }", M5) + addFile("pkg/m5/C5.java", "package pkg.m5;\npublic class C5 { }", M5) + addFile("module-info.java", "module M6 { requires transitive M7; }", M6) + addFile("module-info.java", "module M7 { exports pkg.m7; }", M7) + addFile("pkg/m7/C7.java", "package pkg.m7;\npublic class C7 { }", M7) + highlight("test.java", """ + import pkg.m2.C2; + import pkg.m2.*; + import pkg.m2.impl.C2Impl; + import pkg.m2.impl.*; + import pkg.m4.C4; + import pkg.m5.C5; + import pkg.m7.C7; + + import pkg.lib1.LC1; + import pkg.lib1.impl.LC1Impl; + import pkg.lib1.impl.*; + + import pkg.lib2.LC2; + import pkg.lib2.impl.LC2Impl; + + import static pkg.m2.impl.C2Impl.make; + + /** See also {@link C2Impl#make} */ + class C {{ + C2Impl.make(); + pkg.m2.impl.C2Impl.make(); + }} + """.trimIndent(), true) + } + fun testLinearModuleGraphBug() { addFile("module-info.java", "module M6 { requires M7; }", M6) addFile("module-info.java", "module M7 { }", M7) @@ -308,8 +382,8 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { // private fun highlight(text: String) = highlight("module-info.java", text) - private fun highlight(path: String, text: String) { - myFixture.configureFromExistingVirtualFile(addFile(path, text)) + private fun highlight(path: String, text: String, isTest: Boolean = false) { + myFixture.configureFromExistingVirtualFile(if (isTest) addTestFile(path, text) else addFile(path, text)) myFixture.checkHighlighting() }