redundant casts: skip casts in conditional branches of calls when resulted call would resolve to another method (IDEA-15720)

This commit is contained in:
anna
2011-09-01 18:00:52 +02:00
parent 6b411756ea
commit 4fddb0a5c8
4 changed files with 65 additions and 3 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>A.java</file>
<line>4</line>
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Redundant type cast</problem_class>
<description>Casting &lt;code&gt;param&lt;/code&gt; to &lt;code&gt;Object&lt;/code&gt; is redundant</description>
</problem>
</problems>

View File

@@ -0,0 +1,10 @@
class A {
void add(Object o, String param) {
add(o, o != null ? null : (Object) param);
add(o, o == null ? new Object() : (Object) param);
}
void add(Object o, Object param) {
}
}

View File

@@ -91,4 +91,6 @@ public class RedundantCastTest extends InspectionTestCase {
public void testNestedCast() throws Exception { doTest(); }
public void testPrimitiveInsideSynchronized() throws Exception { doTest(); }
public void testInConditionalPreserveResolve() throws Exception { doTest();}
}

View File

@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -349,9 +350,12 @@ public class RedundantCastUtil {
else {
PsiElement parent = typeCast.getParent();
if (parent instanceof PsiConditionalExpression) {
if (!PsiUtil.isLanguageLevel5OrHigher(typeCast)) {
//branches need to be of the same type
if (!Comparing.equal(operand.getType(), ((PsiConditionalExpression)parent).getType())) return;
//branches need to be of the same type
if (!Comparing.equal(operand.getType(), ((PsiConditionalExpression)parent).getType())) {
if (!PsiUtil.isLanguageLevel5OrHigher(typeCast)) {
return;
}
if (!checkResolveAfterRemoveCast(parent)) return;
}
} else if (parent instanceof PsiSynchronizedStatement && (expr instanceof PsiExpression && ((PsiExpression)expr).getType() instanceof PsiPrimitiveType)) {
return;
@@ -361,6 +365,43 @@ public class RedundantCastUtil {
super.visitTypeCastExpression(typeCast);
}
private static boolean checkResolveAfterRemoveCast(PsiElement parent) {
PsiElement grandPa = parent.getParent();
if (grandPa instanceof PsiExpressionList) {
PsiExpression[] expressions = ((PsiExpressionList)grandPa).getExpressions();
int idx = ArrayUtil.find(expressions, parent);
PsiElement grandGrandPa = grandPa.getParent();
if (grandGrandPa instanceof PsiCall) {
PsiElement resolve = ((PsiCall)grandGrandPa).resolveMethod();
if (resolve instanceof PsiMethod) {
PsiCall expression = (PsiCall)grandGrandPa.copy();
PsiExpressionList argumentList = expression.getArgumentList();
LOG.assertTrue(argumentList != null);
PsiExpression toReplace = argumentList.getExpressions()[idx];
if (toReplace instanceof PsiConditionalExpression) {
PsiExpression thenExpression = ((PsiConditionalExpression)toReplace).getThenExpression();
PsiExpression elseExpression = ((PsiConditionalExpression)toReplace).getElseExpression();
if (thenExpression instanceof PsiTypeCastExpression) {
final PsiExpression thenOperand = ((PsiTypeCastExpression)thenExpression).getOperand();
if (thenOperand != null) {
thenExpression.replace(thenOperand);
}
} else if (elseExpression instanceof PsiTypeCastExpression) {
final PsiExpression elseOperand = ((PsiTypeCastExpression)elseExpression).getOperand();
if (elseOperand != null) {
elseExpression.replace(elseOperand);
}
}
}
if (expression.resolveMethod() != resolve) {
return false;
}
}
}
}
return true;
}
private void processAlreadyHasTypeCast(PsiTypeCastExpression typeCast){
PsiElement parent = typeCast.getParent();
while(parent instanceof PsiParenthesizedExpression) parent = parent.getParent();