Keep braces in redundant cascade if #KT-19704 Fixed
This commit is contained in:
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.PsiElementVisitor
|
import com.intellij.psi.PsiElementVisitor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isElseIf
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
@@ -48,7 +49,8 @@ class ConstantConditionIfInspection : AbstractKotlinInspection() {
|
|||||||
val fixes = mutableListOf<LocalQuickFix>()
|
val fixes = mutableListOf<LocalQuickFix>()
|
||||||
|
|
||||||
if (expression.branch(constantValue) != null) {
|
if (expression.branch(constantValue) != null) {
|
||||||
fixes += SimplifyFix(constantValue, expression.isUsedAsExpression(context))
|
val keepBraces = expression.isElseIf() && expression.branch(constantValue) is KtBlockExpression
|
||||||
|
fixes += SimplifyFix(constantValue, expression.isUsedAsExpression(context), keepBraces)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!constantValue && expression.`else` == null) {
|
if (!constantValue && expression.`else` == null) {
|
||||||
@@ -64,7 +66,8 @@ class ConstantConditionIfInspection : AbstractKotlinInspection() {
|
|||||||
|
|
||||||
private class SimplifyFix(
|
private class SimplifyFix(
|
||||||
private val conditionValue: Boolean,
|
private val conditionValue: Boolean,
|
||||||
private val isUsedAsExpression: Boolean
|
private val isUsedAsExpression: Boolean,
|
||||||
|
private val keepBraces: Boolean
|
||||||
) : LocalQuickFix {
|
) : LocalQuickFix {
|
||||||
override fun getFamilyName() = name
|
override fun getFamilyName() = name
|
||||||
|
|
||||||
@@ -73,9 +76,11 @@ class ConstantConditionIfInspection : AbstractKotlinInspection() {
|
|||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
val ifExpression = descriptor.psiElement.getParentOfType<KtIfExpression>(strict = true) ?: return
|
val ifExpression = descriptor.psiElement.getParentOfType<KtIfExpression>(strict = true) ?: return
|
||||||
|
|
||||||
val branch = ifExpression.branch(conditionValue)?.unwrapBlockOrParenthesis() ?: return
|
val branch = ifExpression.branch(conditionValue)?.let {
|
||||||
|
if (keepBraces) it else it.unwrapBlockOrParenthesis()
|
||||||
|
} ?: return
|
||||||
|
|
||||||
ifExpression.replaceWithBranch(branch, isUsedAsExpression)
|
ifExpression.replaceWithBranch(branch, isUsedAsExpression, keepBraces)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +105,7 @@ private fun KtExpression.constantBooleanValue(context: BindingContext): Boolean?
|
|||||||
return constantValue?.value as? Boolean
|
return constantValue?.value as? Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtExpression.replaceWithBranch(branch: KtExpression, isUsedAsExpression: Boolean) {
|
fun KtExpression.replaceWithBranch(branch: KtExpression, isUsedAsExpression: Boolean, keepBraces: Boolean = false) {
|
||||||
val lastExpression = when {
|
val lastExpression = when {
|
||||||
branch !is KtBlockExpression -> replaced(branch)
|
branch !is KtBlockExpression -> replaced(branch)
|
||||||
isUsedAsExpression -> {
|
isUsedAsExpression -> {
|
||||||
@@ -108,18 +113,17 @@ fun KtExpression.replaceWithBranch(branch: KtExpression, isUsedAsExpression: Boo
|
|||||||
replaced(factory.createExpressionByPattern("run $0", branch.text))
|
replaced(factory.createExpressionByPattern("run $0", branch.text))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val firstChild = branch.firstChild.nextSibling
|
val firstChildSibling = branch.firstChild.nextSibling
|
||||||
|
val lastChild = branch.lastChild
|
||||||
if (firstChild == branch.lastChild) {
|
if (firstChildSibling != lastChild) {
|
||||||
delete()
|
if (keepBraces) {
|
||||||
|
parent.addAfter(branch, this)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parent.addRangeAfter(firstChildSibling, lastChild.prevSibling, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
delete()
|
||||||
val lastChild = branch.lastChild.prevSibling
|
|
||||||
val parent = parent
|
|
||||||
parent.addRangeAfter(firstChild, lastChild, this)
|
|
||||||
delete()
|
|
||||||
}
|
|
||||||
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,4 +39,20 @@
|
|||||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Condition of 'if' expression is constant</problem_class>
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Condition of 'if' expression is constant</problem_class>
|
||||||
<description>Condition is always 'true'</description>
|
<description>Condition is always 'true'</description>
|
||||||
</problem>
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>test.kt</file>
|
||||||
|
<line>31</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Condition of 'if' expression is constant</problem_class>
|
||||||
|
<description>Condition is always 'true'</description>
|
||||||
|
</problem>
|
||||||
|
<problem>
|
||||||
|
<file>test.kt</file>
|
||||||
|
<line>37</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Condition of 'if' expression is constant</problem_class>
|
||||||
|
<description>Condition is always 'true'</description>
|
||||||
|
</problem>
|
||||||
</problems>
|
</problems>
|
||||||
+11
-1
@@ -3,7 +3,7 @@ fun baz(s: String) {}
|
|||||||
|
|
||||||
const val TRUE = true
|
const val TRUE = true
|
||||||
|
|
||||||
fun bar() {
|
fun bar(s: String?) {
|
||||||
foo(if (TRUE) 1 else 2)
|
foo(if (TRUE) 1 else 2)
|
||||||
|
|
||||||
foo(if (false && TRUE) {
|
foo(if (false && TRUE) {
|
||||||
@@ -25,4 +25,14 @@ fun bar() {
|
|||||||
baz("a")
|
baz("a")
|
||||||
1
|
1
|
||||||
} else 2)
|
} else 2)
|
||||||
|
|
||||||
|
if (s ==null) {
|
||||||
|
1
|
||||||
|
} else if (true) {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s ==null) {
|
||||||
|
1
|
||||||
|
} else if (true) 2
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else if (<caret>true) {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else if (<caret>true) 2
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else if (<caret>true) {
|
||||||
|
foo(1)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(x: Int) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foo(1)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun foo(s: String) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
foo("a")
|
||||||
|
foo("b")
|
||||||
|
}
|
||||||
|
else if (<caret>true) {
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foo("c")
|
||||||
|
foo("d")
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
fun foo(s: String) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
foo("a")
|
||||||
|
foo("b")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fun foo(s: String) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else if (<caret>true) {
|
||||||
|
foo("a")
|
||||||
|
foo("b")
|
||||||
|
2
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun foo(s: String) {}
|
||||||
|
|
||||||
|
fun bar(s: String?) {
|
||||||
|
if (s == null) {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foo("a")
|
||||||
|
foo("b")
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -428,18 +428,42 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("endWithElseIf.kt")
|
||||||
|
public void testEndWithElseIf() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/endWithElseIf.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("endWithElseIfNoBraces.kt")
|
||||||
|
public void testEndWithElseIfNoBraces() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/endWithElseIfNoBraces.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("expression.kt")
|
@TestMetadata("expression.kt")
|
||||||
public void testExpression() throws Exception {
|
public void testExpression() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/expression.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/expression.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expressionElseIfBlock.kt")
|
||||||
|
public void testExpressionElseIfBlock() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/expressionElseIfBlock.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noStatements.kt")
|
@TestMetadata("noStatements.kt")
|
||||||
public void testNoStatements() throws Exception {
|
public void testNoStatements() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/noStatements.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/noStatements.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noStatementsElseIf.kt")
|
||||||
|
public void testNoStatementsElseIf() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/noStatementsElseIf.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleBlock.kt")
|
@TestMetadata("simpleBlock.kt")
|
||||||
public void testSimpleBlock() throws Exception {
|
public void testSimpleBlock() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/simpleBlock.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/simpleBlock.kt");
|
||||||
@@ -463,6 +487,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/statement.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/statement.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("statementElseIf.kt")
|
||||||
|
public void testStatementElseIf() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/constantConditionIf/statementElseIf.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/copyWithoutNamedArguments")
|
@TestMetadata("idea/testData/inspectionsLocal/copyWithoutNamedArguments")
|
||||||
|
|||||||
Reference in New Issue
Block a user