fix "Simplify if" generating unreachable code (IDEA-182501)

This commit is contained in:
peter
2018-01-03 21:53:54 +01:00
parent b3805faed2
commit fda735bd1b
4 changed files with 71 additions and 125 deletions
@@ -115,7 +115,12 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement {
@Override
public void invoke(@NotNull final Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
if (!isAvailable()) return;
if (isAvailable()) {
doSimplify();
}
}
public void doSimplify() {
PsiExpression subExpression = getSubExpression();
if (subExpression == null) return;
if (shouldExtractSideEffect()) {
@@ -139,7 +144,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement {
return;
}
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(subExpression.getProject());
final PsiExpression constExpression = factory.createExpressionFromText(Boolean.toString(mySubExpressionValue), subExpression);
PsiExpression expression = (PsiExpression)subExpression.replace(constExpression);
while (expression.getParent() instanceof PsiExpression) {
@@ -15,22 +15,22 @@
*/
package com.siyeh.ig.controlflow;
import com.intellij.codeInsight.daemon.impl.quickfix.SimplifyBooleanExpressionFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiIfStatement;
import com.intellij.psi.PsiStatement;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class ConstantIfStatementInspection extends BaseInspection {
@Override
@@ -59,9 +59,6 @@ public class ConstantIfStatementInspection extends BaseInspection {
@Override
public InspectionGadgetsFix buildFix(Object... infos) {
//if (PsiUtil.isInJspFile(location)) {
// return null;
//}
return new ConstantIfStatementFix();
}
@@ -75,83 +72,12 @@ public class ConstantIfStatementInspection extends BaseInspection {
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement ifKeyword = descriptor.getPsiElement();
final PsiIfStatement statement =
(PsiIfStatement)ifKeyword.getParent();
assert statement != null;
final PsiStatement thenBranch = statement.getThenBranch();
final PsiStatement elseBranch = statement.getElseBranch();
final PsiExpression condition = statement.getCondition();
if (BoolUtils.isFalse(condition)) {
if (elseBranch != null) {
replaceStatementWithUnwrapping(elseBranch, statement);
}
else {
deleteElement(statement);
}
}
else {
replaceStatementWithUnwrapping(thenBranch, statement);
}
public void doFix(Project project, ProblemDescriptor descriptor) {
PsiElement ifKeyword = descriptor.getPsiElement();
PsiExpression condition = Objects.requireNonNull(((PsiIfStatement)ifKeyword.getParent()).getCondition());
new SimplifyBooleanExpressionFix(condition, BoolUtils.isTrue(condition)).doSimplify();
}
private static void replaceStatementWithUnwrapping(PsiStatement branch, PsiIfStatement statement)
throws IncorrectOperationException {
if (branch instanceof PsiBlockStatement &&
!(statement.getParent() instanceof PsiIfStatement)) {
final PsiCodeBlock parentBlock =
PsiTreeUtil.getParentOfType(branch, PsiCodeBlock.class);
if (parentBlock == null) {
replaceWithBranch(branch, statement);
return;
}
final PsiCodeBlock block =
((PsiBlockStatement)branch).getCodeBlock();
final boolean hasConflicts =
DeclarationSearchUtils.containsConflictingDeclarations(
block, parentBlock);
if (hasConflicts) {
replaceWithBranch(branch, statement);
}
else {
final PsiElement containingElement = statement.getParent();
final PsiStatement[] statements = block.getStatements();
if (statements.length > 0) {
assert containingElement != null;
final PsiJavaToken lBrace = block.getLBrace();
final PsiJavaToken rBrace = block.getRBrace();
PsiElement added = null;
if (lBrace != null && rBrace != null) {
final PsiElement firstNonBrace = lBrace.getNextSibling();
final PsiElement lastNonBrace = rBrace.getPrevSibling();
if (firstNonBrace != null && lastNonBrace != null) {
added = containingElement.addRangeBefore(firstNonBrace, lastNonBrace, statement);
}
}
if (added == null) {
added = containingElement.addRangeBefore(statements[0],
statements[statements.length - 1], statement);
}
final Project project = statement.getProject();
final CodeStyleManager codeStyleManager =
CodeStyleManager.getInstance(project);
codeStyleManager.reformat(added);
}
statement.delete();
}
}
else {
replaceWithBranch(branch, statement);
}
}
private static void replaceWithBranch(PsiStatement branch, PsiIfStatement statement) {
CommentTracker commentTracker = new CommentTracker();
final String elseText = commentTracker.markUnchanged(branch).getText();
PsiReplacementUtil.replaceStatement(statement, elseText, commentTracker);
}
}
private static class ConstantIfStatementVisitor
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package com.siyeh.ig.controlflow;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
/**
* @author Bas Leijdekkers
*/
class ConstantIfStatementInspectionTest extends LightInspectionTestCase {
void testParentheses() {
doStatementTest("""/*'if' statement can be simplified*/if/**/ (((false))) {
System.out.println(1);
} else {
System.out.println(2);
}""");
}
void "test remove following statements when body always returns via break"() {
myFixture.configureByText"a.java", """
class Foo {
void f(){
while (true) {
<warning descr="'if' statement can be simplified">i<caret>f</warning> (true) {
break;//comment
}
System.out.println();
}
}
}
"""
myFixture.enableInspections(getInspection())
myFixture.checkHighlighting()
myFixture.launchAction(myFixture.findSingleIntention("Simplify"))
myFixture.checkResult """
class Foo {
void f(){
while (true) {
break;//comment
}
}
}
"""
}
@Override
protected InspectionProfileEntry getInspection() {
return new ConstantIfStatementInspection();
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.controlflow;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
/**
* @author Bas Leijdekkers
*/
public class ConstantIfStatementInspectionTest extends LightInspectionTestCase {
public void testParentheses() {
doStatementTest("/*'if' statement can be simplified*/if/**/ (((false))) {\n" +
" System.out.println(1);\n" +
" } else {\n" +
" System.out.println(2);\n" +
" }");
}
@Override
protected InspectionProfileEntry getInspection() {
return new ConstantIfStatementInspection();
}
}