diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractIfConditionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractIfConditionAction.java index 2569fceadc81..51fce6820407 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractIfConditionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ExtractIfConditionAction.java @@ -4,6 +4,7 @@ package com.intellij.codeInsight.intention.impl; import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.PsiEquivalenceUtil; import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -13,11 +14,18 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiExpressionTrimRenderer; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.CommentTracker; +import com.siyeh.ig.psiutils.ControlFlowUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + +import static com.intellij.util.ObjectUtils.tryCast; + public class ExtractIfConditionAction extends PsiElementBaseIntentionAction { @Override public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { @@ -149,15 +157,39 @@ public class ExtractIfConditionAction extends PsiElementBaseIntentionAction { @NotNull PsiExpression extract, @NotNull PsiExpression leave, CommentTracker tracker) { - - return factory.createStatementFromText( - createIfString(extract, - createIfString(leave, thenBranch, elseBranch, tracker), - elseBranch, - tracker - ), - thenBranch - ); + List elseChain = new ArrayList<>(); + boolean chainFinished = false; + while (!chainFinished) { + PsiIfStatement nextIf = tryCast(ControlFlowUtils.stripBraces(elseBranch), PsiIfStatement.class); + if (nextIf == null) break; + PsiExpression nextCondition = PsiUtil.skipParenthesizedExprDown(nextIf.getCondition()); + if (nextCondition == null) break; + if (PsiEquivalenceUtil.areElementsEquivalent(extract, nextCondition) && nextIf.getThenBranch() != null) { + elseChain.add(nextIf.getThenBranch().getText()); + chainFinished = true; + } else { + if (!(nextCondition instanceof PsiPolyadicExpression)) break; + PsiPolyadicExpression nextPolyadic = (PsiPolyadicExpression)nextCondition; + if (!nextPolyadic.getOperationTokenType().equals(JavaTokenType.ANDAND)) break; + PsiExpression firstOperand = nextPolyadic.getOperands()[0]; + if (!PsiEquivalenceUtil.areElementsEquivalent(extract, firstOperand)) break; + elseChain.add( + createIfString(removeOperand(factory, nextPolyadic, firstOperand, tracker), nextIf.getThenBranch(), (PsiStatement)null, tracker)); + } + elseBranch = nextIf.getElseBranch(); + } + if (!chainFinished && elseBranch != null) { + elseChain.add(elseBranch.getText()); + } + String thenString; + if (elseChain.isEmpty()) { + thenString = createIfString(leave, thenBranch, (String)null, tracker); + } + else { + thenString = "{" + createIfString(leave, thenBranch, String.join(" else ", elseChain), tracker) + "}"; + } + String ifString = createIfString(extract, thenString, elseBranch, tracker); + return factory.createStatementFromText(ifString, thenBranch); } @NotNull diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterMissedBrackets.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterMissedBrackets.java index 836783f274b6..9a74b96576bb 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterMissedBrackets.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterMissedBrackets.java @@ -1,15 +1,13 @@ // "Extract if (a)" "true" class TestThreadInspection { void f(boolean a, boolean b, boolean c){ - if (a) + if (a) { if (b) { System.out.println("a&b");//first comment - } else { - if (c) { - System.out.println("c"); - } + } else if (c) { + System.out.println("c"); } - else if (c) { + } else if (c) { System.out.println("c"); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating.java new file mode 100644 index 000000000000..f6d59ffb2a71 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating.java @@ -0,0 +1,13 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c){ + /*2*/ + if (a) { + if (b) { + System.out.println("a&b");//first comment + } else if (c) { + System.out.println("a&c"); // three + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating2.java new file mode 100644 index 000000000000..0bdd82bf4d0b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating2.java @@ -0,0 +1,17 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c, boolean d){ + //a + if (a) { + if (b) { + System.out.println("a&b");//first comment + } else if (c) { + System.out.println("a&c");//ac + } else { + System.out.println("a");//a + } + } else if (d) { + System.out.println("d");//d + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating3.java new file mode 100644 index 000000000000..0a682a6f873a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterRepeating3.java @@ -0,0 +1,17 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c, boolean d){ + //a + if (a) { + if (b) { + System.out.println("a&b");//first comment + } else { + System.out.println("a");//a + } + } else if (a && c) { + System.out.println("a&c");//ac + } else if (a && d) { + System.out.println("a&d");//ad + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterSimpleElse.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterSimpleElse.java index db4a3fe20eb8..951fdd9cedfe 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterSimpleElse.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/afterSimpleElse.java @@ -1,13 +1,13 @@ // "Extract if (a)" "true" class TestThreadInspection { void f(boolean a, boolean b, boolean c){ - if (a) + if (a) { if (b) { System.out.println("a&b"); } else { System.out.println("c"); } - else { + } else { System.out.println("c"); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating.java new file mode 100644 index 000000000000..56b433699106 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating.java @@ -0,0 +1,10 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c){ + if (a && b) + System.out.println("a&b");//first comment + else if (a && c/*2*/) { + System.out.println("a&c"); // three + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating2.java new file mode 100644 index 000000000000..5bc9d014272b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating2.java @@ -0,0 +1,16 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c, boolean d){ + if (a && b) + System.out.println("a&b");//first comment + else if (a && c) { + System.out.println("a&c");//ac + } + else if (a) { + System.out.println("a");//a + } + else if (d) { + System.out.println("d");//d + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating3.java new file mode 100644 index 000000000000..3a64cda33803 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/extractIfCondition/beforeRepeating3.java @@ -0,0 +1,16 @@ +// "Extract if (a)" "true" +class Test { + void f(boolean a, boolean b, boolean c, boolean d){ + if (a && b) + System.out.println("a&b");//first comment + else if (a) { + System.out.println("a");//a + } + else if (a && c) { + System.out.println("a&c");//ac + } + else if (a && d) { + System.out.println("a&d");//ad + } + } +} \ No newline at end of file