Don't suggest 'remove let' when 'it' is used multiple times
So #KT-16857 Fixed
This commit is contained in:
@@ -78,7 +78,7 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention<Kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isApplicableTo(element: KtCallExpression): Boolean {
|
override fun isApplicableTo(element: KtCallExpression): Boolean {
|
||||||
if (!isLetMethod(element)) return false
|
if (!element.isLetMethodCall()) return false
|
||||||
val lambdaExpression = element.lambdaArguments.firstOrNull()?.getLambdaExpression() ?: return false
|
val lambdaExpression = element.lambdaArguments.firstOrNull()?.getLambdaExpression() ?: return false
|
||||||
val parameterName = lambdaExpression.getParameterName() ?: return false
|
val parameterName = lambdaExpression.getParameterName() ?: return false
|
||||||
val bodyExpression = lambdaExpression.bodyExpression?.children?.singleOrNull() ?: return false
|
val bodyExpression = lambdaExpression.bodyExpression?.children?.singleOrNull() ?: return false
|
||||||
@@ -99,32 +99,26 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention<Kt
|
|||||||
}
|
}
|
||||||
|
|
||||||
val right = right ?: return false
|
val right = right ?: return false
|
||||||
when (right) {
|
return when (right) {
|
||||||
is KtNameReferenceExpression -> return right.text != parameterName
|
is KtNameReferenceExpression -> right.text != parameterName
|
||||||
is KtDotQualifiedExpression -> {
|
is KtDotQualifiedExpression -> !right.hasLambdaExpression() && !right.nameUsed(parameterName)
|
||||||
if (right.isParameterLeftMostReceiver(parameterName)) return false
|
is KtConstantExpression -> true
|
||||||
if (right.hasLambdaExpression()) return false
|
else -> false
|
||||||
return !right.receiverUsedAsArgument(parameterName)
|
|
||||||
}
|
|
||||||
is KtConstantExpression -> return true
|
|
||||||
else -> return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtDotQualifiedExpression.isApplicable(parameterName: String): Boolean {
|
private fun KtDotQualifiedExpression.isApplicable(parameterName: String) =
|
||||||
if (!isParameterLeftMostReceiver(parameterName)) return false
|
!hasLambdaExpression() && getLeftMostReceiverExpression().let { receiver ->
|
||||||
if (hasLambdaExpression()) return false
|
receiver is KtNameReferenceExpression &&
|
||||||
return !receiverUsedAsArgument(parameterName)
|
receiver.getReferencedName() == parameterName &&
|
||||||
}
|
!nameUsed(parameterName, except = receiver)
|
||||||
|
}
|
||||||
|
|
||||||
private fun KtDotQualifiedExpression.hasLambdaExpression()
|
private fun KtDotQualifiedExpression.hasLambdaExpression()
|
||||||
= selectorExpression?.anyDescendantOfType<KtLambdaExpression>() ?: false
|
= selectorExpression?.anyDescendantOfType<KtLambdaExpression>() ?: false
|
||||||
|
|
||||||
private fun KtDotQualifiedExpression.isParameterLeftMostReceiver(parameterName: String)
|
private fun KtCallExpression.isLetMethodCall() =
|
||||||
= getLeftMostReceiverExpression().text == parameterName
|
calleeExpression?.text == "let" && isMethodCall("kotlin.let")
|
||||||
|
|
||||||
private fun isLetMethod(element: KtCallExpression) =
|
|
||||||
element.calleeExpression?.text == "let" && element.isMethodCall("kotlin.let")
|
|
||||||
|
|
||||||
private fun KtLambdaExpression.getParameterName(): String? {
|
private fun KtLambdaExpression.getParameterName(): String? {
|
||||||
val parameters = valueParameters
|
val parameters = valueParameters
|
||||||
@@ -132,16 +126,6 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention<Kt
|
|||||||
return if (parameters.size == 1) parameters[0].text else "it"
|
return if (parameters.size == 1) parameters[0].text else "it"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtDotQualifiedExpression.receiverUsedAsArgument(receiverName: String): Boolean {
|
private fun KtExpression.nameUsed(name: String, except: KtNameReferenceExpression? = null): Boolean =
|
||||||
(selectorExpression as? KtCallExpression)?.valueArguments?.let {
|
anyDescendantOfType<KtNameReferenceExpression> { it != except && it.getReferencedName() == name }
|
||||||
if (it.any { it.receiverUsedAsArgument(receiverName) }) return true
|
|
||||||
}
|
|
||||||
return (receiverExpression as? KtDotQualifiedExpression)?.receiverUsedAsArgument(receiverName) ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KtValueArgument.receiverUsedAsArgument(receiverName: String) =
|
|
||||||
text == receiverName || anyDescendantOfType<KtDotQualifiedExpression> {
|
|
||||||
it.getLeftMostReceiverExpression().text == receiverName ||
|
|
||||||
it.receiverUsedAsArgument(receiverName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(s: String) {
|
||||||
|
if (s.substring(1).let<caret> { it.startsWith("a") || it[1].isLowerCase() }) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13368,6 +13368,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("plusNullable.kt")
|
||||||
public void testPlusNullable() throws Exception {
|
public void testPlusNullable() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceSingleLineLetIntention/plusNullable.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/replaceSingleLineLetIntention/plusNullable.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user