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 d708e921e5dc..ab2b3b81cd8c 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 @@ -735,7 +735,7 @@ public class HighlightClassUtil { // must be inner class if (!PsiUtil.isInnerClass(base)) return; - if (resolve == resolved && baseClass != null && + if (resolve == resolved && baseClass != null && !PsiTreeUtil.isAncestor(baseClass, extendRef, true) && !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); @@ -811,11 +811,9 @@ public class HighlightClassUtil { } @Nullable - public static HighlightInfo checkCreateInnerClassFromStaticContext(PsiElement element, @Nullable PsiExpression qualifier, PsiClass aClass) { - if (!PsiUtil.isInnerClass(aClass)) return null; - PsiClass outerClass = aClass.getContainingClass(); - if (outerClass == null) return null; - + public static HighlightInfo checkCreateInnerClassFromStaticContext(PsiElement element, + @Nullable PsiExpression qualifier, + PsiClass aClass) { PsiElement placeToSearchEnclosingFrom; if (qualifier != null) { PsiType qType = qualifier.getType(); @@ -824,6 +822,16 @@ public class HighlightClassUtil { else { placeToSearchEnclosingFrom = element; } + return checkCreateInnerClassFromStaticContext(element, placeToSearchEnclosingFrom, aClass); + } + + @Nullable + public static HighlightInfo checkCreateInnerClassFromStaticContext(PsiElement element, + PsiElement placeToSearchEnclosingFrom, + PsiClass aClass) { + if (aClass == null || !PsiUtil.isInnerClass(aClass)) return null; + PsiClass outerClass = aClass.getContainingClass(); + if (outerClass == null) return null; if (outerClass instanceof JspClass || hasEnclosingInstanceInScope(outerClass, placeToSearchEnclosingFrom, true)) return null; return reportIllegalEnclosingUsage(placeToSearchEnclosingFrom, aClass, outerClass, element); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index d9c90b1acd5c..d9df710b84b7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -901,6 +901,17 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh highlightReferencedMethodOrClassName(ref, resolved); } + if (!myHolder.hasErrorResults() && resolved instanceof PsiClass) { + final PsiClass aClass = ((PsiClass)resolved).getContainingClass(); + if (aClass != null) { + final PsiElement qualifier = ref.getQualifier(); + final PsiElement place = qualifier instanceof PsiJavaCodeReferenceElement ? ((PsiJavaCodeReferenceElement)qualifier).resolve() : ref; + if (PsiTreeUtil.isAncestor(aClass, place, false) && aClass.hasTypeParameters()) { + myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(ref, place, (PsiClass)resolved)); + } + } + } + return result; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InstanceClassInStaticContextAccess.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InstanceClassInStaticContextAccess.java new file mode 100644 index 000000000000..32e725e7f2cc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InstanceClassInStaticContextAccess.java @@ -0,0 +1,50 @@ +class MyTest { + + class A { + } + + //not an error in java 8?! + static class CA> { + } + + static A> void bar() { + } + + static class B { + { + B.<A>bar(); + A a; + } + + static A> void bar() { + } + + void v(C<A> c) { + } + } +} + +class MyTest1 { + + class A { + } + + static class C> { + } + + static > void bar() { + } + + static class B { + { + B.bar(); + A a = new A(); + } + + static > void bar() { + } + + void v(C> c) { + } + } +} 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 60683c9a9398..a03ad78e5e57 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -201,6 +201,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testInferenceWithBoxingCovariant() throws Exception { doTest17Incompatibility(false); } public void testSuperWildcardIsNotWithinItsBound() throws Exception { doTest17Incompatibility(false); } public void testSpecificReturnType() throws Exception { doTest17Incompatibility(false); } + public void testInstanceClassInStaticContextAccess() throws Exception { doTest17Incompatibility(false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));