IG: report "Overly strong type cast" when cast is necessary for method call

This commit is contained in:
Bas Leijdekkers
2017-01-20 11:45:49 +01:00
parent d7c3c84c78
commit 719c49ea6e
3 changed files with 37 additions and 11 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.InstanceOfUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -117,18 +118,15 @@ public class OverlyStrongTypeCastInspection extends BaseInspection {
return;
}
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true);
if (expectedType == null) {
return;
}
if (expectedType.equals(type)) {
if (expectedType == null || expectedType.equals(type)) {
return;
}
final PsiClass resolved = PsiUtil.resolveClassInType(expectedType);
if (resolved != null && !resolved.isPhysical()) {
return;
}
if (expectedType.isAssignableFrom(operandType)) {
//then it's redundant, and caught by the built-in inspection
if (expectedType.isAssignableFrom(operandType) && !MethodCallUtils.isNecessaryForSurroundingMethodCall(expression, operand)) {
//then it's redundant, and caught by the "Redundant type cast" inspection
return;
}
if (TypeUtils.isTypeParameter(expectedType)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -286,6 +286,30 @@ public class MethodCallUtils {
return copy.resolveMethod();
}
/**
* Checks if the specified expression is an argument for any method call (skipping parentheses in between).
* If the method call is found, checks if same method is called when argument is replaced with replacement.
* @param expression the expression to check
* @param replacement the replacement to replace expression with
* @return true, if method was found and a different method was called with replacement. false, otherwise.
*/
public static boolean isNecessaryForSurroundingMethodCall(PsiExpression expression, PsiExpression replacement) {
PsiElement parent = expression.getParent();
while (parent instanceof PsiParenthesizedExpression) {
expression = (PsiExpression)parent;
parent = parent.getParent();
}
if (!(parent instanceof PsiExpressionList)) {
return false;
}
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiCall)) {
return false;
}
final PsiCall call = (PsiCall)grandParent;
return call.resolveMethod() != findMethodWithReplacedArgument(call, expression, replacement);
}
public static boolean isSuperMethodCall(@NotNull PsiMethodCallExpression expression, @NotNull PsiMethod method) {
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final PsiExpression target = ParenthesesUtils.stripParentheses(methodExpression.getQualifierExpression());
@@ -6,13 +6,17 @@ import java.util.ArrayList;
import java.util.List;
interface TestInter{}
public class OverlyStrongTypeCast
{
void g() {
f((<warning descr="Cast to 'Number' can be weakened to 'Object'">Number</warning>) null);
}
void f(char[] cs) {}
void f(String n) {}
void f(Object o) {}
void iterate(Object o) {
for (Object object : (<warning descr="Cast to 'ArrayList' can be weakened to 'Iterable'">ArrayList</warning>) o) {}
for (String s : (<warning descr="Cast to 'ArrayList<String>' can be weakened to 'Iterable<String>'">ArrayList<String></warning>) o) {}