Extract common conjunct from if-else chain in ExtractIfConditionAction

Fixes IDEA-179499 New inspection: Should break out common conjunct from "if / else if"
This commit is contained in:
Tagir Valeev
2018-04-07 09:08:57 +03:00
parent 1916b3a079
commit 83ebaa7f64
9 changed files with 136 additions and 17 deletions
@@ -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<String> 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
@@ -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");
}
}
@@ -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
}
}
}
}
@@ -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
}
}
}
@@ -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
}
}
}
@@ -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");
}
}
@@ -0,0 +1,10 @@
// "Extract if (a)" "true"
class Test {
void f(boolean a, boolean b, boolean c){
if (<caret>a && b)
System.out.println("a&b");//first comment
else if (a && c/*2*/) {
System.out.println("a&c"); // three
}
}
}
@@ -0,0 +1,16 @@
// "Extract if (a)" "true"
class Test {
void f(boolean a, boolean b, boolean c, boolean d){
if (<caret>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
}
}
}
@@ -0,0 +1,16 @@
// "Extract if (a)" "true"
class Test {
void f(boolean a, boolean b, boolean c, boolean d){
if (<caret>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
}
}
}