Simplify for intention: apply name validator to prevent conflicts

This commit is contained in:
Mikhail Glukhikh
2016-05-27 18:00:31 +03:00
parent 792b37bce4
commit 7a24429b53
5 changed files with 48 additions and 3 deletions
@@ -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<KtForExpression>(SimplifyForIntention())
@@ -51,13 +53,18 @@ class SimplifyForIntention : SelfTargetingRangeIntention<KtForExpression>(
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<String>()
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)
@@ -0,0 +1,12 @@
// WITH_RUNTIME
data class XY(val x: Int, val y: Int)
fun foo(list: List<XY>) {
val y = list.size
for (<caret>element in list) {
val x = element.x + element.y
println(x)
println(y)
}
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
data class XY(val x: Int, val y: Int)
fun foo(list: List<XY>) {
val y = list.size
for ((x1, y1) in list) {
val x = x1 + y1
println(x)
println(y)
}
}
@@ -167,4 +167,12 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'for' that can be simplified using destructing declaration</problem_class>
<description>Simplify 'for' using destructing declaration</description>
</problem>
<problem>
<file>DataClassNameConflict.kt</file>
<line>7</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/DataClassNameConflict.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'for' that can be simplified using destructing declaration</problem_class>
<description>Simplify 'for' using destructing declaration</description>
</problem>
</problems>
@@ -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");