From 6e9234b11504108ce0d2cb9c6af12b54321fc703 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 24 Feb 2016 17:05:16 +0100 Subject: [PATCH] redundant casts: don't treat cast as redundant if functional expression get more specific type (IDEA-152093) --- .../intellij/psi/util/RedundantCastUtil.java | 33 ++++++++++--------- .../AnotherInterfaceMethodIsPointed.java | 4 +-- .../lambda/redundantCast/Ser.java | 2 +- .../redundantCast/SerializableLambda.java | 2 +- .../afterCodeBlockLambda.java | 2 +- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java index e5faabb02e03..1ab3b1ea3ffa 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java @@ -224,6 +224,11 @@ public class RedundantCastUtil { final PsiExpression nestedCastOperand = ((PsiTypeCastExpression)castOperand).getOperand(); operandType = nestedCastOperand != null ? nestedCastOperand.getType() : null; } + else if (castOperand instanceof PsiFunctionalExpression && lType != null) { + final PsiTypeElement typeElement = ((PsiTypeCastExpression)rExpr).getCastType(); + final PsiType castType = typeElement != null ? typeElement.getType() : null; + operandType = lType.equals(castType) ? castOperand.getType() : null; + } else { operandType = castOperand.getType(); } @@ -354,32 +359,30 @@ public class RedundantCastUtil { LOG.assertTrue(argList != null); PsiExpression[] newArgs = argList.getExpressions(); PsiTypeCastExpression castExpression = (PsiTypeCastExpression) deparenthesizeExpression(newArgs[i]); + final PsiTypeElement castTypeElement = cast.getCastType(); + final PsiType castType = castTypeElement != null ? castTypeElement.getType() : null; PsiExpression castOperand = castExpression.getOperand(); if (castOperand == null) return; - final PsiMethod oldFunctionalInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(castOperand); newArgs[i] = (PsiExpression)castExpression.replace(castOperand); + final JavaResolveResult newResult; if (newCall instanceof PsiEnumConstant) { // do this manually, because PsiEnumConstantImpl.resolveMethodGenerics() will assert (no containing class for the copy) final PsiEnumConstant enumConstant = (PsiEnumConstant)expression; PsiClass containingClass = enumConstant.getContainingClass(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(enumConstant.getProject()); final PsiClassType type = facade.getElementFactory().createType(containingClass); - final JavaResolveResult newResult = facade.getResolveHelper().resolveConstructor(type, newCall.getArgumentList(), enumConstant); - if (oldMethod.equals(newResult.getElement()) && newResult.isValidResult()) { + newResult = facade.getResolveHelper().resolveConstructor(type, newCall.getArgumentList(), enumConstant); + } + else { + newResult = newCall.resolveMethodGenerics(); + } + + if (oldMethod.equals(newResult.getElement()) && + Comparing.equal(((PsiCallExpression)newCall).getType(), ((PsiCallExpression)expression).getType()) && + newResult.isValidResult()) { + if (!(newArgs[i] instanceof PsiFunctionalExpression) || castType != null && castType.equals(((PsiFunctionalExpression)newArgs[i]).getFunctionalInterfaceType())) { addToResults(cast); } - } else { - final JavaResolveResult newResult = newCall.resolveMethodGenerics(); - if (oldMethod.equals(newResult.getElement()) && - Comparing.equal(((PsiCallExpression)newCall).getType(), ((PsiCallExpression)expression).getType()) && - newResult.isValidResult()) { - final PsiMethod newFunctionalInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(newArgs[i]); - if (oldFunctionalInterfaceMethod == null || - newFunctionalInterfaceMethod != null && (newFunctionalInterfaceMethod == oldFunctionalInterfaceMethod || - MethodSignatureUtil.isSuperMethod(newFunctionalInterfaceMethod, oldFunctionalInterfaceMethod))) { - addToResults(cast); - } - } } } else if (arg instanceof PsiLambdaExpression) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/AnotherInterfaceMethodIsPointed.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/AnotherInterfaceMethodIsPointed.java index 5f87258e550a..1ae6cf53b38b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/AnotherInterfaceMethodIsPointed.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/AnotherInterfaceMethodIsPointed.java @@ -20,7 +20,7 @@ class Test { public static void main(String[] args) { List strings = Arrays.asList("a", "b", "c"); strings.forEach((IoFunction) arg -> {throw new IOException();}); - strings.forEach((IFunction) arg -> {}); - strings.forEach((IIFunction) arg -> {}); + strings.forEach((IFunction) arg -> {}); + strings.forEach((IIFunction) arg -> {}); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/Ser.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/Ser.java index c4b4bef165e8..8265cc8bb2db 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/Ser.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/Ser.java @@ -15,6 +15,6 @@ class Test { { Predicate mh2 = (SerPredicate)Test::test; - Predicate mh02 = (NonSerPredicate)Test::test; + Predicate mh02 = (NonSerPredicate)Test::test; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/SerializableLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/SerializableLambda.java index cba0a1b73b73..b47c0bcdad1c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/SerializableLambda.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/redundantCast/SerializableLambda.java @@ -6,7 +6,7 @@ class Test { public static void main(String[] args) { Runnable r = (Runnable & Serializable) (() -> {}); r = (Runnable & Serializable)() -> {}; - r = (Runnable & I)() -> {}; + r = (Runnable & I)() -> {}; System.out.println(r); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCodeBlockLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCodeBlockLambda.java index e6e17aa84e79..bc5066843e13 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCodeBlockLambda.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterCodeBlockLambda.java @@ -1,7 +1,7 @@ // "Replace with lambda" "true" class A { { - bar(() -> foo()); + bar((ThrowableComputable) () -> foo()); } private void bar(ThrowableComputable throwableComputable) {}