diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index e3298e65cf01..fba9855a7229 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -28,15 +28,20 @@ import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class JavaResolveUtil { - public static PsiClass getContextClass(PsiElement element) { + public static PsiClass getContextClass(@NotNull PsiElement element) { + PsiElement prev = element; PsiElement scope = element.getContext(); while (scope != null) { - if (scope instanceof PsiClass) return (PsiClass)scope; + if (scope instanceof PsiClass && (prev instanceof PsiMember || prev instanceof PsiDocComment)) { + return (PsiClass)scope; + } + prev = scope; scope = scope.getContext(); } return null; @@ -110,15 +115,19 @@ public class JavaResolveUtil { if (memberClass == null) { return false; } - for (PsiElement placeParent = place; placeParent != null; placeParent = placeParent.getContext()) { - if (placeParent instanceof PsiClass && InheritanceUtil.isInheritorOrSelf((PsiClass)placeParent, memberClass, true)) { + PsiClass contextClass = member instanceof PsiClass ? getContextClass(place) + : PsiTreeUtil.getContextOfType(place, PsiClass.class, false); + while (contextClass != null) { + if (InheritanceUtil.isInheritorOrSelf(contextClass, memberClass, true)) { if (member instanceof PsiClass || modifierList.hasModifierProperty(PsiModifier.STATIC) || accessObjectClass == null || - InheritanceUtil.isInheritorOrSelf(accessObjectClass, (PsiClass)placeParent, true)) { + InheritanceUtil.isInheritorOrSelf(accessObjectClass, contextClass, true)) { return true; } } + + contextClass = getContextClass(contextClass); } return false; } diff --git a/java/java-tests/testData/psi/resolve/class/QualifiedAnonymousClass.java b/java/java-tests/testData/psi/resolve/class/QualifiedAnonymousClass.java new file mode 100644 index 000000000000..83bb3663f21c --- /dev/null +++ b/java/java-tests/testData/psi/resolve/class/QualifiedAnonymousClass.java @@ -0,0 +1,8 @@ +import foo.Outer; + +class Foo { + { + new Outer.Inner() { }; + } +} + diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java index 62cc6930434c..8a7bcb1d0e29 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveClassTest.java @@ -16,11 +16,13 @@ package com.intellij.psi.resolve; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.util.RecursionManager; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packageDependencies.DependenciesBuilder; @@ -226,6 +228,18 @@ public class ResolveClassTest extends ResolveTestCase { PlatformTestUtil.assertTiming("exponent?", 20000, System.currentTimeMillis() - start); } + public void testQualifiedAnonymousClass() throws Exception { + RecursionManager.assertOnRecursionPrevention(myTestRootDisposable); + + PsiReference ref = configure(); + VirtualFile file = ref.getElement().getContainingFile().getVirtualFile(); + assertNotNull(file); + VirtualFile pkg = WriteAction.compute(() -> file.getParent().createChildDirectory(this, "foo")); + createFile(myModule, pkg, "Outer.java", "package foo; public class Outer { protected static class Inner { protected Inner() {} } }"); + + assertEquals("Inner", assertInstanceOf(ref.resolve(), PsiClass.class).getName()); + } + @SuppressWarnings({"ConstantConditions"}) private void configureDependency() { ApplicationManager.getApplication().runWriteAction(new Runnable() { diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java index 78eb4760d4ce..983efed50466 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java @@ -1,6 +1,7 @@ package com.intellij.psi.resolve; import com.intellij.navigation.NavigationItem; +import com.intellij.openapi.util.RecursionManager; import com.intellij.psi.*; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.PsiTreeUtil; @@ -242,6 +243,8 @@ public class ResolveMethod15Test extends Resolve15TestCase { assertTrue(!((PsiMethod) element).isVarArgs()); } public void testFilterFixedVsVarargs9() throws Exception { + RecursionManager.assertOnRecursionPrevention(myTestRootDisposable); + final PsiReference ref = configureByFile(); assertThat(ref, instanceOf(PsiReferenceExpression.class)); final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref; @@ -485,6 +488,8 @@ public class ResolveMethod15Test extends Resolve15TestCase { } public void testInheritance4() throws Exception{ + RecursionManager.assertOnRecursionPrevention(myTestRootDisposable); + PsiReference ref = configureByFile(); PsiElement target = ref.resolve(); assertThat(target, instanceOf(PsiMethod.class));