"Remove redundant let": fix destructuring declaration false positive
#KT-26042 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
7e8521d9dc
commit
2d2f1125a9
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
||||
@@ -105,11 +106,20 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention<Kt
|
||||
val bodyExpression = lambdaExpression.bodyExpression?.children?.singleOrNull() ?: return false
|
||||
|
||||
return when (bodyExpression) {
|
||||
is KtBinaryExpression -> element.parent !is KtSafeQualifiedExpression && bodyExpression.isApplicable(parameterName)
|
||||
is KtDotQualifiedExpression -> bodyExpression.isApplicable(parameterName)
|
||||
is KtCallExpression -> element.parent !is KtSafeQualifiedExpression
|
||||
&& lambdaExpression.functionLiteral.valueParameterReferences(bodyExpression).count() <= 1
|
||||
else -> false
|
||||
is KtBinaryExpression ->
|
||||
element.parent !is KtSafeQualifiedExpression && bodyExpression.isApplicable(parameterName)
|
||||
is KtDotQualifiedExpression ->
|
||||
bodyExpression.isApplicable(parameterName)
|
||||
is KtCallExpression ->
|
||||
if (element.parent is KtSafeQualifiedExpression) {
|
||||
false
|
||||
} else {
|
||||
val count = lambdaExpression.functionLiteral.valueParameterReferences(bodyExpression).count()
|
||||
val destructuringDeclaration = lambdaExpression.functionLiteral.valueParameters.firstOrNull()?.destructuringDeclaration
|
||||
count == 0 || (count == 1 && destructuringDeclaration == null)
|
||||
}
|
||||
else ->
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,13 +173,17 @@ class ReplaceSingleLineLetIntention : SelfTargetingOffsetIndependentIntention<Kt
|
||||
private fun KtExpression.nameUsed(name: String, except: KtNameReferenceExpression? = null): Boolean =
|
||||
anyDescendantOfType<KtNameReferenceExpression> { it != except && it.getReferencedName() == name }
|
||||
|
||||
private fun KtFunctionLiteral.valueParameterReferences(callExpression: KtCallExpression): List<KtReferenceExpression> {
|
||||
private fun KtFunctionLiteral.valueParameterReferences(callExpression: KtCallExpression): List<KtNameReferenceExpression> {
|
||||
val context = analyze(BodyResolveMode.PARTIAL)
|
||||
val descriptor = context[BindingContext.FUNCTION, this]?.valueParameters?.singleOrNull() ?: return emptyList()
|
||||
val name = descriptor.name.asString()
|
||||
val parameterDescriptor = context[BindingContext.FUNCTION, this]?.valueParameters?.singleOrNull() ?: return emptyList()
|
||||
val variableDescriptorByName = if (parameterDescriptor is ValueParameterDescriptorImpl.WithDestructuringDeclaration)
|
||||
parameterDescriptor.destructuringVariables.associate { it.name to it }
|
||||
else
|
||||
mapOf(parameterDescriptor.name to parameterDescriptor)
|
||||
return callExpression.valueArguments.flatMap { arg ->
|
||||
arg.collectDescendantsOfType<KtReferenceExpression>().filter {
|
||||
it.text == name && it.getResolvedCall(context)?.resultingDescriptor == descriptor
|
||||
arg.collectDescendantsOfType<KtNameReferenceExpression>().filter {
|
||||
val descriptor = variableDescriptorByName[it.getReferencedNameAsName()]
|
||||
descriptor != null && it.getResolvedCall(context)?.resultingDescriptor == descriptor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test() {
|
||||
(1 to 2).let<caret> { (i, j) -> foo() }
|
||||
}
|
||||
|
||||
fun foo() = 0
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test() {
|
||||
foo()
|
||||
}
|
||||
|
||||
fun foo() = 0
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test() {
|
||||
(1 to 2).let<caret> { (i, j) -> foo(1, 2) }
|
||||
}
|
||||
|
||||
fun foo(i: Int, j: Int) = i + j
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test() {
|
||||
foo(1, 2)
|
||||
}
|
||||
|
||||
fun foo(i: Int, j: Int) = i + j
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// WITH_RUNTIME
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
fun test() {
|
||||
(1 to 2).let<caret> { (i, j) -> foo(i, 3) }
|
||||
}
|
||||
|
||||
fun foo(i: Int, j: Int) = i + j
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
fun test(k: Int) {
|
||||
(1 to 2).let<caret> { (i, j) -> i + k }
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
fun test() {
|
||||
(1 to 2).let<caret> { (i, j) -> i.toLong() }
|
||||
}
|
||||
@@ -13912,6 +13912,31 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/comparisons.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuringDeclaration.kt")
|
||||
public void testDestructuringDeclaration() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/destructuringDeclaration.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuringDeclaration2.kt")
|
||||
public void testDestructuringDeclaration2() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/destructuringDeclaration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuringDeclaration3.kt")
|
||||
public void testDestructuringDeclaration3() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/destructuringDeclaration3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuringDeclaration4.kt")
|
||||
public void testDestructuringDeclaration4() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/destructuringDeclaration4.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("destructuringDeclaration5.kt")
|
||||
public void testDestructuringDeclaration5() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/destructuringDeclaration5.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dotWithComparison.kt")
|
||||
public void testDotWithComparison() throws Exception {
|
||||
runTest("idea/testData/intentions/replaceSingleLineLetIntention/dotWithComparison.kt");
|
||||
|
||||
Reference in New Issue
Block a user