From 7a24429b53497f82408fa1fceabb30d0b5934403 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 27 May 2016 18:00:31 +0300 Subject: [PATCH] Simplify for intention: apply name validator to prevent conflicts --- .../kotlin/idea/intentions/SimplifyForIntention.kt | 13 ++++++++++--- .../iterationOverMap/DataClassNameConflict.kt | 12 ++++++++++++ .../iterationOverMap/DataClassNameConflict.kt.after | 12 ++++++++++++ .../iterationOverMap/inspectionData/expected.xml | 8 ++++++++ .../idea/intentions/IntentionTestGenerated.java | 6 ++++++ 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt create mode 100644 idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt index f158f854067..e7936866790 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt @@ -25,6 +25,8 @@ import com.intellij.util.Query import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult +import org.jetbrains.kotlin.idea.core.KotlinNameSuggester +import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.lexer.KtTokens @@ -34,7 +36,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import java.util.* import kotlin.collections.forEach class SimplifyForInspection : IntentionBasedInspection(SimplifyForIntention()) @@ -51,13 +53,18 @@ class SimplifyForIntention : SelfTargetingRangeIntention( val loopParameter = element.loopParameter ?: return val factory = KtPsiFactory(element) - loopParameter.replace(factory.createDestructuringDeclarationInFor("(${usagesToRemove.joinToString { it.name!! }})")) + val validator = NewDeclarationNameValidator(element.parent, element, NewDeclarationNameValidator.Target.VARIABLES, + usagesToRemove.map { it.properties }.flatten()) + val names = ArrayList() usagesToRemove.forEach { p -> + val name = KotlinNameSuggester.suggestNameByName(p.name!!, validator) p.properties.firstOrNull()?.delete() p.usersToReplace.forEach { - it.replace(factory.createExpression(p.name!!)) + it.replace(factory.createExpression(name)) } + names.add(name) } + loopParameter.replace(factory.createDestructuringDeclarationInFor("(${names.joinToString()})")) if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) { loopRange.replace(loopRange.receiverExpression) diff --git a/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt b/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt new file mode 100644 index 00000000000..b1a92b67cda --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt @@ -0,0 +1,12 @@ +// WITH_RUNTIME + +data class XY(val x: Int, val y: Int) + +fun foo(list: List) { + val y = list.size + for (element in list) { + val x = element.x + element.y + println(x) + println(y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt.after b/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt.after new file mode 100644 index 00000000000..a27488c51af --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt.after @@ -0,0 +1,12 @@ +// WITH_RUNTIME + +data class XY(val x: Int, val y: Int) + +fun foo(list: List) { + val y = list.size + for ((x1, y1) in list) { + val x = x1 + y1 + println(x) + println(y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml b/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml index 8ea31054701..dacd983c223 100644 --- a/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml +++ b/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml @@ -167,4 +167,12 @@ 'for' that can be simplified using destructing declaration Simplify 'for' using destructing declaration + + DataClassNameConflict.kt + 7 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + \ 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 fe34d136076..5d9e71d8357 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -6555,6 +6555,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("DataClassNameConflict.kt") + public void testDataClassNameConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassNameConflict.kt"); + doTest(fileName); + } + @TestMetadata("DataClassNoVariablesInside.kt") public void testDataClassNoVariablesInside() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt");