good code red: do not allow unchecked conversions on deeper wildcard levels (IDEA-80386)

This commit is contained in:
anna
2012-04-03 19:19:44 +02:00
parent 6719c86450
commit a4e23d3546
4 changed files with 67 additions and 2 deletions
@@ -880,10 +880,10 @@ public class TypeConversionUtil {
}
else {
if (leftWildcard.isExtends()) {
return isAssignable(leftBound, typeRight, allowUncheckedConversion);
return isAssignable(leftBound, typeRight, allowUncheckedConversion && !leftBound.accept(new WildcardDetector()));
}
else { // isSuper
return isAssignable(typeRight, leftBound, allowUncheckedConversion);
return isAssignable(typeRight, leftBound, allowUncheckedConversion && !leftBound.accept(new WildcardDetector()));
}
}
}
@@ -1676,4 +1676,34 @@ public class TypeConversionUtil {
return WRAPPER_TO_PRIMITIVE.get(o.getClass());
}
private static class WildcardDetector extends PsiTypeVisitor<Boolean> {
@Override
public Boolean visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) {
return true;
}
@Override
public Boolean visitWildcardType(PsiWildcardType wildcardType) {
return true;
}
@Override
public Boolean visitClassType(PsiClassType classType) {
final PsiType[] parameters = classType.getParameters();
for (PsiType parameter : parameters) {
if (parameter.accept(this)) return true;
}
return super.visitClassType(classType);
}
@Override
public Boolean visitArrayType(PsiArrayType arrayType) {
return arrayType.getComponentType().accept(this);
}
@Override
public Boolean visitType(PsiType type) {
return false;
}
}
}
@@ -2,6 +2,7 @@ class Test {
static {
Class<Test> testClass = get(Test.class);
foo(testClass);
Test f = foo(testClass);
}
static <E> Class<E> get(Class<? super E> value) {
@@ -0,0 +1,33 @@
import java.util.List;
public class IDEA80386 {
void foo(Class<List> listClass) {
<error descr="Incompatible types. Found: 'java.lang.Class<java.util.List>', required: 'java.lang.Class<? extends java.util.List<?>>'">Class<? extends List<?>> cls = listClass;</error>
Class < ?extends List > cls1 = listClass;
<error descr="Incompatible types. Found: 'java.lang.Class<java.util.List>', required: 'java.lang.Class<? extends java.util.List<? extends java.util.List<?>>>'">Class<? extends List<? extends List<?>>> cls2 = listClass;</error>
Class<? super List<?>> clsS = listClass;
Class<? super List> clsS1 = listClass;
}
void fooE(Class<? extends List> listClass) {
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends java.util.List>>', required: 'java.lang.Class<? extends java.util.List<?>>'">Class<? extends List<?>> cls = listClass;</error>
Class<? extends List> cls1 = listClass;
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends java.util.List>>', required: 'java.lang.Class<? extends java.util.List<? extends java.util.List<?>>>'">Class<? extends List<? extends List<?>>> cls2 = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends java.util.List>>', required: 'java.lang.Class<? super java.util.List<?>>'">Class<? super List<?>> clsS = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? extends java.util.List>>', required: 'java.lang.Class<? super java.util.List>'">Class<? super List> clsS1 = listClass;</error>
}
void fooS(Class<? super List> listClass) {
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? super java.util.List>>', required: 'java.lang.Class<? extends java.util.List<?>>'">Class<? extends List<?>> cls1 = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<? super java.util.List>>', required: 'java.lang.Class<? extends java.util.List<? extends java.util.List<?>>>'">Class<? extends List<? extends List<?>>> cls2 = listClass;</error>
Class<? super List<?>> clsS = listClass;
Class<? super List> clsS1 = listClass;
}
void fooU(Class<?> listClass) {
<error descr="Incompatible types. Found: 'java.lang.Class<capture<?>>', required: 'java.lang.Class<? extends java.util.List<?>>'">Class<? extends List<?>> cls1 = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<?>>', required: 'java.lang.Class<? extends java.util.List<? extends java.util.List<?>>>'">Class<? extends List<? extends List<?>>> cls2 = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<?>>', required: 'java.lang.Class<? super java.util.List<?>>'">Class<? super List<?>> clsS = listClass;</error>
<error descr="Incompatible types. Found: 'java.lang.Class<capture<?>>', required: 'java.lang.Class<? super java.util.List>'">Class<? super List> clsS1 = listClass;</error>
}
}
@@ -121,6 +121,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testUncheckedWarningsLevel6() throws Exception { doTest(true);}
public void testIDEA77991() throws Exception { doTest(false);}
public void testIDEA80386() throws Exception { doTest(false);}
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));