Invert if: more correct handling of empty returns #KT-13444 Fixed
(cherry picked from commit be2adaf)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
25eefdb6ec
commit
605ac0b25e
@@ -113,14 +113,21 @@ class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(KtIfEx
|
||||
val last = afterIfInBlock.last()
|
||||
// build new then branch from statements after if (we will add exit statement if necessary later)
|
||||
//TODO: no block if single?
|
||||
val newThenRange = PsiChildRange(first, last).trimWhiteSpaces()
|
||||
val newThenRange = if (isEmptyReturn(lastThenStatement) && isEmptyReturn(lastStatementInBlock)) {
|
||||
PsiChildRange(first, lastStatementInBlock.prevSibling).trimWhiteSpaces()
|
||||
}
|
||||
else {
|
||||
PsiChildRange(first, last).trimWhiteSpaces()
|
||||
}
|
||||
val newIf = factory.createExpressionByPattern("if ($0) { $1 }", newCondition, newThenRange) as KtIfExpression
|
||||
|
||||
// remove statements after if as they are moving under if
|
||||
block.deleteChildRange(first, last)
|
||||
|
||||
if (lastThenStatement is KtReturnExpression && lastThenStatement.returnedExpression == null) {
|
||||
lastThenStatement.delete()
|
||||
if (isEmptyReturn(lastThenStatement)) {
|
||||
if (block.parent is KtDeclarationWithBody && block.parent !is KtFunctionLiteral) {
|
||||
lastThenStatement.delete()
|
||||
}
|
||||
}
|
||||
val updatedIf = copyThenBranchAfter(ifExpression)
|
||||
|
||||
@@ -148,6 +155,9 @@ class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(KtIfEx
|
||||
return updatedIf.replace(newIf) as KtIfExpression
|
||||
}
|
||||
|
||||
private fun isEmptyReturn(statement: KtExpression) =
|
||||
statement is KtReturnExpression && statement.returnedExpression == null && statement.labeledExpression == null
|
||||
|
||||
private fun copyThenBranchAfter(ifExpression: KtIfExpression): KtIfExpression {
|
||||
val factory = KtPsiFactory(ifExpression)
|
||||
val thenBranch = ifExpression.then ?: return ifExpression
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fun println(s: String) {}
|
||||
|
||||
fun foo(y: Boolean) {
|
||||
<caret>if (!y) return
|
||||
println("no1")
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun println(s: String) {}
|
||||
|
||||
fun foo(y: Boolean) {
|
||||
if (y) {
|
||||
println("no1")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
var foo: Boolean = false
|
||||
set(arg) {
|
||||
<caret>if (field == arg) return
|
||||
field = arg
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
var foo: Boolean = false
|
||||
set(arg) {
|
||||
if (field != arg) {
|
||||
field = arg
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
inline fun call(f: () -> Unit) = f()
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(arg: Boolean) {
|
||||
call {
|
||||
<caret>if (!arg) return@call
|
||||
bar()
|
||||
return
|
||||
}
|
||||
bar()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
inline fun call(f: () -> Unit) = f()
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(arg: Boolean) {
|
||||
call {
|
||||
if (arg) {
|
||||
bar()
|
||||
return
|
||||
}
|
||||
return@call
|
||||
}
|
||||
bar()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
inline fun call(f: () -> Unit) = f()
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(arg: Boolean) {
|
||||
call {
|
||||
<caret>if (!arg) return
|
||||
bar()
|
||||
return
|
||||
}
|
||||
bar()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
inline fun call(f: () -> Unit) = f()
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(arg: Boolean) {
|
||||
call {
|
||||
if (arg) {
|
||||
bar()
|
||||
}
|
||||
return
|
||||
}
|
||||
bar()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun println(s: String) {}
|
||||
|
||||
fun foo(x: Boolean, y: Boolean) {
|
||||
if (x) {
|
||||
<caret>if (!y) return
|
||||
println("no1")
|
||||
return
|
||||
}
|
||||
println("no2")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fun println(s: String) {}
|
||||
|
||||
fun foo(x: Boolean, y: Boolean) {
|
||||
if (x) {
|
||||
if (y) {
|
||||
println("no1")
|
||||
}
|
||||
return
|
||||
}
|
||||
println("no2")
|
||||
}
|
||||
@@ -6816,6 +6816,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifWithBothBranchesReturn.kt")
|
||||
public void testIfWithBothBranchesReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/ifWithBothBranchesReturn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifWithBothBranchesSetter.kt")
|
||||
public void testIfWithBothBranchesSetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/ifWithBothBranchesSetter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("in.kt")
|
||||
public void testIn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/in.kt");
|
||||
@@ -6834,6 +6846,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaNonLocalAndLocalReturn.kt")
|
||||
public void testLambdaNonLocalAndLocalReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/lambdaNonLocalAndLocalReturn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaNonLocalReturn.kt")
|
||||
public void testLambdaNonLocalReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/lambdaNonLocalReturn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lastStatement1.kt")
|
||||
public void testLastStatement1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/lastStatement1.kt");
|
||||
@@ -6900,6 +6924,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedIfWithReturn.kt")
|
||||
public void testNestedIfWithReturn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/nestedIfWithReturn.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notIn.kt")
|
||||
public void testNotIn() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/invertIfCondition/notIn.kt");
|
||||
|
||||
Reference in New Issue
Block a user