diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt index 536b9fcc11f..e19e563ec08 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt @@ -26,12 +26,13 @@ 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.inspections.IntentionBasedInspection +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* 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 kotlin.collections.forEach as forEachStdLib +import kotlin.collections.forEach class SimplifyForInspection : IntentionBasedInspection(SimplifyForIntention()) @@ -41,13 +42,19 @@ class SimplifyForIntention : SelfTargetingRangeIntention( "Simplify 'for'" ) { override fun applyTo(element: KtForExpression, editor: Editor?) { - val (propertiesToRemove, removeSelectorInLoopRange) = collectPropertiesToRemove(element) ?: return + val (usagesToRemove, removeSelectorInLoopRange) = collectUsagesToRemove(element) ?: return val loopRange = element.loopRange ?: return val loopParameter = element.loopParameter ?: return - loopParameter.replace(KtPsiFactory(element).createDestructuringDeclarationInFor("(${propertiesToRemove.joinToString { it.name!! }})")) - propertiesToRemove.forEachStdLib { p -> p.delete() } + val factory = KtPsiFactory(element) + loopParameter.replace(factory.createDestructuringDeclarationInFor("(${usagesToRemove.joinToString { it.name!! }})")) + usagesToRemove.forEach { p -> + p.property?.delete() + p.usersToReplace.forEach { + it.replace(factory.createExpression(p.name!!)) + } + } if (removeSelectorInLoopRange && loopRange is KtDotQualifiedExpression) { loopRange.replace(loopRange.receiverExpression) @@ -57,15 +64,15 @@ class SimplifyForIntention : SelfTargetingRangeIntention( override fun applicabilityRange(element: KtForExpression): TextRange? { if (element.destructuringParameter != null) return null - val propertiesToRemove = collectPropertiesToRemove(element) - if (propertiesToRemove != null && propertiesToRemove.first.isNotEmpty()) { + val usagesToRemove = collectUsagesToRemove(element) + if (usagesToRemove != null && usagesToRemove.first.isNotEmpty()) { return element.loopParameter!!.textRange } return null } // Note: list should contains properties in order to create destructing declaration - private fun collectPropertiesToRemove(element: KtForExpression): Pair, Boolean>? { + private fun collectUsagesToRemove(element: KtForExpression): Pair, Boolean>? { val loopParameter = element.loopParameter ?: return null val context = element.analyzeFullyAndGetResult().bindingContext @@ -74,45 +81,41 @@ class SimplifyForIntention : SelfTargetingRangeIntention( val classDescriptor = loopParameterDescriptor.type.constructor.declarationDescriptor as? ClassDescriptor ?: return null var otherUsages = false - var removeSelectorInLoopRange = false - val propertiesToRemove: Array + val usagesToRemove : Array if (DescriptorUtils.isSubclass(classDescriptor, classDescriptor.builtIns.mapEntry)) { val loopRangeDescriptorName = element.loopRange.getResolvedCall(context)?.resultingDescriptor?.name - if (loopRangeDescriptorName != null && - (loopRangeDescriptorName.asString().equals("entries") || loopRangeDescriptorName.asString().equals("entrySet"))) { - removeSelectorInLoopRange = true - } + val removeSelectorInLoopRange = loopRangeDescriptorName?.asString().let { it == "entries" || it == "entrySet" } - propertiesToRemove = arrayOfNulls(2) + usagesToRemove = arrayOfNulls(2) ReferencesSearch.search(loopParameter).iterateOverMapEntryPropertiesUsages( context, - { index, property -> propertiesToRemove[index] = property }, + { index, usageData -> usagesToRemove[index] += usageData.named(if (index == 0) "key" else "value") }, { otherUsages = true } ) - if (!otherUsages && propertiesToRemove.all { it != null }) { - return propertiesToRemove.mapNotNull { it } to removeSelectorInLoopRange + if (!otherUsages && usagesToRemove.all { it != null && it.name != null}) { + return usagesToRemove.mapNotNull { it } to removeSelectorInLoopRange } } else if (classDescriptor.isData) { val valueParameters = classDescriptor.unsubstitutedPrimaryConstructor?.valueParameters ?: return null - propertiesToRemove = arrayOfNulls(valueParameters.size) + usagesToRemove = arrayOfNulls(valueParameters.size) ReferencesSearch.search(loopParameter).iterateOverDataClassPropertiesUsagesWithIndex( context, classDescriptor, - { index, property -> propertiesToRemove[index] = property }, + { index, usageData -> usagesToRemove[index] += usageData.named(valueParameters[index].name.asString()) }, { otherUsages = true } ) if (otherUsages) return null - val notNullProperties = propertiesToRemove.filterNotNull() - val droppedLastUnused = propertiesToRemove.dropLastWhile { it == null } - if (droppedLastUnused.size == notNullProperties.size) { - return notNullProperties to removeSelectorInLoopRange + val notNullUsages = usagesToRemove.filterNotNull().filter { it.name != null } + val droppedLastUnused = usagesToRemove.dropLastWhile { it == null } + if (droppedLastUnused.size == notNullUsages.size) { + return notNullUsages to false } } @@ -121,20 +124,20 @@ class SimplifyForIntention : SelfTargetingRangeIntention( private fun Query.iterateOverMapEntryPropertiesUsages( context: BindingContext, - process: (Int, KtProperty) -> Unit, + process: (Int, UsageData) -> Unit, cancel: () -> Unit ) { // TODO: Remove SAM-constructor when KT-11265 will be fixed forEach(Processor forEach@{ val applicableUsage = getDataIfUsageIsApplicable(it, context) if (applicableUsage != null) { - val (property, descriptor) = applicableUsage - if (descriptor.name.asString().equals("key") || descriptor.name.asString().equals("getKey")) { - process(0, property) + val descriptorName = applicableUsage.descriptor.name.asString() + if (descriptorName.equals("key") || descriptorName.equals("getKey")) { + process(0, applicableUsage) return@forEach true } - else if (descriptor.name.asString().equals("value") || descriptor.name.asString().equals("getValue")) { - process(1, property) + else if (descriptorName.equals("value") || descriptorName.equals("getValue")) { + process(1, applicableUsage) return@forEach true } } @@ -147,7 +150,7 @@ class SimplifyForIntention : SelfTargetingRangeIntention( private fun Query.iterateOverDataClassPropertiesUsagesWithIndex( context: BindingContext, dataClass: ClassDescriptor, - process: (Int, KtProperty) -> Unit, + process: (Int, UsageData) -> Unit, cancel: () -> Unit ) { val valueParameters = dataClass.unsubstitutedPrimaryConstructor?.valueParameters ?: return @@ -155,10 +158,9 @@ class SimplifyForIntention : SelfTargetingRangeIntention( forEach(Processor forEach@{ val applicableUsage = getDataIfUsageIsApplicable(it, context) if (applicableUsage != null) { - val (property, descriptor) = applicableUsage for (valueParameter in valueParameters) { - if (context.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter) == descriptor) { - process(valueParameter.index, property) + if (context.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter) == applicableUsage.descriptor) { + process(valueParameter.index, applicableUsage) return@forEach true } } @@ -171,12 +173,37 @@ class SimplifyForIntention : SelfTargetingRangeIntention( private fun getDataIfUsageIsApplicable(usage: PsiReference, context: BindingContext): UsageData? { val parentCall = usage.element.parent as? KtExpression ?: return null - val property = parentCall.parent as? KtProperty ?: return null + val userParent = parentCall.parent + if (userParent is KtBinaryExpression) { + if (userParent.operationToken in KtTokens.ALL_ASSIGNMENTS && + userParent.left === parentCall) return null + } + if (userParent is KtUnaryExpression) { + if (userParent.operationToken === KtTokens.PLUSPLUS || userParent.operationToken === KtTokens.MINUSMINUS) return null + } + + val property = parentCall.parent as? KtProperty val resolvedCall = parentCall.getResolvedCall(context) ?: return null val descriptor = resolvedCall.resultingDescriptor - return UsageData(property, descriptor) + return UsageData(property, parentCall, descriptor) } - private data class UsageData(val property: KtProperty, val descriptor: CallableDescriptor) + private data class UsageData(val property: KtProperty?, + val usersToReplace: List, + val descriptor: CallableDescriptor, + val name: String? = property?.name + ) { + constructor(property: KtProperty?, user: KtExpression, descriptor: CallableDescriptor): + this(property, if (property != null) emptyList() else listOf(user), descriptor) + + fun named(suggested: String) = if (name != null) this else copy(name = suggested) + } + + 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) + } } \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassDependentLocal.kt b/idea/testData/intentions/iterationOverMap/DataClassDependentLocal.kt new file mode 100644 index 00000000000..85922d7fa37 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassDependentLocal.kt @@ -0,0 +1,12 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +data class XY(val x: Int, val y: Int) +fun test(xys: Array) { + for (xy in xys) { + val x = xy.x + println(x) + val y = xy.y + x + println(y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt b/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt new file mode 100644 index 00000000000..7e041ff0b3f --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + val xx = xy.x + println(xx + xy.y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt.after b/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt.after new file mode 100644 index 00000000000..ae8461c2298 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for ((xx, y) in xys) { + println(xx + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt new file mode 100644 index 00000000000..974f99dfdf8 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + println(xy.x + xy.y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt.after b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt.after new file mode 100644 index 00000000000..73dfab72d0e --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for ((x, y) in xys) { + println(x + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt new file mode 100644 index 00000000000..1a159071804 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + println(xy.x + xy.y + xy?.x + xy?.y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt.after b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt.after new file mode 100644 index 00000000000..5f794dfb21a --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for ((x, y) in xys) { + println(x + y + x + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt b/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt new file mode 100644 index 00000000000..a7640dc2790 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + println(xy.x + xy.y) + val xyx = xy.x + println(xyx + xy.y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt.after b/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt.after new file mode 100644 index 00000000000..a585bfaac51 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt.after @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for ((xyx, y) in xys) { + println(xyx + y) + println(xyx + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt b/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt new file mode 100644 index 00000000000..cd4c43c2d54 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + val y = xy.y + println(xy.x + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt.after b/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt.after new file mode 100644 index 00000000000..73dfab72d0e --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array) { + for ((x, y) in xys) { + println(x + y) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassWithAssignmentInside.kt b/idea/testData/intentions/iterationOverMap/DataClassWithAssignmentInside.kt new file mode 100644 index 00000000000..842e37c887e --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassWithAssignmentInside.kt @@ -0,0 +1,9 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +data class XY(var x: String, val y: String) +fun test(xys: Array) { + for (xy in xys) { + xy.x = xy.y + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt b/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt new file mode 100644 index 00000000000..f31dedd3dc7 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array, base: XY) { + for (xy in xys) { + if (xy.x == base.x) { + println(xy.y) + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt.after b/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt.after new file mode 100644 index 00000000000..47b3eb06324 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt.after @@ -0,0 +1,10 @@ +// WITH_RUNTIME + +data class XY(val x: String, val y: String) +fun test(xys: Array, base: XY) { + for ((x, y) in xys) { + if (x == base.x) { + println(y) + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/DataClassWithIncrementInside.kt b/idea/testData/intentions/iterationOverMap/DataClassWithIncrementInside.kt new file mode 100644 index 00000000000..b1e8688c6de --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/DataClassWithIncrementInside.kt @@ -0,0 +1,10 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +data class XY(var x: Int, var y: Int) +fun test(xys: Array) { + for (xy in xys) { + xy.x++ + xy.y-- + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/MapNoProperties.kt b/idea/testData/intentions/iterationOverMap/MapNoProperties.kt new file mode 100644 index 00000000000..e3b2637c108 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/MapNoProperties.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test(map: Map) { + for (entry in map.entries) { + if (entry.key == "my_name") println("My index is ${entry.value}") + } +} \ No newline at end of file diff --git a/idea/testData/intentions/iterationOverMap/MapNoProperties.kt.after b/idea/testData/intentions/iterationOverMap/MapNoProperties.kt.after new file mode 100644 index 00000000000..529d794f152 --- /dev/null +++ b/idea/testData/intentions/iterationOverMap/MapNoProperties.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME + +fun test(map: Map) { + for ((key, value) in map) { + if (key == "my_name") println("My index is ${value}") + } +} \ 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 82e465f9a19..611911fdb07 100644 --- a/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml +++ b/idea/testData/intentions/iterationOverMap/inspectionData/expected.xml @@ -71,4 +71,68 @@ Simplify 'for' using destructing declaration Simplify 'for' using destructing declaration + + DataClassNoVariablesInside.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassNoVariablesMultiUsages.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassPropertyBetweenUsages.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassSecondVariable.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassWithExternalUsage.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassDependentLocal.kt + 6 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + DataClassFirstVariable.kt + 5 + light_idea_test_case + + 'for' that can be simplified using destructing declaration + Simplify 'for' using destructing declaration + + + MapNoProperties.kt + 4 + 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 8d07af44241..4790426c13f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -6519,12 +6519,36 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("DataClassDependentLocal.kt") + public void testDataClassDependentLocal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassDependentLocal.kt"); + doTest(fileName); + } + @TestMetadata("DataClassFirstNPropertiesUsed.kt") public void testDataClassFirstNPropertiesUsed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassFirstNPropertiesUsed.kt"); doTest(fileName); } + @TestMetadata("DataClassFirstVariable.kt") + public void testDataClassFirstVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassFirstVariable.kt"); + doTest(fileName); + } + + @TestMetadata("DataClassNoVariablesInside.kt") + public void testDataClassNoVariablesInside() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassNoVariablesInside.kt"); + doTest(fileName); + } + + @TestMetadata("DataClassNoVariablesMultiUsages.kt") + public void testDataClassNoVariablesMultiUsages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassNoVariablesMultiUsages.kt"); + doTest(fileName); + } + @TestMetadata("DataClassNotAllPropertiesUsed.kt") public void testDataClassNotAllPropertiesUsed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassNotAllPropertiesUsed.kt"); @@ -6537,12 +6561,42 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("DataClassPropertyBetweenUsages.kt") + public void testDataClassPropertyBetweenUsages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassPropertyBetweenUsages.kt"); + doTest(fileName); + } + + @TestMetadata("DataClassSecondVariable.kt") + public void testDataClassSecondVariable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassSecondVariable.kt"); + doTest(fileName); + } + @TestMetadata("DataClassUnused.kt") public void testDataClassUnused() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassUnused.kt"); doTest(fileName); } + @TestMetadata("DataClassWithAssignmentInside.kt") + public void testDataClassWithAssignmentInside() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassWithAssignmentInside.kt"); + doTest(fileName); + } + + @TestMetadata("DataClassWithExternalUsage.kt") + public void testDataClassWithExternalUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassWithExternalUsage.kt"); + doTest(fileName); + } + + @TestMetadata("DataClassWithIncrementInside.kt") + public void testDataClassWithIncrementInside() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/DataClassWithIncrementInside.kt"); + doTest(fileName); + } + @TestMetadata("EntriesCallIsMissing.kt") public void testEntriesCallIsMissing() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/EntriesCallIsMissing.kt"); @@ -6555,6 +6609,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("MapNoProperties.kt") + public void testMapNoProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/MapNoProperties.kt"); + doTest(fileName); + } + @TestMetadata("OnlyKeyUsed.kt") public void testOnlyKeyUsed() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/iterationOverMap/OnlyKeyUsed.kt");