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)
|
val isUnit = KotlinBuiltIns.isUnit(expressionType)
|
||||||
if (!isUnit && !KotlinBuiltIns.isNothing(expressionType)) return null
|
if (!isUnit && !KotlinBuiltIns.isNothing(expressionType)) return null
|
||||||
if (isUnit) {
|
if (isUnit) {
|
||||||
|
if (statement.hasResultingIfWithoutElse()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
val resultingWhens = statement.resultingWhens()
|
val resultingWhens = statement.resultingWhens()
|
||||||
if (resultingWhens.any { it.elseExpression == null && context.get(BindingContext.EXHAUSTIVE_WHEN, it) != true}) {
|
if (resultingWhens.any { it.elseExpression == null && context.get(BindingContext.EXHAUSTIVE_WHEN, it) != true}) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -141,6 +141,15 @@ fun KtExpression.resultingWhens(): List<KtWhenExpression> = when (this) {
|
|||||||
else -> listOf()
|
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? {
|
private fun KtExpression.specialNegation(): KtExpression? {
|
||||||
val factory = KtPsiFactory(this)
|
val factory = KtPsiFactory(this)
|
||||||
when (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);
|
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")
|
@TestMetadata("elvisWhenUnitNonExhaustive.kt")
|
||||||
public void testElvisWhenUnitNonExhaustive() throws Exception {
|
public void testElvisWhenUnitNonExhaustive() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/elvisWhenUnitNonExhaustive.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/elvisWhenUnitNonExhaustive.kt");
|
||||||
@@ -4852,6 +4864,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ifWhenUnitExhaustive.kt")
|
||||||
public void testIfWhenUnitExhaustive() throws Exception {
|
public void testIfWhenUnitExhaustive() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/ifWhenUnitExhaustive.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/ifWhenUnitExhaustive.kt");
|
||||||
@@ -4864,6 +4888,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("lambdaWhenUnitNonExhaustive.kt")
|
||||||
public void testLambdaWhenUnitNonExhaustive() throws Exception {
|
public void testLambdaWhenUnitNonExhaustive() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/lambdaWhenUnitNonExhaustive.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/lambdaWhenUnitNonExhaustive.kt");
|
||||||
@@ -4900,6 +4930,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("whenUnitExhaustive.kt")
|
||||||
public void testWhenUnitExhaustive() throws Exception {
|
public void testWhenUnitExhaustive() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/whenUnitExhaustive.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/convertToExpressionBody/whenUnitExhaustive.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user