Convert to expression body is forbidden for if without else #KT-12951 Fixed
This commit is contained in:
@@ -109,6 +109,9 @@ class ConvertToExpressionBodyIntention : SelfTargetingOffsetIndependentIntention
|
||||
val isUnit = KotlinBuiltIns.isUnit(expressionType)
|
||||
if (!isUnit && !KotlinBuiltIns.isNothing(expressionType)) return null
|
||||
if (isUnit) {
|
||||
if (statement.hasResultingIfWithoutElse()) {
|
||||
return null
|
||||
}
|
||||
val resultingWhens = statement.resultingWhens()
|
||||
if (resultingWhens.any { it.elseExpression == null && context.get(BindingContext.EXHAUSTIVE_WHEN, it) != true}) {
|
||||
return null
|
||||
|
||||
@@ -141,6 +141,15 @@ fun KtExpression.resultingWhens(): List<KtWhenExpression> = when (this) {
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
fun KtExpression?.hasResultingIfWithoutElse(): Boolean = when (this) {
|
||||
is KtIfExpression -> `else` == null || then.hasResultingIfWithoutElse() || `else`.hasResultingIfWithoutElse()
|
||||
is KtWhenExpression -> entries.any { it.expression.hasResultingIfWithoutElse() }
|
||||
is KtBinaryExpression -> left.hasResultingIfWithoutElse() || right.hasResultingIfWithoutElse()
|
||||
is KtUnaryExpression -> baseExpression.hasResultingIfWithoutElse()
|
||||
is KtBlockExpression -> statements.lastOrNull().hasResultingIfWithoutElse()
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun KtExpression.specialNegation(): KtExpression? {
|
||||
val factory = KtPsiFactory(this)
|
||||
when (this) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun nullable() {}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) {
|
||||
<caret>nullable() ?: if (f) bar() else bar()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun nullable() {}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) = nullable() ?: if (f) bar() else bar()
|
||||
@@ -0,0 +1,9 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
fun nullable() {}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) {
|
||||
<caret>nullable() ?: if (f) bar()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) {
|
||||
<caret>if (f) bar() else bar()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) = if (f) bar() else bar()
|
||||
@@ -0,0 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
fun bar() {}
|
||||
|
||||
fun foo(f: Boolean) {
|
||||
<caret>if (f) bar()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun <T> run(f: () -> T) = f()
|
||||
fun whenExpr(flag: Boolean) {
|
||||
<caret>run {
|
||||
println("run")
|
||||
if (flag) {
|
||||
println("flag")
|
||||
}
|
||||
}
|
||||
}
|
||||
fun println(s: String) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
fun <T> run(f: () -> T) = f()
|
||||
fun whenExpr(flag: Boolean) = run {
|
||||
println("run")
|
||||
if (flag) {
|
||||
println("flag")
|
||||
}
|
||||
}
|
||||
fun println(s: String) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
// IS_APPLICABLE: true
|
||||
enum class AccessMode { READ, WRITE, RW }
|
||||
fun whenExpr(mode: Boolean, access: AccessMode) {
|
||||
<caret>when (access) {
|
||||
AccessMode.READ -> if (mode) println("read") else println("noread")
|
||||
AccessMode.WRITE -> if (mode) println("write") else println("nowrite")
|
||||
AccessMode.RW -> if (mode) println("both") else println("no both")
|
||||
}
|
||||
}
|
||||
fun println(s: String) {}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// IS_APPLICABLE: true
|
||||
enum class AccessMode { READ, WRITE, RW }
|
||||
fun whenExpr(mode: Boolean, access: AccessMode) = when (access) {
|
||||
AccessMode.READ -> if (mode) println("read") else println("noread")
|
||||
AccessMode.WRITE -> if (mode) println("write") else println("nowrite")
|
||||
AccessMode.RW -> if (mode) println("both") else println("no both")
|
||||
}
|
||||
fun println(s: String) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
// IS_APPLICABLE: false
|
||||
enum class AccessMode { READ, WRITE, RW }
|
||||
fun whenExpr(mode: Boolean, access: AccessMode) {
|
||||
<caret>when (access) {
|
||||
AccessMode.READ -> if (mode) println("read") else println("noread")
|
||||
AccessMode.WRITE -> if (mode) println("write")
|
||||
AccessMode.RW -> if (mode) println("both") else println("no both")
|
||||
}
|
||||
}
|
||||
fun println(s: String) {}
|
||||
@@ -4774,6 +4774,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("elvisIfElseUnit.kt")
|
||||
public void testElvisIfElseUnit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/elvisIfElseUnit.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("elvisIfUnit.kt")
|
||||
public void testElvisIfUnit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/elvisIfUnit.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("elvisWhenUnitNonExhaustive.kt")
|
||||
public void testElvisWhenUnitNonExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/elvisWhenUnitNonExhaustive.kt");
|
||||
@@ -4852,6 +4864,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifElseUnit.kt")
|
||||
public void testIfElseUnit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/ifElseUnit.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifUnit.kt")
|
||||
public void testIfUnit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/ifUnit.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifWhenUnitExhaustive.kt")
|
||||
public void testIfWhenUnitExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/ifWhenUnitExhaustive.kt");
|
||||
@@ -4864,6 +4888,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaIfUnit.kt")
|
||||
public void testLambdaIfUnit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/lambdaIfUnit.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWhenUnitNonExhaustive.kt")
|
||||
public void testLambdaWhenUnitNonExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/lambdaWhenUnitNonExhaustive.kt");
|
||||
@@ -4900,6 +4930,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenIfUnitExhaustive.kt")
|
||||
public void testWhenIfUnitExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/whenIfUnitExhaustive.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenIfUnitNonExhaustive.kt")
|
||||
public void testWhenIfUnitNonExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/whenIfUnitNonExhaustive.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenUnitExhaustive.kt")
|
||||
public void testWhenUnitExhaustive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/whenUnitExhaustive.kt");
|
||||
|
||||
Reference in New Issue
Block a user