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 12f4143eaa95..f8b5e67dd8f8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java @@ -185,9 +185,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo PsiExpression value = returnStatement.getReturnValue(); if(isLiteral(value, Boolean.TRUE) || isLiteral(value, Boolean.FALSE)) { boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue(); - PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(statement, PsiWhiteSpace.class, PsiComment.class); - if(nextStatement instanceof PsiReturnStatement) { - PsiReturnStatement nextReturnStatement = (PsiReturnStatement)nextStatement; + PsiReturnStatement nextReturnStatement = getNextReturnStatement(statement); + if(nextReturnStatement != null) { if(isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) { String methodName; if (foundResult) { @@ -223,6 +222,22 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo }; } + @Nullable + static PsiReturnStatement getNextReturnStatement(PsiStatement statement) { + PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(statement, PsiWhiteSpace.class, PsiComment.class); + if(nextStatement instanceof PsiReturnStatement) return (PsiReturnStatement)nextStatement; + PsiElement parent = statement.getParent(); + if(parent instanceof PsiCodeBlock) { + PsiStatement[] statements = ((PsiCodeBlock)parent).getStatements(); + if(statements.length == 0 || statements[statements.length-1] != statement) return null; + parent = parent.getParent(); + if(!(parent instanceof PsiBlockStatement)) return null; + parent = parent.getParent(); + } + if(parent instanceof PsiIfStatement) return getNextReturnStatement((PsiStatement)parent); + return null; + } + @NotNull private TextRange getRange(PsiForeachStatement statement, boolean isOnTheFly) { boolean wholeStatement = false; @@ -894,10 +909,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo PsiExpression value = returnStatement.getReturnValue(); if(!isLiteral(value, Boolean.TRUE) && !isLiteral(value, Boolean.FALSE)) return; boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue(); - PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(foreachStatement, PsiWhiteSpace.class, PsiComment.class); - if(!(nextStatement instanceof PsiReturnStatement)) return; - PsiReturnStatement nextReturnStatement = (PsiReturnStatement)nextStatement; - if(!isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) return; + PsiReturnStatement nextReturnStatement = getNextReturnStatement(foreachStatement); + if (nextReturnStatement == null || !isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) return; String methodName = foundResult ? "anyMatch" : "noneMatch"; final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); String streamText = generateStream(iteratedValue, intermediateOps).toString(); @@ -930,8 +943,11 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } else { streamText += "."+methodName+"("+tb.getVariable().getName()+" -> true)"; } + boolean siblings = nextReturnStatement.getParent() == foreachStatement.getParent(); PsiElement result = foreachStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", foreachStatement)); - nextReturnStatement.delete(); + if(siblings) { + nextReturnStatement.delete(); + } simplifyAndFormat(project, result); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIf.java new file mode 100644 index 000000000000..97d3a3a91178 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIf.java @@ -0,0 +1,12 @@ +// "Replace with anyMatch()" "true" + +import java.util.Arrays; +import java.util.Objects; + +public class Main { + boolean contains(String[][] haystack, String needle) { + if(haystack != null) + return Arrays.stream(haystack).filter(Objects::nonNull).flatMap(Arrays::stream).anyMatch(needle::equals); + return false; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIfBlock.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIfBlock.java new file mode 100644 index 000000000000..23f900212a80 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterAnyMatchEnclosingIfBlock.java @@ -0,0 +1,13 @@ +// "Replace with anyMatch()" "true" + +import java.util.Arrays; +import java.util.Objects; + +public class Main { + boolean contains(String[][] haystack, String needle) { + if(haystack != null) { + return Arrays.stream(haystack).filter(Objects::nonNull).flatMap(Arrays::stream).anyMatch(needle::equals); + } + return false; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIf.java new file mode 100644 index 000000000000..74bbaa757069 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIf.java @@ -0,0 +1,15 @@ +// "Replace with anyMatch()" "true" + +public class Main { + boolean contains(String[][] haystack, String needle) { + if(haystack != null) + for (String[] row : haystack) { + if (row == null) continue; + for (String str : row) { + if (needle.equals(str)) + return true; + } + } + return false; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfBlock.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfBlock.java new file mode 100644 index 000000000000..70953dfce87b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfBlock.java @@ -0,0 +1,16 @@ +// "Replace with anyMatch()" "true" + +public class Main { + boolean contains(String[][] haystack, String needle) { + if(haystack != null) { + for (String[] row : haystack) { + if (row == null) continue; + for (String str : row) { + if (needle.equals(str)) + return true; + } + } + } + return false; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfInterrupted.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfInterrupted.java new file mode 100644 index 000000000000..cea665b8dab1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeAnyMatchEnclosingIfInterrupted.java @@ -0,0 +1,17 @@ +// "Replace with anyMatch()" "false" + +public class Main { + boolean contains(String[][] haystack, String needle) { + if(haystack != null) { + for (String[] row : haystack) { + if (row == null) continue; + for (String str : row) { + if (needle.equals(str)) + return true; + } + } + System.out.println("Oops"); + } + return false; + } +}