mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IfStatementWithIdenticalBranchesInspection: tail call heuristic
GitOrigin-RevId: 8c74e25df2a005a28f2d0e711b61b5b128ad7979
This commit is contained in:
committed by
intellij-monorepo-bot
parent
90b899e1ba
commit
db442bde43
@@ -0,0 +1,17 @@
|
||||
// "Extract common part from 'if'" "INFORMATION"
|
||||
|
||||
class X {
|
||||
void foo() {
|
||||
if (true) {
|
||||
another(1);
|
||||
}
|
||||
else {
|
||||
another(2);
|
||||
}
|
||||
bar();
|
||||
}
|
||||
|
||||
void another(int i) {}
|
||||
|
||||
void bar() {}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// "Extract common part from 'if'" "INFORMATION"
|
||||
|
||||
class X {
|
||||
void foo() {
|
||||
if<caret> (true) {
|
||||
another(1);
|
||||
bar();
|
||||
}
|
||||
else {
|
||||
another(2);
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
void another(int i) {}
|
||||
|
||||
void bar() {}
|
||||
}
|
||||
+40
-8
@@ -17,6 +17,7 @@ package com.siyeh.ig.controlflow;
|
||||
|
||||
import com.intellij.codeInsight.BlockUtils;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -36,12 +38,21 @@ import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
// Not really with identical branches, but also common parts
|
||||
public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
public boolean myHighlightWhenLastStatementIsCall = true;
|
||||
|
||||
private static final List<IfStatementInspector> ourInspectors = new ArrayList<>(Arrays.asList(
|
||||
ImplicitElse::inspect,
|
||||
ThenElse::inspect,
|
||||
ElseIf::inspect
|
||||
));
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Highlight when last common statement is call", this, "myHighlightWhenLastStatementIsCall");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
@@ -51,7 +62,7 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
PsiStatement[] thenStatements = unwrap(ifStatement.getThenBranch());
|
||||
PsiStatement[] elseStatements = unwrap(ifStatement.getElseBranch());
|
||||
for (IfStatementInspector inspector : ourInspectors) {
|
||||
IfInspectionResult result = inspector.inspect(ifStatement, thenStatements, elseStatements, isOnTheFly);
|
||||
IfInspectionResult result = inspector.inspect(ifStatement, thenStatements, elseStatements, isOnTheFly, myHighlightWhenLastStatementIsCall);
|
||||
if (result != null) {
|
||||
ProblemHighlightType highlightType;
|
||||
if (result.myIsWarning) {
|
||||
@@ -73,7 +84,8 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
@Nullable IfInspectionResult inspect(@NotNull PsiIfStatement ifStatement,
|
||||
@NotNull PsiStatement[] thenBranch,
|
||||
@NotNull PsiStatement[] elseBranch,
|
||||
boolean isOnTheFly);
|
||||
boolean isOnTheFly,
|
||||
boolean highlightWhenLastStatementIsCall);
|
||||
}
|
||||
|
||||
private static class IfInspectionResult {
|
||||
@@ -175,7 +187,10 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
private final boolean myMayChangeSemantics;
|
||||
private final boolean myIsOnTheFly;
|
||||
|
||||
private ExtractCommonIfPartsFix(CommonPartType type, boolean mayChangeSemantics, boolean isOnTheFly) {
|
||||
|
||||
private ExtractCommonIfPartsFix(CommonPartType type,
|
||||
boolean mayChangeSemantics,
|
||||
boolean isOnTheFly) {
|
||||
myType = type;
|
||||
myMayChangeSemantics = mayChangeSemantics;
|
||||
myIsOnTheFly = isOnTheFly;
|
||||
@@ -631,7 +646,8 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
@Nullable static IfInspectionResult inspect(@NotNull PsiIfStatement ifStatement,
|
||||
@NotNull PsiStatement[] thenBranch,
|
||||
@NotNull PsiStatement[] elseBranch,
|
||||
boolean isOnTheFly) {
|
||||
boolean isOnTheFly,
|
||||
boolean highlightWhenLastStatementIsCall) {
|
||||
ImplicitElse implicitElse = from(thenBranch, elseBranch, ifStatement);
|
||||
if (implicitElse == null) return null;
|
||||
CommonPartType type = implicitElse.getType();
|
||||
@@ -807,21 +823,36 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
return new ThenElse(headCommonParts, tailCommonParts, mayChangeSemantics, type, substitutionTable);
|
||||
}
|
||||
|
||||
private static boolean isSingleCallTail(List<PsiStatement> tail) {
|
||||
if (tail.size() != 1) return false;
|
||||
PsiExpressionStatement expressionStatement = tryCast(tail.get(0), PsiExpressionStatement.class);
|
||||
if (expressionStatement == null) return false;
|
||||
PsiMethodCallExpression call = tryCast(expressionStatement.getExpression(), PsiMethodCallExpression.class);
|
||||
return call != null;
|
||||
}
|
||||
|
||||
|
||||
@Nullable static IfInspectionResult inspect(@NotNull PsiIfStatement ifStatement,
|
||||
@NotNull PsiStatement[] thenBranch,
|
||||
@NotNull PsiStatement[] elseBranch,
|
||||
boolean isOnTheFly) {
|
||||
boolean isOnTheFly,
|
||||
boolean highlightWhenLastStatementIsCall) {
|
||||
ThenElse thenElse = from(ifStatement, thenBranch, elseBranch, isOnTheFly);
|
||||
if (thenElse == null) return null;
|
||||
boolean isNotInCodeBlock = !(ifStatement.getParent() instanceof PsiCodeBlock);
|
||||
boolean mayChangeSemantics = thenElse.myMayChangeSemantics;
|
||||
CommonPartType type = thenElse.myCommonPartType;
|
||||
ExtractCommonIfPartsFix fix = new ExtractCommonIfPartsFix(type, mayChangeSemantics, isOnTheFly);
|
||||
boolean isInfoLevel = mayChangeSemantics || isNotInCodeBlock;
|
||||
boolean tailStatementIsSingleCall = !highlightWhenLastStatementIsCall
|
||||
&& isSingleCallTail(thenElse.myTailStatementsOfThen)
|
||||
&& thenElse.myHeadUnitsOfThen.isEmpty();
|
||||
boolean isInfoLevel = mayChangeSemantics
|
||||
|| isNotInCodeBlock
|
||||
|| type == CommonPartType.WITH_VARIABLES_EXTRACT
|
||||
|| tailStatementIsSingleCall;
|
||||
PsiElement elementToHighlight = isInfoLevel ? ifStatement : ifStatement.getFirstChild();
|
||||
if (type == CommonPartType.VARIABLES_ONLY && !isOnTheFly) return null;
|
||||
return new IfInspectionResult(elementToHighlight, type != CommonPartType.WITH_VARIABLES_EXTRACT && !isInfoLevel, fix,
|
||||
return new IfInspectionResult(elementToHighlight, !isInfoLevel, fix,
|
||||
type.getDescriptionMessage(mayChangeSemantics));
|
||||
}
|
||||
|
||||
@@ -1038,7 +1069,8 @@ public class IfStatementWithIdenticalBranchesInspection extends AbstractBaseJava
|
||||
@Nullable static IfInspectionResult inspect(@NotNull PsiIfStatement ifStatement,
|
||||
@NotNull PsiStatement[] thenBranch,
|
||||
@NotNull PsiStatement[] elseBranch,
|
||||
boolean isOnTheFly) {
|
||||
boolean isOnTheFly,
|
||||
boolean highlightWhenLastStatementIsCall) {
|
||||
ElseIf elseIf = from(ifStatement, thenBranch);
|
||||
if (elseIf == null) return null;
|
||||
String message = InspectionsBundle.message("inspection.common.if.parts.family.else.if.description");
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ public class IfStatementWithIdenticalBranchesInspectionTest extends LightQuickFi
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
IfStatementWithIdenticalBranchesInspection inspection = new IfStatementWithIdenticalBranchesInspection();
|
||||
inspection.myHighlightWhenLastStatementIsCall = !getTestName(false).equals("LastStatementIsCallInfo.java");
|
||||
return new LocalInspectionTool[]{inspection};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user