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)
loopParameter.replace(factory.createDestructuringDeclarationInFor("(${usagesToRemove.joinToString { it.name!! }})"))
usagesToRemove.forEach { p ->
p.property?.delete()
p.properties.firstOrNull()?.delete()
p.usersToReplace.forEach {
it.replace(factory.createExpression(p.name!!))
}
@@ -97,7 +97,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
{ 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
}
}
@@ -116,7 +116,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
val notNullUsages = usagesToRemove.filterNotNull().filter { it.name != 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
}
}
@@ -192,13 +192,13 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
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 descriptor: CallableDescriptor,
val name: String? = property?.name
val name: String? = properties.firstOrNull()?.name
) {
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)
}
@@ -206,7 +206,8 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
private operator fun UsageData?.plus(newData: UsageData): UsageData {
if (this == null) return newData
val allUsersToReplace = usersToReplace + newData.usersToReplace
if (property != null) return copy(usersToReplace = allUsersToReplace)
else return newData.copy(usersToReplace = allUsersToReplace)
val allProperties = properties + newData.properties
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);
}
@TestMetadata("DataClassTwoDifferentLocals.kt")
public void testDataClassTwoDifferentLocals() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassTwoDifferentLocals.kt");
doTest(fileName);
}
@TestMetadata("DataClassUnused.kt")
public void testDataClassUnused() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassUnused.kt");