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 f26cf534f6c0..170e6a8e5d2d 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 @@ -152,11 +152,14 @@ public class JavaModuleGraphUtil { } public boolean reads(PsiJavaModule source, PsiJavaModule destination) { - Iterator directReaders = myGraph.getOut(destination); - while (directReaders.hasNext()) { - PsiJavaModule next = directReaders.next(); - if (source.equals(next) || myPublicEdges.contains(key(destination, next)) && reads(source, next)) { - return true; + Collection nodes = myGraph.getNodes(); + if (nodes.contains(destination) && nodes.contains(source)) { + Iterator directReaders = myGraph.getOut(destination); + while (directReaders.hasNext()) { + PsiJavaModule next = directReaders.next(); + if (source.equals(next) || myPublicEdges.contains(key(destination, next)) && reads(source, next)) { + return true; + } } } return false; 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 f268eefe3391..6ee5c450a1bb 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 @@ -55,16 +55,13 @@ import static com.intellij.psi.SyntaxTraverser.psiTraverser; public class ModuleHighlightUtil { @Nullable - static PsiJavaModule getModuleDescriptor(@NotNull PsiElement element) { - VirtualFile file = Optional.of(element) - .map(e -> e instanceof PsiFileSystemItem ? (PsiFileSystemItem)e : e.getContainingFile()) - .map(PsiFileSystemItem::getVirtualFile) - .orElse(null); + static PsiJavaModule getModuleDescriptor(@NotNull PsiFileSystemItem fsItem) { + VirtualFile file = fsItem.getVirtualFile(); if (file == null) return null; - Project project = element.getProject(); + Project project = fsItem.getProject(); ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project); - if (element instanceof PsiCompiledElement) { + if (index.isInLibraryClasses(file)) { return Optional.ofNullable(index.getClassRootForFile(file)) .map(r -> r.findChild(PsiJavaModule.MODULE_INFO_CLS_FILE)) .map(PsiManager.getInstance(project)::findFile) @@ -96,7 +93,7 @@ public class ModuleHighlightUtil { @Nullable static HighlightInfo checkFileDuplicates(@NotNull PsiJavaModule element, @NotNull PsiFile file) { - Module module = ModuleUtilCore.findModuleForPsiElement(element); + Module module = findModule(file); if (module != null) { Project project = file.getProject(); Collection others = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, module.getModuleScope(false)); @@ -173,12 +170,12 @@ public class ModuleHighlightUtil { } } - Module host = ModuleUtilCore.findModuleForPsiElement(module); + Module host = findModule(module); for (PsiProvidesStatement statement : psiTraverser().children(module).filter(PsiProvidesStatement.class)) { PsiJavaCodeReferenceElement ref = statement.getInterfaceReference(); if (ref != null) { PsiElement target = ref.resolve(); - if (target instanceof PsiClass && ModuleUtilCore.findModuleForPsiElement(target) == host) { + if (target instanceof PsiClass && findModule(target) == host) { String className = refText(ref), packageName = StringUtil.getPackageName(className); if (!exports.contains(packageName) && !uses.contains(className)) { String message = JavaErrorMessages.message("module.service.unused"); @@ -243,7 +240,7 @@ public class ModuleHighlightUtil { if (refElement != null) { PsiElement target = refElement.resolve(); if (target instanceof PsiPackage) { - Module module = ModuleUtilCore.findModuleForPsiElement(refElement); + Module module = findModule(refElement); if (module != null) { String packageName = ((PsiPackage)target).getQualifiedName(); PsiDirectory[] directories = ((PsiPackage)target).getDirectories(module.getModuleScope(false)); @@ -339,12 +336,12 @@ public class ModuleHighlightUtil { static HighlightInfo checkPackageAccessibility(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiElement target, @NotNull PsiJavaModule refModule) { - Module module = ModuleUtilCore.findModuleForPsiElement(ref); + Module module = findModule(refModule); if (module != null) { - if (target instanceof PsiClass && !(target instanceof PsiCompiledElement) && module != ModuleUtilCore.findModuleForPsiElement(target)) { + if (target instanceof PsiClass) { PsiElement targetFile = target.getParent(); if (targetFile instanceof PsiClassOwner) { - PsiJavaModule targetModule = getModuleDescriptor(target); + PsiJavaModule targetModule = getModuleDescriptor((PsiFileSystemItem)targetFile); String packageName = ((PsiClassOwner)targetFile).getPackageName(); return checkPackageAccessibility(ref, refModule, targetModule, packageName); } @@ -353,7 +350,7 @@ public class ModuleHighlightUtil { PsiElement refImport = ref.getParent(); if (refImport instanceof PsiImportStatementBase && ((PsiImportStatementBase)refImport).isOnDemand()) { PsiDirectory[] dirs = ((PsiPackage)target).getDirectories(module.getModuleWithDependenciesAndLibrariesScope(false)); - if (dirs.length == 1 && ModuleUtilCore.findModuleForPsiElement(dirs[0]) != module) { + if (dirs.length == 1) { PsiJavaModule targetModule = getModuleDescriptor(dirs[0]); String packageName = ((PsiPackage)target).getQualifiedName(); return checkPackageAccessibility(ref, refModule, targetModule, packageName); @@ -369,26 +366,35 @@ public class ModuleHighlightUtil { PsiJavaModule refModule, PsiJavaModule targetModule, String packageName) { - if (targetModule == null) { - String message = JavaErrorMessages.message("module.package.on.classpath"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); - } + if (!refModule.equals(targetModule)) { + if (targetModule == null) { + String message = JavaErrorMessages.message("module.package.on.classpath"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); + } - String refModuleName = refModule.getModuleName(); - String requiredName = targetModule.getModuleName(); - if (!(targetModule instanceof PsiCompiledElement) && !JavaModuleGraphUtil.exports(targetModule, packageName, refModule)) { - String message = JavaErrorMessages.message("module.package.not.exported", requiredName, packageName, refModuleName); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); - } + String refModuleName = refModule.getModuleName(); + String requiredName = targetModule.getModuleName(); + if (!JavaModuleGraphUtil.exports(targetModule, packageName, refModule)) { + String message = JavaErrorMessages.message("module.package.not.exported", requiredName, packageName, refModuleName); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); + } - if (!(PsiJavaModule.JAVA_BASE.equals(requiredName) || JavaModuleGraphUtil.reads(refModule, targetModule))) { - String message = JavaErrorMessages.message("module.not.in.requirements", refModuleName, requiredName); - return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); + if (!(PsiJavaModule.JAVA_BASE.equals(requiredName) || JavaModuleGraphUtil.reads(refModule, targetModule))) { + String message = JavaErrorMessages.message("module.not.in.requirements", refModuleName, requiredName); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).description(message).create(); + } } return null; } + private static Module findModule(PsiElement element) { + return Optional.ofNullable(element.getContainingFile()) + .map(PsiFile::getVirtualFile) + .map(f -> ModuleUtilCore.findModuleForFile(f, element.getProject())) + .orElse(null); + } + private static HighlightInfo moduleResolveError(PsiJavaModuleReferenceElement refElement, PsiPolyVariantReference ref) { boolean missing = ref.multiResolve(true).length == 0; String message = JavaErrorMessages.message(missing ? "module.not.found" : "module.not.on.path", refElement.getReferenceText()); diff --git a/java/java-tests/testData/codeInsight/jigsaw/lib1.jar b/java/java-tests/testData/codeInsight/jigsaw/lib1.jar new file mode 100644 index 000000000000..f719fc6306be Binary files /dev/null and b/java/java-tests/testData/codeInsight/jigsaw/lib1.jar differ 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 05d8b4117228..292ebf115985 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt @@ -134,7 +134,7 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { } fun testPackageAccessibility() { - addFile("module-info.java", "module M { requires M2; requires M6; }") + addFile("module-info.java", "module M { requires M2; requires M6; requires LIB1; }") 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) @@ -154,6 +154,10 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { import pkg.m5.C5; import pkg.m7.C7; + import pkg.lib1.LC1; + import pkg.lib1.impl.LC1Impl; + import pkg.lib1.impl.*; + import static pkg.m2.impl.C2Impl.make; class C { } diff --git a/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt b/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt index cdc211e11e3c..f29828fc4d91 100644 --- a/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt +++ b/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt @@ -15,6 +15,7 @@ */ package com.intellij.testFramework.fixtures +import com.intellij.openapi.application.ex.PathManagerEx import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager @@ -49,6 +50,7 @@ object MultiModuleJava9ProjectDescriptor : DefaultLightProjectDescriptor() { override fun setUpProject(project: Project, handler: SetupHandler) { super.setUpProject(project, handler) + runWriteAction { val main = ModuleManager.getInstance(project).findModuleByName(TEST_MODULE_NAME)!! @@ -68,6 +70,9 @@ object MultiModuleJava9ProjectDescriptor : DefaultLightProjectDescriptor() { val m7 = makeModule(project, ModuleDescriptor.M7) ModuleRootModificationUtil.addDependency(m6, m7, DependencyScope.COMPILE, true) + + val libDir = "jar://${PathManagerEx.getTestDataPath()}/codeInsight/jigsaw/" + ModuleRootModificationUtil.addModuleLibrary(main, libDir + "lib1.jar!/") } }