From 36bc7c3c64875b4b862ad8a5c734ce75c1693da1 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 5 Feb 2026 15:44:15 +0100 Subject: [PATCH] IDEA-384922 [java-highlighting] Required transitive dependency is not highlighted GitOrigin-RevId: 3e80edab97d215b7a0d32b23c96cfcdfa6723476 --- .../highlighting/FunctionChecker.java | 9 ++++ .../MultipleModuleHighlightingTest.java | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/FunctionChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/FunctionChecker.java index 3d7ce04df820..ae084966dce9 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/FunctionChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/FunctionChecker.java @@ -5,6 +5,7 @@ import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError; import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds; import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext; import com.intellij.lang.jvm.JvmModifier; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.JavaResolveResult; import com.intellij.psi.LambdaUtil; import com.intellij.psi.PsiCall; @@ -14,6 +15,7 @@ import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiExpressionList; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFunctionalExpression; import com.intellij.psi.PsiIntersectionType; import com.intellij.psi.PsiJavaCodeReferenceElement; @@ -418,6 +420,7 @@ final class FunctionChecker { PsiUtil.resolveGenericsClassInType(PsiClassImplUtil.correctType(functionalInterfaceType, expression.getResolveScope())); PsiClass psiClass = resolveResult.getElement(); if (psiClass == null) return; + PsiFile file = psiClass.getContainingFile(); if (!PsiUtil.isAccessible(myVisitor.project(), psiClass, expression, null)) { myVisitor.myModifierChecker.reportAccessProblem(expression, psiClass, resolveResult); return; @@ -448,5 +451,11 @@ final class FunctionChecker { } myVisitor.myModuleChecker.checkModuleAccess(psiClass, expression); + if (!myVisitor.hasErrorResults()) { + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile != null && !expression.getResolveScope().contains(virtualFile)) { + myVisitor.report(JavaErrorKinds.CLASS_NOT_ACCESSIBLE.create(expression, psiClass)); + } + } } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/MultipleModuleHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/MultipleModuleHighlightingTest.java index 456024774873..cc3a9d0bc655 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/MultipleModuleHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/MultipleModuleHighlightingTest.java @@ -5,13 +5,17 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; import com.intellij.openapi.module.JavaModuleType; import com.intellij.openapi.module.Module; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.roots.ModuleSourceOrderEntry; import com.intellij.openapi.roots.OrderEntry; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; @@ -52,6 +56,51 @@ public class MultipleModuleHighlightingTest extends JavaCodeInsightFixtureTestCa myFixture.checkHighlighting(); } + @Override + protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception { + moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_8); + moduleBuilder.addJdk(IdeaTestUtil.getMockJdk18Path().getPath()); + } + + public void testMissedTransitiveDepFunctionalInterface() throws IOException { + Sdk sdk = ModuleRootManager.getInstance(getModule()).getSdk(); + Module mod1 = + PsiTestUtil.addModule(getProject(), JavaModuleType.getModuleType(), "mod1", myFixture.getTempDirFixture().findOrCreateDir("mod1")); + Module mod2 = + PsiTestUtil.addModule(getProject(), JavaModuleType.getModuleType(), "mod2", myFixture.getTempDirFixture().findOrCreateDir("mod2")); + Module mod3 = + PsiTestUtil.addModule(getProject(), JavaModuleType.getModuleType(), "mod3", myFixture.getTempDirFixture().findOrCreateDir("mod3")); + ModuleRootModificationUtil.setModuleSdk(mod1, sdk); + ModuleRootModificationUtil.setModuleSdk(mod2, sdk); + ModuleRootModificationUtil.setModuleSdk(mod3, sdk); + ModuleRootModificationUtil.addDependency(mod2, mod1); + ModuleRootModificationUtil.addDependency(mod3, mod2); + myFixture.addFileToProject("mod1/M1.java", "public class M1 {}"); + myFixture.addFileToProject("mod2/M2.java", """ + import java.util.function.Supplier; + + public class M2 { + public static void test(Supplier supplier) { + System.out.println(supplier.get()); + } + + public static M1Sub create() { + return new M1Sub(); + } + + public static class M1Sub extends M1 {} + } + """); + PsiFile file = myFixture.addFileToProject("mod3/M3.java", """ + public class M3 { + public static void main(String[] args) { + M2.test(M2::create); + } + }"""); + myFixture.configureFromExistingVirtualFile(PsiUtilCore.getVirtualFile(file)); + IdeaTestUtil.withLevel(mod3, LanguageLevel.JDK_1_8, myFixture::checkHighlighting); + } + public void testMissedMethodInHierarchy() throws IOException { Module mod1 = PsiTestUtil.addModule(getProject(), JavaModuleType.getModuleType(), "mod1", myFixture.getTempDirFixture().findOrCreateDir("mod1"));