if then to elvis: propose transformation to 'let' #KT-26653 Fixed

This commit is contained in:
Toshiaki Kameyama
2018-09-08 17:16:25 +03:00
committed by Mikhail Glukhikh
parent 539c55c5b2
commit 1c8e75eb34
11 changed files with 89 additions and 15 deletions
@@ -93,12 +93,14 @@ class IfThenToSafeAccessInspection : AbstractApplicabilityBasedInspection<KtIfEx
else -> false
}
private fun KtSafeQualifiedExpression.renameLetParameter(editor: Editor) {
val callExpression = selectorExpression as? KtCallExpression ?: return
if (callExpression.calleeExpression?.text != "let") return
val parameter = callExpression.lambdaArguments.singleOrNull()?.getLambdaExpression()?.valueParameters?.singleOrNull() ?: return
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
editor.caretModel.moveToOffset(parameter.startOffset)
KotlinVariableInplaceRenameHandler().doRename(parameter, editor, null)
companion object {
internal fun KtSafeQualifiedExpression.renameLetParameter(editor: Editor) {
val callExpression = selectorExpression as? KtCallExpression ?: return
if (callExpression.calleeExpression?.text != "let") return
val parameter = callExpression.lambdaArguments.singleOrNull()?.getLambdaExpression()?.valueParameters?.singleOrNull() ?: return
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
editor.caretModel.moveToOffset(parameter.startOffset)
KotlinVariableInplaceRenameHandler().doRename(parameter, editor, null)
}
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.inspections.branchedTransformations.IfThenToSafeAccessInspection
import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
@@ -54,6 +55,8 @@ class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpre
false
baseClause.evaluatesTo(receiverExpression) ->
true
baseClause.anyArgumentEvaluatesTo(receiverExpression) ->
true
hasImplicitReceiverReplaceableBySafeCall() || baseClause.hasFirstReceiverOf(receiverExpression) ->
!baseClause.hasNullableType(context)
else ->
@@ -95,6 +98,9 @@ class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpre
if (editor != null) {
elvis.inlineLeftSideIfApplicableWithPrompt(editor)
with(IfThenToSafeAccessInspection) {
(elvis.left as? KtSafeQualifiedExpression)?.renameLetParameter(editor)
}
}
}
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
fun foo(s: String?) {
val x = <caret>if (s != null) {
bar(s)
}
else {
13
}
}
fun bar(s: String): Int = 42
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(s: String?) {
val x = s?.let { bar(it) } ?: 13
}
fun bar(s: String): Int = 42
@@ -0,0 +1,12 @@
// WITH_RUNTIME
fun foo(it: String?) {
val x = <caret>if (it != null) {
bar(it)
}
else {
13
}
}
fun bar(s: String): Int = 42
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(it: String?) {
val x = it?.let { it1 -> bar(it1) } ?: 13
}
fun bar(s: String): Int = 42
@@ -1,4 +1,3 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
class Test {
@@ -6,9 +5,8 @@ class Test {
return param1
}
fun doAThingIfPresent(param1: String?) {
// In theory could propose transformation to 'let'
<caret>if (param1 != null) {
fun doAThingIfPresent(param1: String?): String {
return <caret>if (param1 != null) {
doAThing(param1)
} else {
""
@@ -0,0 +1,11 @@
// WITH_RUNTIME
class Test {
fun doAThing(param1: String): String {
return param1
}
fun doAThingIfPresent(param1: String?): String {
return param1?.let { doAThing(it) } ?: ""
}
}
@@ -1,4 +1,3 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
class Test {
@@ -6,9 +5,8 @@ class Test {
return param1
}
fun doAThingIfPresent(param1: String?) {
// In theory could propose transformation to 'let'
<caret>if (param1 is String) {
fun doAThingIfPresent(param1: Any?): String {
return <caret>if (param1 is String) {
doAThing(param1)
} else {
""
@@ -0,0 +1,11 @@
// WITH_RUNTIME
class Test {
fun doAThing(param1: String): String {
return param1
}
fun doAThingIfPresent(param1: Any?): String {
return (param1 as? String)?.let { doAThing(it) } ?: ""
}
}
@@ -2441,6 +2441,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/branched/ifThenToElvis/otherBlockHasMoreThanOneStatement.kt");
}
@TestMetadata("replaceWithLet.kt")
public void testReplaceWithLet() throws Exception {
runTest("idea/testData/intentions/branched/ifThenToElvis/replaceWithLet.kt");
}
@TestMetadata("replaceWithLetAndRenameIt.kt")
public void testReplaceWithLetAndRenameIt() throws Exception {
runTest("idea/testData/intentions/branched/ifThenToElvis/replaceWithLetAndRenameIt.kt");
}
@TestMetadata("replaceWithLetInMember.kt")
public void testReplaceWithLetInMember() throws Exception {
runTest("idea/testData/intentions/branched/ifThenToElvis/replaceWithLetInMember.kt");