diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 9bf9b9fb0553..8642e2462d2f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -285,7 +285,9 @@ public final class PsiClassImplUtil { PsiClass containingClass = aClass.getContainingClass(); if (aClass.hasModifierProperty(PsiModifier.PUBLIC) || aClass.hasModifierProperty(PsiModifier.PROTECTED)) { - return containingClass == null ? maximalUseScope : containingClass.getUseScope(); + // If the containing class is not final, it's possible to expose nested class through public subclass of containing class + return containingClass == null || !containingClass.hasModifierProperty(PsiModifier.FINAL) ? + maximalUseScope : containingClass.getUseScope(); } else if (aClass.hasModifierProperty(PsiModifier.PRIVATE) || aClass instanceof PsiTypeParameter) { PsiClass topClass = PsiUtil.getTopLevelClass(aClass); diff --git a/java/java-tests/testSrc/com/intellij/java/psi/search/ClassInheritorsTest.java b/java/java-tests/testSrc/com/intellij/java/psi/search/ClassInheritorsTest.java index 3eee6e9bc342..3bb6e9a83f6d 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/search/ClassInheritorsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/search/ClassInheritorsTest.java @@ -114,6 +114,25 @@ public class ClassInheritorsTest extends JavaCodeInsightFixtureTestCase { assertSize(5, ClassInheritorsSearch.search(myFixture.findClass("one.Test.A")).findAll()); assertSize(4, ClassInheritorsSearch.search(myFixture.findClass("one.Test.B")).findAll()); } + + public void testClassExposedViaContainingClassSubclass() { + myFixture.addClass(""" + package one; + interface OuterSuper { + interface Inner {} + } + """); + myFixture.addClass(""" + package one; + public interface Child extends OuterSuper { + } + """); + myFixture.addClass(""" + package two; + interface InnerChild extends one.Child.Inner {} + """); + assertSize(1, ClassInheritorsSearch.search(myFixture.findClass("one.OuterSuper.Inner")).findAll()); + } public void testInheritorsInAnotherModuleWithNoDirectDependency() throws IOException { myFixture.addFileToProject("A.java", "class A {}");