From 10c8616d19908b867692559987ea9e92cdea3cf8 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 4 Oct 2016 15:31:06 +0700 Subject: [PATCH] StreamAPI migration: propose to use any/all/noneMatch if next return is not true/false (using || or &&) --- .../streamMigration/ReplaceWithMatchFix.java | 11 +++++++-- .../StreamApiMigrationInspection.java | 23 ++++++++++--------- .../afterAllMatchChain.java | 9 ++++++++ .../afterAnyMatchChain.java | 9 ++++++++ .../beforeAllMatchChain.java | 15 ++++++++++++ 5 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchChain.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchChain.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchChain.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithMatchFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithMatchFix.java index 28c06350f19f..d2a482e78190 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithMatchFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/streamMigration/ReplaceWithMatchFix.java @@ -23,6 +23,7 @@ import com.intellij.psi.*; import com.siyeh.ig.psiutils.BoolUtils; import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.ParenthesesUtils; import org.jetbrains.annotations.NotNull; /** @@ -57,13 +58,19 @@ class ReplaceWithMatchFix extends MigrateToStreamFix { if (ExpressionUtils.isLiteral(value, Boolean.TRUE) || ExpressionUtils.isLiteral(value, Boolean.FALSE)) { boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue(); PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(foreachStatement); - if (nextReturnStatement != null && ExpressionUtils.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) { + if (nextReturnStatement != null) { + PsiExpression returnValue = nextReturnStatement.getReturnValue(); + if(returnValue == null) return null; String methodName = foundResult ? "anyMatch" : "noneMatch"; String streamText = generateStream(iteratedValue, tb.getLastOperation()).toString(); streamText = addTerminalOperation(streamText, methodName, foreachStatement, tb); restoreComments(foreachStatement, body); if (nextReturnStatement.getParent() == foreachStatement.getParent()) { - nextReturnStatement.delete(); + if(!ExpressionUtils.isLiteral(returnValue, !foundResult)) { + streamText+= (foundResult ? "||" : "&&") + ParenthesesUtils.getText(returnValue, ParenthesesUtils.AND_PRECEDENCE); + } + removeLoop(foreachStatement); + return returnValue.replace(elementFactory.createExpressionFromText(streamText, nextReturnStatement)); } return foreachStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", foreachStatement)); } 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 21ae392ea9e1..f791192355b0 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 @@ -596,18 +596,19 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo if (nextReturnStatement != null && (ExpressionUtils.isLiteral(value, Boolean.TRUE) || ExpressionUtils.isLiteral(value, Boolean.FALSE))) { boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue(); - if(ExpressionUtils.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) { - String methodName; - if (foundResult) { - methodName = "anyMatch"; - } - else { - methodName = "noneMatch"; - Operation lastOp = tb.getLastOperation(); - if(lastOp instanceof FilterOp && (((FilterOp)lastOp).isNegated() ^ BoolUtils.isNegation(lastOp.getExpression()))) { - methodName = "allMatch"; - } + String methodName; + if (foundResult) { + methodName = "anyMatch"; + } + else { + methodName = "noneMatch"; + Operation lastOp = tb.getLastOperation(); + if(lastOp instanceof FilterOp && (((FilterOp)lastOp).isNegated() ^ BoolUtils.isNegation(lastOp.getExpression()))) { + methodName = "allMatch"; } + } + if(nextReturnStatement.getParent() == statement.getParent() || + ExpressionUtils.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) { registerProblem(statement, methodName, new ReplaceWithMatchFix(methodName)); return; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchChain.java new file mode 100644 index 000000000000..02032cf255be --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAllMatchChain.java @@ -0,0 +1,9 @@ +// "Replace with allMatch()" "true" + +import java.util.List; + +public class Main { + boolean find(List data, boolean other, boolean third) { + return data.stream().map(String::trim).allMatch(trimmed -> trimmed.startsWith("xyz")) && (other || third); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchChain.java new file mode 100644 index 000000000000..d5b9da7efdac --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchChain.java @@ -0,0 +1,9 @@ +// "Replace with anyMatch()" "true" + +import java.util.List; + +public class Main { + boolean find(List data, boolean other, boolean third) { + return data.stream().map(String::trim).anyMatch(trimmed -> trimmed.startsWith("xyz")) || (other || third); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchChain.java new file mode 100644 index 000000000000..e824a129ba98 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAllMatchChain.java @@ -0,0 +1,15 @@ +// "Replace with allMatch()" "true" + +import java.util.List; + +public class Main { + boolean find(List data, boolean other, boolean third) { + for(String e : data) { + String trimmed = e.trim(); + if(!trimmed.startsWith("xyz")) { + return false; + } + } + return other || third; + } +}