diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index cd09b455ece4..cad1c585f3ab 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -654,7 +654,7 @@ public class HighlightClassUtil { * @param extendRef points to the class in the extends list * @param resolved extendRef resolved */ - public static HighlightInfo checkClassExtendsForeignInnerClass(PsiJavaCodeReferenceElement extendRef, PsiElement resolved) { + public static HighlightInfo checkClassExtendsForeignInnerClass(final PsiJavaCodeReferenceElement extendRef, PsiElement resolved) { PsiElement parent = extendRef.getParent(); if (!(parent instanceof PsiReferenceList)) { return null; @@ -663,7 +663,7 @@ public class HighlightClassUtil { if (!(grand instanceof PsiClass)) { return null; } - PsiClass aClass = (PsiClass)grand; + final PsiClass aClass = (PsiClass)grand; if (aClass instanceof PsiTypeParameter) { return null; } @@ -673,17 +673,41 @@ public class HighlightClassUtil { if (!(resolved instanceof PsiClass)) { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, JavaErrorMessages.message("class.name.expected")); } - PsiClass base = (PsiClass)resolved; - // must be inner class - if (!PsiUtil.isInnerClass(base)) return null; - PsiClass baseClass = base.getContainingClass(); + final HighlightInfo[] infos = new HighlightInfo[1]; + extendRef.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitElement(PsiElement element) { + if (infos[0] != null) return; + super.visitElement(element); + } - if (!hasEnclosingInstanceInScope(baseClass, extendRef, true) && !qualifiedNewCalledInConstructors(aClass, baseClass)) { - String description = JavaErrorMessages.message("no.enclosing.instance.in.scope", HighlightUtil.formatClass(baseClass)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, description); - } + @Override + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + super.visitReferenceElement(reference); + final PsiElement resolve = reference.resolve(); + if (resolve instanceof PsiClass) { + final PsiClass base = (PsiClass)resolve; + final PsiClass baseClass = base.getContainingClass(); + if (baseClass != null && base.hasModifierProperty(PsiModifier.PRIVATE) && !PsiTreeUtil.isAncestor(baseClass, aClass, true)) { + String description = JavaErrorMessages.message("private.symbol", + HighlightUtil.formatClass(base), + HighlightUtil.formatClass(baseClass)); + infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, description); + return; + } - return null; + // must be inner class + if (!PsiUtil.isInnerClass(base)) return; + + if (!hasEnclosingInstanceInScope(baseClass, extendRef, true) && !qualifiedNewCalledInConstructors(aClass, baseClass)) { + String description = JavaErrorMessages.message("no.enclosing.instance.in.scope", HighlightUtil.formatClass(baseClass)); + infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, description); + } + } + } + }); + + return infos[0]; } private static boolean qualifiedNewCalledInConstructors(final PsiClass aClass, final PsiClass baseClass) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PrivateInnerClassRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PrivateInnerClassRef.java new file mode 100644 index 000000000000..53c5b5660dce --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/PrivateInnerClassRef.java @@ -0,0 +1,14 @@ +import java.util.Comparator; + +public abstract class A implements Comparator { + + private static class B { + } + + private interface I extends Comparator{} + private interface I1 extends Comparator{} +} + +//abstract class C implements error descr="'C.D' has private access in 'C'">C.D error { +// private static class D {} +//} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 0a352a05bab3..452ece2addbb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -102,6 +102,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testTypeWithinItsWildcardBound() throws Exception { doTest(false); } public void testMethodSignatureEquality() throws Exception { doTest(false); } public void testInnerClassRef() throws Exception { doTest(false); } + public void testPrivateInnerClassRef() throws Exception { doTest(false); } public void testJavaUtilCollections() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));