From 4916734a249b27fbde0361c8323f580ec4e0cec7 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 14 Oct 2015 13:20:17 +0200 Subject: [PATCH] reifiable type check fixed for local classes; instanceof check to use the same algorithm (IDEA-146352; IDEA-146351) --- .../impl/analysis/GenericsHighlightUtil.java | 40 +++++-------------- .../impl/analysis/JavaGenericsUtil.java | 24 +++++------ .../ReifiableTypeWithLocalClasses.java | 13 ++++++ .../daemon/GenericsHighlightingTest.java | 4 ++ 4 files changed, 40 insertions(+), 41 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index eedfee025b03..333b633b7ac1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -841,41 +841,23 @@ public class GenericsHighlightUtil { static HighlightInfo checkInstanceOfGenericType(PsiInstanceOfExpression expression) { final PsiTypeElement checkTypeElement = expression.getCheckType(); if (checkTypeElement == null) return null; - PsiElement ref = checkTypeElement.getInnermostComponentReferenceElement(); - while (ref instanceof PsiJavaCodeReferenceElement) { - final HighlightInfo result = isIllegalForInstanceOf((PsiJavaCodeReferenceElement)ref, checkTypeElement); - if (result != null) return result; - ref = ((PsiQualifiedReference)ref).getQualifier(); - } - return null; + return isIllegalForInstanceOf(checkTypeElement.getType(), checkTypeElement); } - private static HighlightInfo isIllegalForInstanceOf(PsiJavaCodeReferenceElement ref, final PsiTypeElement typeElement) { - final PsiElement resolved = ref.resolve(); + /** + * 15.20.2 Type Comparison Operator instanceof + * ReferenceType mentioned after the instanceof operator is reifiable + */ + private static HighlightInfo isIllegalForInstanceOf(PsiType type, final PsiTypeElement typeElement) { + final PsiClass resolved = PsiUtil.resolveClassInClassTypeOnly(type); if (resolved instanceof PsiTypeParameter) { String description = JavaErrorMessages.message("generics.cannot.instanceof.type.parameters"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).create(); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } - if (resolved instanceof PsiClass) { - final PsiClass containingClass = ((PsiClass)resolved).getContainingClass(); - if (containingClass != null && - ref.getQualifier() == null && - containingClass.getTypeParameters().length > 0 && - !((PsiClass)resolved).hasModifierProperty(PsiModifier.STATIC) && - ((PsiClass)resolved).getTypeParameters().length == 0) { - String description = JavaErrorMessages.message("illegal.generic.type.for.instanceof"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); - } - } - - final PsiType[] parameters = ref.getTypeParameters(); - for (PsiType parameterType : parameters) { - if (parameterType != null && - !(parameterType instanceof PsiWildcardType && ((PsiWildcardType)parameterType).getBound() == null)) { - String description = JavaErrorMessages.message("illegal.generic.type.for.instanceof"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); - } + if (!JavaGenericsUtil.isReifiableType(type)) { + String description = JavaErrorMessages.message("illegal.generic.type.for.instanceof"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } return null; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java index 465b2a7f8031..87fe026926c0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java @@ -20,6 +20,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; @@ -56,22 +57,21 @@ public class JavaGenericsUtil { } return true; } - final PsiClass resolved = ((PsiClassType)PsiUtil.convertAnonymousToBaseType(classType)).resolve(); - if (resolved instanceof PsiTypeParameter) { + + assert parameters.length == 0; + final PsiClassType.ClassResolveResult resolved = ((PsiClassType)PsiUtil.convertAnonymousToBaseType(classType)).resolveGenerics(); + final PsiClass aClass = resolved.getElement(); + if (aClass instanceof PsiTypeParameter) { return false; } - if (parameters.length == 0) { - if (resolved != null && !resolved.hasModifierProperty(PsiModifier.STATIC)) { - final PsiClass containingClass = resolved.getContainingClass(); - if (containingClass != null) { - final PsiTypeParameter[] containingClassTypeParameters = containingClass.getTypeParameters(); - if (containingClassTypeParameters.length > 0) { - return false; - } - } + + if (aClass != null && !aClass.hasModifierProperty(PsiModifier.STATIC)) { + PsiClass containingClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true); + if (containingClass != null) { + return isReifiableType(JavaPsiFacade.getElementFactory(aClass.getProject()).createType(containingClass, resolved.getSubstitutor())); } - return true; } + return true; } return false; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java new file mode 100644 index 000000000000..d87c6caebaf1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ReifiableTypeWithLocalClasses.java @@ -0,0 +1,13 @@ +class B { + + Object[] foo(Object obj) { + class C {} + return new C[0]; + } + + + boolean foo1(Object obj) { + class C {} + return obj instanceof C; + } +} \ No newline at end of file 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 ec833f93673d..dba68689d646 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -532,6 +532,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testReifiableTypeWithLocalClasses() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass);