diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithFindFirstFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithFindFirstFix.java index 848a3089a6c8..079fef324296 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithFindFirstFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithFindFirstFix.java @@ -19,6 +19,7 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.siyeh.ig.psiutils.EquivalenceChecker; import com.siyeh.ig.psiutils.ExpressionUtils; import org.jetbrains.annotations.NotNull; @@ -103,6 +104,17 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix { return "(" + castType.getText() + ")" + stream + ".orElse(null)"; } } + if(StreamApiMigrationInspection.isLiteral(falseExpression, Boolean.FALSE) && PsiType.BOOLEAN.equals(trueExpression.getType())) { + return stream + ".filter(" + StreamApiMigrationInspection.createLambda(var, trueExpression) + ").isPresent()"; + } + if(trueExpression instanceof PsiConditionalExpression) { + PsiConditionalExpression condition = (PsiConditionalExpression)trueExpression; + if(EquivalenceChecker.getCanonicalPsiEquivalence().expressionsAreEquivalent(falseExpression, condition.getElseExpression())) { + return generateOptionalUnwrap( + stream + ".filter(" + StreamApiMigrationInspection.createLambda(var, condition.getCondition()) + ")", tb, + condition.getThenExpression(), falseExpression); + } + } stream += ".map(" + StreamApiMigrationInspection.createLambda(var, trueExpression) + ")"; } stream += ".orElse(" + falseExpression.getText() + ")"; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java index f9be7ffa1e4f..0df821c0f688 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java @@ -561,7 +561,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo methodName = "noneMatch"; if(!operations.isEmpty()) { Operation lastOp = operations.get(operations.size() - 1); - if(lastOp instanceof FilterOp && BoolUtils.isNegation(lastOp.getExpression())) { + if(lastOp instanceof FilterOp && (((FilterOp)lastOp).isNegated() ^ BoolUtils.isNegation(lastOp.getExpression()))) { methodName = "allMatch"; } } @@ -644,6 +644,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo myNegated = negated; } + public boolean isNegated() { + return myNegated; + } + @Override public String createReplacement(PsiElementFactory factory) { PsiExpression expression = diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchContinue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchContinue.java new file mode 100644 index 000000000000..c3855eff9095 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchContinue.java @@ -0,0 +1,9 @@ +// "Replace with allMatch()" "true" + +import java.util.Arrays; + +public class Main { + boolean find(String[][] data) { + return Arrays.stream(data).flatMap(Arrays::stream).allMatch(str -> str.startsWith("xyz")); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstBoolean.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstBoolean.java new file mode 100644 index 000000000000..ae42de1e2be7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstBoolean.java @@ -0,0 +1,13 @@ +// "Replace with findFirst()" "true" + +import java.util.Collection; +import java.util.List; + +public class Main { + public static boolean find(List> list) { + /* + Block comment + */ + return list.stream().flatMap(Collection::stream).filter(string -> string.startsWith("ABC")).findFirst().filter(string -> string.substring(3).equals("xyz")).isPresent(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstTernary.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstTernary.java new file mode 100644 index 000000000000..438a9f62fec3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFindFirstTernary.java @@ -0,0 +1,10 @@ +// "Replace with findFirst()" "true" + +import java.util.Collection; +import java.util.List; + +public class Main { + public static String find(List> list) { + return list.stream().flatMap(Collection::stream).filter(string -> string.startsWith("ABC")).findFirst().filter(string -> string.substring(3).equals("xyz")).map(String::trim).orElse(null); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNoneMatchContinue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNoneMatchContinue.java new file mode 100644 index 000000000000..baaccd8b931a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNoneMatchContinue.java @@ -0,0 +1,9 @@ +// "Replace with noneMatch()" "true" + +import java.util.Arrays; + +public class Main { + boolean find(String[][] data) { + return Arrays.stream(data).flatMap(Arrays::stream).noneMatch(str -> str.startsWith("xyz")); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchContinue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchContinue.java new file mode 100644 index 000000000000..0d3a8d993a6c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchContinue.java @@ -0,0 +1,13 @@ +// "Replace with allMatch()" "true" + +public class Main { + boolean find(String[][] data) { + for(String[] arr : data) { + for(String str : arr) { + if(str.startsWith("xyz")) continue; + return false; + } + } + return true; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstBoolean.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstBoolean.java new file mode 100644 index 000000000000..f8fd16a15826 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstBoolean.java @@ -0,0 +1,19 @@ +// "Replace with findFirst()" "true" + +import java.util.List; + +public class Main { + public static boolean find(List> list) { + for(List innerList : list) { + for(String string : innerList) { + if(string.startsWith("ABC")) { + return string.substring(3).equals("xyz"); + /* + Block comment + */ + } + } + } + return false; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstTernary.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstTernary.java new file mode 100644 index 000000000000..b10fbacf414f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFindFirstTernary.java @@ -0,0 +1,16 @@ +// "Replace with findFirst()" "true" + +import java.util.List; + +public class Main { + public static String find(List> list) { + for(List innerList : list) { + for(String string : innerList) { + if(string.startsWith("ABC")) { + return string.substring(3).equals("xyz") ? string.trim() : null; + } + } + } + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNoneMatchContinue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNoneMatchContinue.java new file mode 100644 index 000000000000..e93bf710e403 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNoneMatchContinue.java @@ -0,0 +1,13 @@ +// "Replace with noneMatch()" "true" + +public class Main { + boolean find(String[][] data) { + for(String[] arr : data) { + for(String str : arr) { + if(!str.startsWith("xyz")) continue; + return false; + } + } + return true; + } +}