diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/DestructureIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/DestructureIntention.kt index 1d848d05ecb4..80c0f88c178d 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/DestructureIntention.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/DestructureIntention.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade @@ -233,6 +234,7 @@ class DestructureIntention : SelfTargetingRangeIntention( usageScopeElement.iterateOverDataClassPropertiesUsagesWithIndex( context, nameToSearch, + variableDescriptor, constructorParameterNameMap, { index, usageData -> noBadUsages = usagesToRemove[index].add(usageData, index) && noBadUsages }, { noBadUsages = false } @@ -285,31 +287,35 @@ class DestructureIntention : SelfTargetingRangeIntention( private fun PsiElement.iterateOverDataClassPropertiesUsagesWithIndex( context: BindingContext, parameterName: Name, + variableDescriptor: VariableDescriptor, constructorParameterNameMap: Map, process: (Int, SingleUsageData) -> Unit, cancel: () -> Unit ) { anyDescendantOfType { - if (it.getReferencedNameAsName() != parameterName) false - else { - val applicableUsage = getDataIfUsageIsApplicable(it, context) - if (applicableUsage != null) { - val usageDescriptor = applicableUsage.descriptor - if (usageDescriptor == null) { - for (parameter in constructorParameterNameMap.values) { + when { + it.getReferencedNameAsName() != parameterName -> false + it.getResolvedCall(context)?.resultingDescriptor != variableDescriptor -> false + else -> { + val applicableUsage = getDataIfUsageIsApplicable(it, context) + if (applicableUsage != null) { + val usageDescriptor = applicableUsage.descriptor + if (usageDescriptor == null) { + for (parameter in constructorParameterNameMap.values) { + process(parameter.index, applicableUsage) + } + return@anyDescendantOfType false + } + val parameter = constructorParameterNameMap[usageDescriptor.name] + if (parameter != null) { process(parameter.index, applicableUsage) + return@anyDescendantOfType false } - return@anyDescendantOfType false } - val parameter = constructorParameterNameMap[usageDescriptor.name] - if (parameter != null) { - process(parameter.index, applicableUsage) - return@anyDescendantOfType false - } - } - cancel() - true + cancel() + true + } } } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index e38b44859ef0..1ef0be16bd0e 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -8531,6 +8531,16 @@ public abstract class IntentionTestGenerated extends AbstractIntentionTest { runTest("testData/intentions/destructuringInLambda/pair.kt"); } + @TestMetadata("sameNameReferences.kt") + public void testSameNameReferences() throws Exception { + runTest("testData/intentions/destructuringInLambda/sameNameReferences.kt"); + } + + @TestMetadata("sameNameReferences2.kt") + public void testSameNameReferences2() throws Exception { + runTest("testData/intentions/destructuringInLambda/sameNameReferences2.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("testData/intentions/destructuringInLambda/simple.kt"); @@ -8579,6 +8589,11 @@ public abstract class IntentionTestGenerated extends AbstractIntentionTest { runTest("testData/intentions/destructuringVariables/noInitializer.kt"); } + @TestMetadata("sameNameReferences.kt") + public void testSameNameReferences() throws Exception { + runTest("testData/intentions/destructuringVariables/sameNameReferences.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("testData/intentions/destructuringVariables/simple.kt"); diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/inspectionData/expected.xml b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/inspectionData/expected.xml index de4a0a51cc08..1f8a7ccd0d39 100644 --- a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/inspectionData/expected.xml +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/inspectionData/expected.xml @@ -79,4 +79,12 @@ Use destructuring declaration Use destructuring declaration + + sameNameReferences.kt + 9 + light_idea_test_case + + Use destructuring declaration + Use destructuring declaration + \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt new file mode 100644 index 000000000000..4c0b3b1ed487 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt @@ -0,0 +1,13 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(f: (D) -> Int) { +} + +fun bar() {} + +fun test() { + foo { bar -> + bar() + bar.v1 + bar.v2 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt.after b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt.after new file mode 100644 index 000000000000..da4ed1efba05 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences.kt.after @@ -0,0 +1,13 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(f: (D) -> Int) { +} + +fun bar() {} + +fun test() { + foo { (v1, v2) -> + bar() + v1 + v2 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt new file mode 100644 index 000000000000..7906cd7c333c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt @@ -0,0 +1,13 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(f: (D) -> Int) { +} + +fun it() {} + +fun test() { + foo { + it() + it.v1 + it.v2 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt.after b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt.after new file mode 100644 index 000000000000..a9a0afcb8705 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringInLambda/sameNameReferences2.kt.after @@ -0,0 +1,13 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(f: (D) -> Int) { +} + +fun it() {} + +fun test() { + foo { (v1, v2) -> + it() + v1 + v2 + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt b/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt new file mode 100644 index 000000000000..ca09de481490 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt @@ -0,0 +1,8 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(): D = D(1, 2) + +fun test(): Int { + val foo = foo() + return foo.v1 + foo.v2 +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt.after b/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt.after new file mode 100644 index 000000000000..1c209f1a2c34 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/intentions/destructuringVariables/sameNameReferences.kt.after @@ -0,0 +1,8 @@ +data class D(val v1: Int, val v2: Int) + +fun foo(): D = D(1, 2) + +fun test(): Int { + val (v1, v2) = foo() + return v1 + v2 +} \ No newline at end of file