IDEA-111450 false positive for "Redundant type cast" inspection

This commit is contained in:
Mike Strobel
2013-09-12 21:43:10 +04:00
committed by Anna Kozlova
parent b816d2770e
commit fbc3d18f9e
3 changed files with 55 additions and 5 deletions
@@ -638,10 +638,21 @@ public class RedundantCastUtil {
}
private static boolean wrapperCastChangeSemantics(PsiExpression operand, PsiExpression otherOperand, PsiExpression toCast) {
boolean isPrimitiveComparisonWithCast = TypeConversionUtil.isPrimitiveAndNotNull(operand.getType()) ||
TypeConversionUtil.isPrimitiveAndNotNull(otherOperand.getType());
boolean isPrimitiveComparisonWithoutCast = TypeConversionUtil.isPrimitiveAndNotNull(toCast.getType()) ||
TypeConversionUtil.isPrimitiveAndNotNull(otherOperand.getType());
final boolean isPrimitiveComparisonWithCast;
final boolean isPrimitiveComparisonWithoutCast;
if (TypeConversionUtil.isPrimitiveAndNotNull(otherOperand.getType())) {
// IDEA-111450: A primitive comparison requires one primitive operand and one primitive or wrapper operand.
isPrimitiveComparisonWithCast = TypeConversionUtil.isPrimitiveAndNotNullOrWrapper(operand.getType());
isPrimitiveComparisonWithoutCast = TypeConversionUtil.isPrimitiveAndNotNullOrWrapper(toCast.getType());
}
else {
// We do not check whether `otherOperand` is a wrapper, because a reference-to-primitive cast has a
// side effect regardless of whether we end up doing a primitive or reference comparison.
isPrimitiveComparisonWithCast = TypeConversionUtil.isPrimitiveAndNotNull(operand.getType());
isPrimitiveComparisonWithoutCast = TypeConversionUtil.isPrimitiveAndNotNull(toCast.getType());
}
// wrapper casted to primitive vs wrapper comparison
return isPrimitiveComparisonWithCast != isPrimitiveComparisonWithoutCast;
}
@@ -673,4 +684,4 @@ public class RedundantCastUtil {
return method instanceof PsiMethod &&
AnnotationUtil.isAnnotated((PsiMethod)method, CommonClassNames.JAVA_LANG_INVOKE_MH_POLYMORPHIC, false, true);
}
}
}
@@ -0,0 +1,38 @@
import java.lang.Character;
import java.util.List;
public class Test {
public static void test() {
Character c1 = '1';
Character c2 = '2';
Object o = '3';
// A cast on either operand is required to force a primitive comparison; not redundant.
System.out.println((char) c1 == c2);
System.out.println(c1 == (char) c2);
// If one operand is a primitive, and the other is a wrapper, the wrapper need not be cast.
System.out.println((<warning descr="Casting 'c1' to 'char' is redundant">char</warning>) c1 == '*');
System.out.println('*' == (<warning descr="Casting 'c1' to 'char' is redundant">char</warning>) c1);
// The cast on the Object is required to force a primitive comparison; not redundant.
System.out.println((char) o == '*');
System.out.println('*' == (char) o);
// The cast on the Object is required to force a primitive comparison; not redundant.
System.out.println((Character) o == '*');
System.out.println('*' == (Character) o);
// The cast on the Object triggers an implicit unboxing of the wrapper; not redundant.
System.out.println((char) o == c1);
System.out.println(c1 == (char) o);
// A cast on the Object is required for a primitive comparison, but the wrapper cast is redundant.
System.out.println((char) o == (<warning descr="Casting 'c1' to 'char' is redundant">char</warning>) c1);
System.out.println((<warning descr="Casting 'c1' to 'char' is redundant">char</warning>) c1 == (char) o);
// Although a reference comparison, the cast on the wrapper has a side effect; not redundant.
System.out.println(o == (char) c1);
System.out.println((char) c1 == o);
}
}
@@ -179,4 +179,5 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testIDEA62056() { doTest(false, false); }
public void testIDEA78916() { doTest(false, false); }
public void testIDEA111420() { doTest(false, false); }
public void testIDEA111450() { doTest(true, false); }
}