diff --git a/java/java-impl/src/com/intellij/codeInspection/streamToLoop/TerminalOperation.java b/java/java-impl/src/com/intellij/codeInspection/streamToLoop/TerminalOperation.java index 6070e931218e..679b8dbb4bd8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/streamToLoop/TerminalOperation.java +++ b/java/java-impl/src/com/intellij/codeInspection/streamToLoop/TerminalOperation.java @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.siyeh.ig.psiutils.BoolUtils; +import com.siyeh.ig.psiutils.ParenthesesUtils; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -707,7 +708,9 @@ abstract class TerminalOperation extends Operation { String comparePredicate; if(myComparator != null) { myComparator.transform(context, inVar.getName(), best); - comparePredicate = myTemplate.replace("{comparator}", myComparator.getText()); + PsiExpression expression = myComparator.getExpression(); + String text = ParenthesesUtils.areParenthesesNeeded(JavaTokenType.GT, expression) ? "("+expression.getText()+")" : expression.getText(); + comparePredicate = myTemplate.replace("{comparator}", text); } else { comparePredicate = myTemplate.replace("{best}", best).replace("{item}", inVar.getName()); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/afterMaxLambdaTernary.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/afterMaxLambdaTernary.java new file mode 100644 index 000000000000..75583f622149 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/afterMaxLambdaTernary.java @@ -0,0 +1,17 @@ +// "Replace Stream API chain with loop" "true" + +import java.util.*; + +public class Main { + private static Optional max(Map> dependencies, String fruits, Map weights) { + boolean seen = false; + String best = null; + for (String s : dependencies.get(fruits)) { + if (!seen || (s.compareTo(best) < 0 ? -1 : s.compareTo(best) > 0 ? 1 : 0) > 0) { + seen = true; + best = s; + } + } + return seen ? Optional.of(best) : Optional.empty(); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/beforeMaxLambdaTernary.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/beforeMaxLambdaTernary.java new file mode 100644 index 000000000000..7c3f53e0c370 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamToLoop/beforeMaxLambdaTernary.java @@ -0,0 +1,9 @@ +// "Replace Stream API chain with loop" "true" + +import java.util.*; + +public class Main { + private static Optional max(Map> dependencies, String fruits, Map weights) { + return dependencies.get(fruits).stream().max((o1, o2) -> o1.compareTo(o2) < 0 ? -1 : o1.compareTo(o2) > 0 ? 1 : 0); + } +} diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java index c9b5fea6b39b..a69ca8c5d875 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java @@ -18,6 +18,7 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -554,11 +555,16 @@ public class ParenthesesUtils { return parentPrecedence < childPrecedence; } + @Contract("_, null -> false") public static boolean areParenthesesNeeded(PsiJavaToken sign, PsiExpression rhs) { + return areParenthesesNeeded(sign.getTokenType(), rhs); + } + + @Contract("_, null -> false") + public static boolean areParenthesesNeeded(IElementType signTokenType, PsiExpression rhs) { if (rhs instanceof PsiPolyadicExpression) { final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression)rhs; final int precedence1 = getPrecedenceForOperator(binaryExpression.getOperationTokenType()); - final IElementType signTokenType = sign.getTokenType(); final IElementType newOperatorToken = tokenMap.get(signTokenType); final int precedence2 = getPrecedenceForOperator(newOperatorToken); return precedence1 >= precedence2 || !isCommutativeOperator(newOperatorToken);