From 719c49ea6e0f31cfa0183592ef9846751f536406 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 19 Jan 2017 20:32:08 +0100 Subject: [PATCH] IG: report "Overly strong type cast" when cast is necessary for method call --- .../OverlyStrongTypeCastInspection.java | 12 ++++----- .../siyeh/ig/psiutils/MethodCallUtils.java | 26 ++++++++++++++++++- .../OverlyStrongTypeCast.java | 10 ++++--- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java index 4c7da771eee7..942decad9b83 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java @@ -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)) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java index 67dfffd8e77b..24deaaeb7662 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java @@ -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()); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/overly_strong_type_cast/OverlyStrongTypeCast.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/overly_strong_type_cast/OverlyStrongTypeCast.java index f1698ce5f7b5..7d1d5cb78222 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/overly_strong_type_cast/OverlyStrongTypeCast.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/overly_strong_type_cast/OverlyStrongTypeCast.java @@ -6,13 +6,17 @@ import java.util.ArrayList; import java.util.List; - - - interface TestInter{} public class OverlyStrongTypeCast { + void g() { + f((Number) null); + } + void f(char[] cs) {} + void f(String n) {} + void f(Object o) {} + void iterate(Object o) { for (Object object : (ArrayList) o) {} for (String s : (ArrayList) o) {}