From 32fe2746f9e9f157c5426648cf7c14e5b26abebd Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 26 May 2014 14:10:22 +0400 Subject: [PATCH] stream api: do not collapse loops when body is not throws compatible (IDEA-125541) --- .../StreamApiMigrationInspection.java | 23 +++++++++++++++++-- .../beforeThrownCollect.java | 19 +++++++++++++++ .../beforeThrownExceptionsNotMatched.java | 17 ++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownCollect.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownExceptionsNotMatched.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java index f073953d0810..d04ef1bbb295 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java @@ -15,10 +15,12 @@ */ package com.intellij.codeInspection; +import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -27,6 +29,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.IntArrayList; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -160,7 +163,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo if (args.length == 1) { if (args[0] instanceof PsiCallExpression) { final PsiMethod method = ((PsiCallExpression)args[0]).resolveMethod(); - return method != null && !method.hasTypeParameters(); + return method != null && !method.hasTypeParameters() && !isThrowsCompatible(method); } return true; } @@ -222,7 +225,23 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo return false; } //method reference - return LambdaCanBeMethodReferenceInspection.canBeMethodReferenceProblem(body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : body, new PsiParameter[] {parameter}, null) == null; + final PsiCallExpression callExpression = LambdaCanBeMethodReferenceInspection + .canBeMethodReferenceProblem(body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : body, + new PsiParameter[]{parameter}, null); + if (callExpression == null) { + return true; + } + final PsiMethod method = callExpression.resolveMethod(); + return method != null && isThrowsCompatible(method); + } + + private static boolean isThrowsCompatible(PsiMethod method) { + return ContainerUtil.find(method.getThrowsList().getReferencedTypes(), new Condition() { + @Override + public boolean value(PsiClassType type) { + return !ExceptionUtil.isUncheckedException(type); + } + }) != null; } private static class ReplaceWithForeachCallFix implements LocalQuickFix { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownCollect.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownCollect.java new file mode 100644 index 000000000000..2b797ce1d667 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownCollect.java @@ -0,0 +1,19 @@ +// "Replace with collect" "false" +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class ForEachTest { + + interface A { + String ii() throws IOException; + } + private List reqs; + + public ForEachTest () throws IOException { + List result = new ArrayList<>(); + for(A val : reqs) { + result.add(val.ii()); + } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownExceptionsNotMatched.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownExceptionsNotMatched.java new file mode 100644 index 000000000000..82c83b6e6f80 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeThrownExceptionsNotMatched.java @@ -0,0 +1,17 @@ +// "Replace with forEach" "false" +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +class Test { + + private List reqs; + + public ForEachTest () throws IOException { + DataOutputStream req = new DataOutputStream(new ByteArrayOutputStream()); + for(byte[] val : reqs) { + req.write(val); + } + } +}