diff --git a/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java index 669b9fda60c0..70e00f256207 100644 --- a/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java +++ b/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java @@ -155,13 +155,7 @@ public class RedundantCastUtil { if (!isApplicableForConditionalBranch(opType, ((PsiConditionalExpression)castOperand).getElseExpression())) return; } if (TypeConversionUtil.isAssignable(lType, opType, false)) { - if (castOperand instanceof PsiFunctionalExpression) { - final PsiTypeElement typeElement = ((PsiTypeCastExpression)rExpr).getCastType(); - final PsiType castType = typeElement != null ? typeElement.getType() : null; - if (!lType.equals(castType)) { - return; - } - } + if (!isFunctionalExpressionTypePreserved((PsiTypeCastExpression)rExpr, castOperand, lType)) return; addToResults((PsiTypeCastExpression)rExpr); } } @@ -169,6 +163,17 @@ public class RedundantCastUtil { } } + private static boolean isFunctionalExpressionTypePreserved(PsiTypeCastExpression typeCast, + PsiExpression castOperand, + @NotNull PsiType lType) { + if (castOperand instanceof PsiFunctionalExpression) { + final PsiTypeElement typeElement = typeCast.getCastType(); + final PsiType castType = typeElement != null ? typeElement.getType() : null; + return lType.equals(castType); + } + return true; + } + @Override public void visitPolyadicExpression(PsiPolyadicExpression expression) { class Processor { @@ -406,7 +411,7 @@ public class RedundantCastUtil { PsiExpression returnExpression = deparenthesizeExpression(expressions.get(returnExprIdx)); final PsiExpression newReturnExpression = deparenthesizeExpression(newReturnExpressions.get(returnExprIdx)); if (newReturnExpression instanceof PsiTypeCastExpression) { - checkLambdaReturn(i, returnExpression, (PsiTypeCastExpression)newReturnExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); + checkLambdaReturn(i, (PsiTypeCastExpression)returnExpression, (PsiTypeCastExpression)newReturnExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); } else if (returnExpression instanceof PsiConditionalExpression) { LOG.assertTrue(newReturnExpression instanceof PsiConditionalExpression); @@ -421,12 +426,12 @@ public class RedundantCastUtil { if (thenExpression instanceof PsiTypeCastExpression && !castForBoxing(getInnerMostOperand(thenExpression), elseExpression != null ? elseExpression.getType() : null, returnExpression.getType())) { - checkLambdaReturn(i, thenExpression, (PsiTypeCastExpression)newThenExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); + checkLambdaReturn(i, (PsiTypeCastExpression)thenExpression, (PsiTypeCastExpression)newThenExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); } if (elseExpression instanceof PsiTypeCastExpression && !castForBoxing(getInnerMostOperand(elseExpression), thenExpression != null ? thenExpression.getType() : null, returnExpression.getType())) { - checkLambdaReturn(i, elseExpression, (PsiTypeCastExpression)newElseExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); + checkLambdaReturn(i, (PsiTypeCastExpression)elseExpression, (PsiTypeCastExpression)newElseExpression, interfaceType, newLambdaExpression, oldCall, newCall, parameters); } } } @@ -434,23 +439,25 @@ public class RedundantCastUtil { } private void checkLambdaReturn(int i, - PsiExpression returnExpression, + PsiTypeCastExpression returnExpression, PsiTypeCastExpression newReturnExpression, PsiType originalFunctionalInterfaceType, PsiLambdaExpression newLambdaExpression, PsiCall oldCall, PsiCall newCall, PsiParameter[] parameters) { - PsiExpression castOperand = getInnerMostOperand(newReturnExpression); + PsiExpression castOperand = getInnerMostOperand(returnExpression); if (castOperand == null) return; + final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(originalFunctionalInterfaceType); + if (interfaceReturnType == null || + !isFunctionalExpressionTypePreserved(returnExpression, castOperand, interfaceReturnType)) return; PsiExpression strippedCast = (PsiExpression)newReturnExpression.replace(castOperand); PsiType newArgType = calculateNewArgType(i, resolveNewResult(oldCall, newCall), parameters); final PsiType functionalInterfaceType = newLambdaExpression.getGroundTargetType(newArgType); if (originalFunctionalInterfaceType.equals(functionalInterfaceType)) { - final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(originalFunctionalInterfaceType); final PsiType castExprType = LambdaUtil.performWithTargetType(newLambdaExpression, functionalInterfaceType, () -> strippedCast.getType()); - if (interfaceReturnType != null && castExprType != null && interfaceReturnType.isAssignableFrom(castExprType)) { - addToResults((PsiTypeCastExpression)returnExpression); + if (castExprType != null && interfaceReturnType.isAssignableFrom(castExprType)) { + addToResults(returnExpression); return; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/LambdaReturnChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/LambdaReturnChain.java new file mode 100644 index 000000000000..e65f8a966b49 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/LambdaReturnChain.java @@ -0,0 +1,15 @@ + +import java.util.Collection; +import java.util.function.Consumer; +import java.util.function.Function; + +abstract class NestedLambda { + abstract V[] map2Array(Collection collection, Class aClass, Function mapper); + + void m(Collection methods) { + Object[] r = map2Array(methods, Consumer.class, method -> (Consumer) resolveResult -> { + int i = resolveResult.intValue(); + }); + Object[] r1 = map2Array(methods, Consumer.class, method -> (Consumer) resolveResult -> { }); + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaRedundantCastTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaRedundantCastTest.java index 09462afa2ff2..0455091ee3d7 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaRedundantCastTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/LambdaRedundantCastTest.java @@ -96,9 +96,8 @@ public class LambdaRedundantCastTest extends LightDaemonAnalyzerTestCase { public void testInvalidConditional() { doTest(); } - public void testSuperBoundLambda() { - doTest(); - } + public void testSuperBoundLambda() { doTest(); } + public void testLambdaReturnChain() { doTest(); } private void doTest() { doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, false);