reifiable type check fixed for local classes; instanceof check to use the same algorithm (IDEA-146352; IDEA-146351)

This commit is contained in:
Anna Kozlova
2015-10-14 17:05:36 +02:00
parent 6dc2a6c4dd
commit 4916734a24
4 changed files with 40 additions and 41 deletions
@@ -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;
@@ -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;
@@ -0,0 +1,13 @@
class B<T> {
Object[] foo(Object obj) {
class C {}
return <error descr="Generic array creation">new C[0]</error>;
}
boolean foo1(Object obj) {
class C {}
return obj instanceof <error descr="Illegal generic type for instanceof">C</error>;
}
}
@@ -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);