From 0fe652059e8427e5ce65fa2cda38e7297416eff2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Jan 2017 14:17:15 +0300 Subject: [PATCH] reifiable types: skip anonymous types through the tree hierarchy as they can't be generic (IDEA-166840) --- .../impl/analysis/JavaGenericsUtil.java | 13 ++++++-- .../ReifiableTypeWithLocalClasses.java | 32 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java index ffa701452179..552e5784d319 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java @@ -59,16 +59,25 @@ public class JavaGenericsUtil { } assert parameters.length == 0; - final PsiClassType.ClassResolveResult resolved = ((PsiClassType)PsiUtil.convertAnonymousToBaseType(classType)).resolveGenerics(); + final PsiClassType.ClassResolveResult resolved = classType.resolveGenerics(); final PsiClass aClass = resolved.getElement(); if (aClass instanceof PsiTypeParameter) { return false; } if (aClass != null && !aClass.hasModifierProperty(PsiModifier.STATIC)) { - PsiModifierListOwner enclosingStaticElement = PsiUtil.getEnclosingStaticElement(aClass, aClass.getContainingClass()); + //local class (inner inside inside anonymous) should skip anonymous as it can't be static itself + final PsiClass stopClassLevel = PsiUtil.isLocalClass(aClass) ? null : aClass.getContainingClass(); + PsiModifierListOwner enclosingStaticElement = PsiUtil.getEnclosingStaticElement(aClass, stopClassLevel); PsiClass containingClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true); if (containingClass != null && (enclosingStaticElement == null || PsiTreeUtil.isAncestor(enclosingStaticElement, containingClass, false))) { + //anonymous classes are not generic + while (containingClass instanceof PsiAnonymousClass) { + containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class, true); + } + if (containingClass == null || enclosingStaticElement != null && !PsiTreeUtil.isAncestor(enclosingStaticElement, containingClass, false)) { + return true; + } return isReifiableType(JavaPsiFacade.getElementFactory(aClass.getProject()).createType(containingClass, resolved.getSubstitutor())); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java index a65a22de7773..080b09df3178 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java @@ -21,4 +21,36 @@ class B { return new C(); } + + static interface I {} + void anonymousClassWithLocal() { + I i = new I() { + class InsideAnno {} + { + InsideAnno[] array = new InsideAnno[1]; + } + }; + } + + static void staticAnonymousClassWithLocal() { + I i = new I() { + class InsideAnno {} + { + InsideAnno[] array = new InsideAnno[1]; + } + }; + } + + static void staticAnonymousClassWithGenericLocal() { + I i = new I() { + + class InsideAnno { + class O {} + + { + O[] array = new O[1]; + } + } + }; + } } \ No newline at end of file