From b12199036813993ae1c6981a1c38d9e030e3e1d2 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 23 Mar 2017 15:32:36 +0300 Subject: [PATCH] Don't suggest 'remove let' when 'it' is used multiple times So #KT-16857 Fixed --- .../ReplaceSingleLineLetIntention.kt | 48 +++++++------------ .../multipleUsages.kt | 8 ++++ .../intentions/IntentionTestGenerated.java | 6 +++ 3 files changed, 30 insertions(+), 32 deletions(-) create mode 100644 idea/testData/intentions/replaceSingleLineLetIntention/multipleUsages.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceSingleLineLetIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceSingleLineLetIntention.kt index 26ef7329955..8f09bad959a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceSingleLineLetIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceSingleLineLetIntention.kt @@ -78,7 +78,7 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention return right.text != parameterName - is KtDotQualifiedExpression -> { - if (right.isParameterLeftMostReceiver(parameterName)) return false - if (right.hasLambdaExpression()) return false - return !right.receiverUsedAsArgument(parameterName) - } - is KtConstantExpression -> return true - else -> return false + return when (right) { + is KtNameReferenceExpression -> right.text != parameterName + is KtDotQualifiedExpression -> !right.hasLambdaExpression() && !right.nameUsed(parameterName) + is KtConstantExpression -> true + else -> false } } - private fun KtDotQualifiedExpression.isApplicable(parameterName: String): Boolean { - if (!isParameterLeftMostReceiver(parameterName)) return false - if (hasLambdaExpression()) return false - return !receiverUsedAsArgument(parameterName) - } + private fun KtDotQualifiedExpression.isApplicable(parameterName: String) = + !hasLambdaExpression() && getLeftMostReceiverExpression().let { receiver -> + receiver is KtNameReferenceExpression && + receiver.getReferencedName() == parameterName && + !nameUsed(parameterName, except = receiver) + } private fun KtDotQualifiedExpression.hasLambdaExpression() = selectorExpression?.anyDescendantOfType() ?: false - private fun KtDotQualifiedExpression.isParameterLeftMostReceiver(parameterName: String) - = getLeftMostReceiverExpression().text == parameterName - - private fun isLetMethod(element: KtCallExpression) = - element.calleeExpression?.text == "let" && element.isMethodCall("kotlin.let") + private fun KtCallExpression.isLetMethodCall() = + calleeExpression?.text == "let" && isMethodCall("kotlin.let") private fun KtLambdaExpression.getParameterName(): String? { val parameters = valueParameters @@ -132,16 +126,6 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention { - it.getLeftMostReceiverExpression().text == receiverName || - it.receiverUsedAsArgument(receiverName) - } + private fun KtExpression.nameUsed(name: String, except: KtNameReferenceExpression? = null): Boolean = + anyDescendantOfType { it != except && it.getReferencedName() == name } } \ No newline at end of file diff --git a/idea/testData/intentions/replaceSingleLineLetIntention/multipleUsages.kt b/idea/testData/intentions/replaceSingleLineLetIntention/multipleUsages.kt new file mode 100644 index 00000000000..c6c5b260b57 --- /dev/null +++ b/idea/testData/intentions/replaceSingleLineLetIntention/multipleUsages.kt @@ -0,0 +1,8 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +fun foo(s: String) { + if (s.substring(1).let { it.startsWith("a") || it[1].isLowerCase() }) { + + } +} \ 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 69b8d4f4143..d23a75da03b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -13368,6 +13368,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("multipleUsages.kt") + public void testMultipleUsages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceSingleLineLetIntention/multipleUsages.kt"); + doTest(fileName); + } + @TestMetadata("plusNullable.kt") public void testPlusNullable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceSingleLineLetIntention/plusNullable.kt");