diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToIfIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToIfIntention.kt index 11a87aa74db..fb1ed05c222 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToIfIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToIfIntention.kt @@ -19,15 +19,16 @@ package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions import com.intellij.codeInsight.intention.LowPriorityAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention -import org.jetbrains.kotlin.psi.KtIfExpression -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtReturnExpression -import org.jetbrains.kotlin.psi.createExpressionByPattern +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.types.typeUtil.isNothing class UnfoldReturnToIfIntention : SelfTargetingRangeIntention(KtReturnExpression::class.java, "Replace return with 'if' expression"), LowPriorityAction { override fun applicabilityRange(element: KtReturnExpression): TextRange? { @@ -37,14 +38,29 @@ class UnfoldReturnToIfIntention : SelfTargetingRangeIntention "" + else -> if (expr.getResolvedCall(context)?.resultingDescriptor?.returnType?.isNothing() == true) "" else "return " + } + return psiFactory.createExpressionByPattern("$returnText$0", expr) + } + } + } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToWhenIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToWhenIntention.kt index ba044037975..7024d723a9e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToWhenIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/UnfoldReturnToWhenIntention.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions import com.intellij.codeInsight.intention.LowPriorityAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention import org.jetbrains.kotlin.psi.* @@ -35,14 +36,17 @@ class UnfoldReturnToWhenIntention : SelfTargetingRangeIntention val expr = entry.expression!!.lastBlockStatementOrThis() - expr.replace(KtPsiFactory(element).createExpressionByPattern("return $0", expr)) + val newExpr = newEntry.expression!!.lastBlockStatementOrThis() + newExpr.replace(UnfoldReturnToIfIntention.createReturnExpression(expr, psiFactory, context)) } - element.replace(newWhenExpression) } } diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt new file mode 100644 index 00000000000..8362ab31c17 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt @@ -0,0 +1,10 @@ +fun test(b: Boolean): Int { + while (true) { + return if (b) { + 1 + } else { + break + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt.after b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt.after new file mode 100644 index 00000000000..468d555bcb3 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt.after @@ -0,0 +1,10 @@ +fun test(b: Boolean): Int { + while (true) { + if (b) { + return 1 + } else { + break + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt new file mode 100644 index 00000000000..c98396e8099 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt @@ -0,0 +1,12 @@ +fun test(b: Boolean): Int { + var i = 0 + while (i == 0) { + return if (b) { + 1 + } else { + i++ + continue + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt.after b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt.after new file mode 100644 index 00000000000..9f45ed533bf --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt.after @@ -0,0 +1,12 @@ +fun test(b: Boolean): Int { + var i = 0 + while (i == 0) { + if (b) { + return 1 + } else { + i++ + continue + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt new file mode 100644 index 00000000000..3ce0b05384c --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt @@ -0,0 +1,9 @@ +fun test(b: Boolean): Int { + while (true) { + return if (b) { + 1 + } else { + return 0 + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt.after b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt.after new file mode 100644 index 00000000000..5b258374ff1 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt.after @@ -0,0 +1,9 @@ +fun test(b: Boolean): Int { + while (true) { + if (b) { + return 1 + } else { + return 0 + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt new file mode 100644 index 00000000000..32c44b6c856 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +fun test(b: Boolean): Int { + return if (b) { + 1 + } else { + TODO() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt.after b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt.after new file mode 100644 index 00000000000..1c40de6e470 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME +fun test(b: Boolean): Int { + if (b) { + return 1 + } else { + TODO() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt new file mode 100644 index 00000000000..be8aaaa7e9e --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt @@ -0,0 +1,7 @@ +fun test(b: Boolean): Int { + return if (b) { + throw AssertionError() + } else { + 1 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt.after b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt.after new file mode 100644 index 00000000000..f591130d407 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt.after @@ -0,0 +1,7 @@ +fun test(b: Boolean): Int { + if (b) { + throw AssertionError() + } else { + return 1 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt new file mode 100644 index 00000000000..ae9b24a166a --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt @@ -0,0 +1,9 @@ +fun test(b: Boolean): Int { + loop@ while (true) { + return when (b) { + true -> 1 + else -> break@loop + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt.after b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt.after new file mode 100644 index 00000000000..600f721c9d6 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt.after @@ -0,0 +1,9 @@ +fun test(b: Boolean): Int { + loop@ while (true) { + when (b) { + true -> return 1 + else -> break@loop + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt new file mode 100644 index 00000000000..e37b85d894b --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt @@ -0,0 +1,13 @@ +fun test(b: Boolean): Int { + var i = 0 + loop@while (i == 0) { + return when (b) { + true -> 1 + else -> { + i++ + continue@loop + } + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt.after b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt.after new file mode 100644 index 00000000000..449aac51602 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt.after @@ -0,0 +1,13 @@ +fun test(b: Boolean): Int { + var i = 0 + loop@while (i == 0) { + when (b) { + true -> return 1 + else -> { + i++ + continue@loop + } + } + } + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt new file mode 100644 index 00000000000..10a93596237 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt @@ -0,0 +1,8 @@ +fun test(b: Boolean): Int { + while (true) { + return when (b) { + true -> 1 + else -> return 0 + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt.after b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt.after new file mode 100644 index 00000000000..2e3650f0dd7 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt.after @@ -0,0 +1,8 @@ +fun test(b: Boolean): Int { + while (true) { + when (b) { + true -> return 1 + else -> return 0 + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt new file mode 100644 index 00000000000..9cd2eb4c9b1 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME +fun test(b: Boolean): Int { + return when (b) { + true -> 1 + else -> TODO() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt.after b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt.after new file mode 100644 index 00000000000..9140e3c9c55 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME +fun test(b: Boolean): Int { + when (b) { + true -> return 1 + else -> TODO() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt new file mode 100644 index 00000000000..a3f1a983066 --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt @@ -0,0 +1,6 @@ +fun foo(b: Boolean): Int { + return when (b) { + true -> throw AssertionError() + else -> 1 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt.after b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt.after new file mode 100644 index 00000000000..8f2496d3e6c --- /dev/null +++ b/idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt.after @@ -0,0 +1,6 @@ +fun foo(b: Boolean): Int { + when (b) { + true -> throw AssertionError() + else -> return 1 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index ae4b3155106..e44e27786a5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -2467,6 +2467,36 @@ public class IntentionTestGenerated extends AbstractIntentionTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/branched/unfolding/returnToIf"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } + @TestMetadata("ifWithBreak.kt") + public void testIfWithBreak() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/ifWithBreak.kt"); + doTest(fileName); + } + + @TestMetadata("ifWithContinue.kt") + public void testIfWithContinue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/ifWithContinue.kt"); + doTest(fileName); + } + + @TestMetadata("ifWithInnerReturn.kt") + public void testIfWithInnerReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/ifWithInnerReturn.kt"); + doTest(fileName); + } + + @TestMetadata("ifWithNothing.kt") + public void testIfWithNothing() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/ifWithNothing.kt"); + doTest(fileName); + } + + @TestMetadata("ifWithThrow.kt") + public void testIfWithThrow() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/ifWithThrow.kt"); + doTest(fileName); + } + @TestMetadata("innerIfTransformed.kt") public void testInnerIfTransformed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToIf/innerIfTransformed.kt"); @@ -2511,6 +2541,36 @@ public class IntentionTestGenerated extends AbstractIntentionTest { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/simpleWhenWithBlocks.kt"); doTest(fileName); } + + @TestMetadata("whenWithBreak.kt") + public void testWhenWithBreak() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/whenWithBreak.kt"); + doTest(fileName); + } + + @TestMetadata("whenWithContinue.kt") + public void testWhenWithContinue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/whenWithContinue.kt"); + doTest(fileName); + } + + @TestMetadata("whenWithInnerReturn.kt") + public void testWhenWithInnerReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/whenWithInnerReturn.kt"); + doTest(fileName); + } + + @TestMetadata("whenWithNothing.kt") + public void testWhenWithNothing() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/whenWithNothing.kt"); + doTest(fileName); + } + + @TestMetadata("whenWithThrow.kt") + public void testWhenWithThrow() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/unfolding/returnToWhen/whenWithThrow.kt"); + doTest(fileName); + } } }