Simplify for: take into account two or more possible local variables for the same loop parameter property

This commit is contained in:
Mikhail Glukhikh
2016-05-18 19:45:28 +03:00
parent 9108ab1923
commit f81192d48f
3 changed files with 27 additions and 8 deletions
@@ -50,7 +50,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
val factory = KtPsiFactory(element) val factory = KtPsiFactory(element)
loopParameter.replace(factory.createDestructuringDeclarationInFor("(${usagesToRemove.joinToString { it.name!! }})")) loopParameter.replace(factory.createDestructuringDeclarationInFor("(${usagesToRemove.joinToString { it.name!! }})"))
usagesToRemove.forEach { p -> usagesToRemove.forEach { p ->
p.property?.delete() p.properties.firstOrNull()?.delete()
p.usersToReplace.forEach { p.usersToReplace.forEach {
it.replace(factory.createExpression(p.name!!)) it.replace(factory.createExpression(p.name!!))
} }
@@ -97,7 +97,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
{ otherUsages = true } { otherUsages = true }
) )
if (!otherUsages && usagesToRemove.all { it != null && it.name != null}) { if (!otherUsages && usagesToRemove.all { it != null && it.name != null && it.properties.size <= 1 }) {
return usagesToRemove.mapNotNull { it } to removeSelectorInLoopRange return usagesToRemove.mapNotNull { it } to removeSelectorInLoopRange
} }
} }
@@ -116,7 +116,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
val notNullUsages = usagesToRemove.filterNotNull().filter { it.name != null } val notNullUsages = usagesToRemove.filterNotNull().filter { it.name != null }
val droppedLastUnused = usagesToRemove.dropLastWhile { it == null } val droppedLastUnused = usagesToRemove.dropLastWhile { it == null }
if (droppedLastUnused.size == notNullUsages.size) { if (droppedLastUnused.size == notNullUsages.size && droppedLastUnused.all { it != null && it.properties.size <= 1 } ) {
return notNullUsages to false return notNullUsages to false
} }
} }
@@ -192,13 +192,13 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
return UsageData(property, parentCall, descriptor) return UsageData(property, parentCall, descriptor)
} }
private data class UsageData(val property: KtProperty?, private data class UsageData(val properties: List<KtProperty>,
val usersToReplace: List<KtExpression>, val usersToReplace: List<KtExpression>,
val descriptor: CallableDescriptor, val descriptor: CallableDescriptor,
val name: String? = property?.name val name: String? = properties.firstOrNull()?.name
) { ) {
constructor(property: KtProperty?, user: KtExpression, descriptor: CallableDescriptor): constructor(property: KtProperty?, user: KtExpression, descriptor: CallableDescriptor):
this(property, if (property != null) emptyList() else listOf(user), descriptor) this(listOfNotNull(property), if (property != null) emptyList() else listOf(user), descriptor)
fun named(suggested: String) = if (name != null) this else copy(name = suggested) fun named(suggested: String) = if (name != null) this else copy(name = suggested)
} }
@@ -206,7 +206,8 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
private operator fun UsageData?.plus(newData: UsageData): UsageData { private operator fun UsageData?.plus(newData: UsageData): UsageData {
if (this == null) return newData if (this == null) return newData
val allUsersToReplace = usersToReplace + newData.usersToReplace val allUsersToReplace = usersToReplace + newData.usersToReplace
if (property != null) return copy(usersToReplace = allUsersToReplace) val allProperties = properties + newData.properties
else return newData.copy(usersToReplace = allUsersToReplace) if (properties.isNotEmpty()) return copy(properties = allProperties, usersToReplace = allUsersToReplace)
else return newData.copy(properties = allProperties, usersToReplace = allUsersToReplace)
} }
} }
@@ -0,0 +1,12 @@
// IS_APPLICABLE: false
// WITH_RUNTIME
data class XY(val x: String, val y: Int)
fun test(xys: Array<XY>) {
for (<caret>xy in xys) {
val x = xy.x
println(x)
val xx = xy.x
println(xx)
}
}
@@ -6579,6 +6579,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("DataClassTwoDifferentLocals.kt")
public void testDataClassTwoDifferentLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassTwoDifferentLocals.kt");
doTest(fileName);
}
@TestMetadata("DataClassUnused.kt") @TestMetadata("DataClassUnused.kt")
public void testDataClassUnused() throws Exception { public void testDataClassUnused() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassUnused.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassUnused.kt");