Convert to expression body is forbidden for if without else #KT-12951 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-08-10 14:26:45 +03:00
parent 1c5c6506ce
commit 6a6c67dd5f
14 changed files with 148 additions and 0 deletions
@@ -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) {}
@@ -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");