From e9e7ce005dac03c88439a1cfc76556f1c06287e4 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 3 May 2013 16:15:28 +0200 Subject: [PATCH] forbid casting to nested wildcards (IDEA-71007) --- .../intellij/psi/util/TypeConversionUtil.java | 11 +++++-- .../psi/util/TypesDistinctProver.java | 3 +- .../DisableCastingToNestedWildcards.java | 32 +++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 4 +++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DisableCastingToNestedWildcards.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 672a01334f47..9cce64d95310 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -325,7 +325,7 @@ public class TypeConversionUtil { PsiClass[] supers = derived.getSupers(); if (manager.areElementsEquivalent(base, derived)) { derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor); - return areSameArgumentTypes(derived, baseResult.getSubstitutor(), derivedSubstitutor); + return areSameArgumentTypes(derived, baseResult.getSubstitutor(), derivedSubstitutor, 1); } else if (base.isInheritor(derived, true)) { derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor); @@ -355,11 +355,18 @@ public class TypeConversionUtil { } private static boolean areSameArgumentTypes(PsiClass aClass, PsiSubstitutor substitutor1, PsiSubstitutor substitutor2) { + return areSameArgumentTypes(aClass, substitutor1, substitutor2, 0); + } + + private static boolean areSameArgumentTypes(PsiClass aClass, + PsiSubstitutor substitutor1, + PsiSubstitutor substitutor2, + int level) { for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) { PsiType typeArg1 = substitutor1.substitute(typeParameter); PsiType typeArg2 = substitutor2.substitute(typeParameter); if (typeArg1 == null || typeArg2 == null) return true; - if (TypesDistinctProver.provablyDistinct(typeArg1, typeArg2)) return false; + if (TypesDistinctProver.provablyDistinct(typeArg1, typeArg2, level)) return false; final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 5d2c6aab7467..04bd3481bf27 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -35,7 +35,7 @@ public class TypesDistinctProver { return provablyDistinct(type1, type2, 0); } - private static boolean provablyDistinct(PsiType type1, PsiType type2, int level) { + protected static boolean provablyDistinct(PsiType type1, PsiType type2, int level) { if (type1 instanceof PsiClassType && ((PsiClassType)type1).resolve() instanceof PsiTypeParameter) return false; if (type2 instanceof PsiClassType && ((PsiClassType)type2).resolve() instanceof PsiTypeParameter) return false; if (type1 instanceof PsiWildcardType) { @@ -43,6 +43,7 @@ public class TypesDistinctProver { return provablyDistinct((PsiWildcardType)type1, (PsiWildcardType)type2); } + if (level > 1) return true; if (type2 instanceof PsiCapturedWildcardType) { return ((PsiWildcardType)type1).isExtends() && level > 0 || provablyDistinct((PsiWildcardType)type1, ((PsiCapturedWildcardType)type2).getWildcard()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DisableCastingToNestedWildcards.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DisableCastingToNestedWildcards.java new file mode 100644 index 000000000000..9c076abce2ac --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/DisableCastingToNestedWildcards.java @@ -0,0 +1,32 @@ +import java.util.List; + +public class Test { + + interface P { + + } + + public abstract class AP implements P { + + } + + public class AP1 extends AP { + + } + + public class AP2 extends AP { + + } + + private static final List> AP_LIST = listOf(AP1.class); + + + private static List listOf(T... ts) { + return null; + } + + public static void test() { + List> apList1 = (List>) AP_LIST; + List> apList2 = (List>) AP_LIST; + } +} 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 de9a8363ca8e..2012ad3e4463 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -239,6 +239,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testDisableCastingToNestedWildcards() throws Exception { + doTest5(false); + } + public void testBooleanInferenceFromIfCondition() throws Exception { doTest5(false); }