distinct prover: distinguish types when type parameter has bounds (IDEA-118037)

This commit is contained in:
Anna Kozlova
2013-12-16 16:40:07 +04:00
parent 0d7a9088b5
commit a449241577
3 changed files with 37 additions and 2 deletions

View File

@@ -36,8 +36,6 @@ public class TypesDistinctProver {
}
protected static boolean provablyDistinct(PsiType type1, PsiType type2, int level) {
if (type1 instanceof PsiClassType && ((PsiClassType)type1).resolve() instanceof PsiTypeParameter && level < 2) return false;
if (type2 instanceof PsiClassType && ((PsiClassType)type2).resolve() instanceof PsiTypeParameter && level < 2) return false;
if (type1 instanceof PsiWildcardType) {
if (type2 instanceof PsiWildcardType) {
return provablyDistinct((PsiWildcardType)type1, (PsiWildcardType)type2, true);
@@ -119,11 +117,33 @@ public class TypesDistinctProver {
final PsiClass boundClass1 = classResolveResult1.getElement();
final PsiClass boundClass2 = classResolveResult2.getElement();
if (boundClass1 instanceof PsiTypeParameter && level < 2) {
if (!distinguishFromTypeParam((PsiTypeParameter)boundClass1, boundClass2, type1)) return false;
}
if (boundClass2 instanceof PsiTypeParameter && level < 2) {
if (!distinguishFromTypeParam((PsiTypeParameter)boundClass2, boundClass1, type2)) return false;
}
return type2 != null && type1 != null && !type1.equals(type2) &&
(!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) ||
!InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true));
}
private static boolean distinguishFromTypeParam(PsiTypeParameter typeParam, PsiClass boundClass, PsiType type1) {
final PsiClassType[] paramBounds = typeParam.getExtendsListTypes();
if (paramBounds.length == 0 && type1 instanceof PsiClassType) return false;
for (PsiClassType classType : paramBounds) {
final PsiClass paramBound = classType.resolve();
if (paramBound != null &&
(InheritanceUtil.isInheritorOrSelf(paramBound, boundClass, true) ||
InheritanceUtil.isInheritorOrSelf(boundClass, paramBound, true))) {
return false;
}
}
return true;
}
public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2, boolean rejectInconsistentRaw) {
if (type1.isSuper() && type2.isSuper()) return false;
if (type1.isExtends() && type2.isExtends()) {

View File

@@ -0,0 +1,14 @@
final class Test
{
class Foo
{
<T extends String> void foo(Class<T> clazz)
{
if (<error descr="Operator '==' cannot be applied to 'java.lang.Class<java.lang.Void>', 'java.lang.Class<T>'">Void.class == clazz</error>)
{
System.out.println("Yeah!");
}
}
}
}

View File

@@ -333,6 +333,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA113526() { doTest5(true); }
public void testIDEA116493() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testIDEA117827() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testIDEA118037() { 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()));