From c8b48a46eb96f488e1f54e2ce0e013ed8b2c8eb7 Mon Sep 17 00:00:00 2001 From: Olga Klisho Date: Thu, 5 Feb 2026 14:47:10 +0100 Subject: [PATCH] [kotlin] KTIJ-37274 ReplaceManualRangeWithIndicesCallsInspection support withIndex replacement GitOrigin-RevId: bbb044e2db9897009cce15cb083e618666f23baf --- .../messages/KotlinBundle.properties | 2 + .../tests/K2LocalInspectionTestGenerated.java | 20 ++ ...ceManualRangeWithIndicesCallsInspection.kt | 251 ++++++++++++++---- .../utils/LoopToCollectionTransformUtils.kt | 90 ++++--- .../LocalInspectionTestGenerated.java | 20 ++ .../complexReceiver.kt | 1 + .../complexReceiver.kt.after | 1 + .../elementNameCollision.kt | 1 + .../elementNameCollision.kt.after | 1 + .../elementNameCollisionMultiple.kt | 1 + .../elementNameCollisionMultiple.kt.after | 1 + .../elementNameCollisionNestedLoop.kt | 1 + .../elementNameCollisionNestedLoop.kt.after | 1 + .../elementNameCollisionParameter.kt | 1 + .../elementNameCollisionParameter.kt.after | 1 + .../implicitReceiverFor.kt | 1 + .../implicitReceiverFor.kt.after | 1 + .../lastIndex.kt | 1 + .../lastIndex.kt.after | 1 + .../multipleImplicitReceivers.kt | 1 + .../multipleImplicitReceivers.kt.after | 1 + .../multipleImplicitReceivers2.kt | 1 + .../multipleImplicitReceivers2.kt.after | 5 +- .../simpleFor.kt | 1 + .../simpleFor.kt.after | 1 + .../sizeLabeled.kt | 1 + .../sizeLabeled.kt.after | 1 + .../thisReceiverFor.kt | 1 + .../thisReceiverFor.kt.after | 1 + .../withIndexBasic.kt | 8 + .../withIndexBasic.kt.after | 8 + .../withIndexElementNameCollision.kt | 10 + .../withIndexElementNameCollision.kt.after | 10 + .../withIndexMultipleArrayAccess.kt | 10 + .../withIndexMultipleArrayAccess.kt.after | 10 + .../withIndexRangeTo.kt | 8 + .../withIndexRangeTo.kt.after | 8 + 37 files changed, 395 insertions(+), 88 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt.after diff --git a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties index 68520a7c9ef8..da97aed5af1a 100644 --- a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties +++ b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties @@ -1688,6 +1688,8 @@ replace.index.loop.with.collection.loop.quick.fix.text=Replace with loop over el replace.manual.range.with.indices.call.quick.fix.text=Replace with indices range.could.be.replaced.with.indices.call=Range could be replaced with '.indices' call for.loop.over.indices.could.be.replaced.with.loop.over.elements=For loop over indices could be replaced with loop over elements +for.loop.could.use.withIndex=For loop could use 'withIndex()' +replace.index.loop.with.withIndex.quick.fix.text=Replace with 'withIndex()' replace.negated.0.with.1=Replace negated ''{0}'' with ''{1}'' replace.with.elvis.return.fix.text=Replace with ''?: return{0}'' replace.with.return=Replace '!!' with '?: return' diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java index f54d6395fa2a..622966e1e115 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java @@ -9861,6 +9861,26 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp public void testUsedForOtherArray() throws Exception { runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/usedForOtherArray.kt"); } + + @TestMetadata("withIndexBasic.kt") + public void testWithIndexBasic() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt"); + } + + @TestMetadata("withIndexElementNameCollision.kt") + public void testWithIndexElementNameCollision() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt"); + } + + @TestMetadata("withIndexMultipleArrayAccess.kt") + public void testWithIndexMultipleArrayAccess() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt"); + } + + @TestMetadata("withIndexRangeTo.kt") + public void testWithIndexRangeTo() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt"); + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/ReplaceManualRangeWithIndicesCallsInspection.kt b/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/ReplaceManualRangeWithIndicesCallsInspection.kt index ac0527e8fbff..672b2750fc38 100644 --- a/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/ReplaceManualRangeWithIndicesCallsInspection.kt +++ b/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/ReplaceManualRangeWithIndicesCallsInspection.kt @@ -1,12 +1,20 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.codeInsight.inspections.shared +import com.intellij.codeInspection.InspectionManager +import com.intellij.codeInspection.ProblemDescriptor +import com.intellij.codeInspection.ProblemHighlightType +import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.util.InspectionMessage import com.intellij.codeInspection.util.IntentionFamilyName import com.intellij.modcommand.ModPsiUpdater import com.intellij.openapi.project.Project +import com.intellij.psi.SmartPsiElementPointer +import com.intellij.psi.createSmartPointer import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.analysis.api.KaSession +import org.jetbrains.kotlin.analysis.api.resolution.singleFunctionCallOrNull +import org.jetbrains.kotlin.analysis.api.resolution.symbol import org.jetbrains.kotlin.analysis.api.resolution.successfulVariableAccessCall import org.jetbrains.kotlin.analysis.api.types.KaType import org.jetbrains.kotlin.idea.base.codeInsight.KotlinDeclarationNameValidator @@ -15,6 +23,9 @@ import org.jetbrains.kotlin.idea.base.codeInsight.KotlinNameSuggestionProvider import org.jetbrains.kotlin.idea.base.psi.replaced import org.jetbrains.kotlin.idea.base.psi.safeDeparenthesize import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.AbstractRangeInspection.Companion.rangeExpressionByPsi +import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.AbstractRangeInspection.RangeExpression +import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinApplicableInspectionBase import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinModCommandQuickFix import org.jetbrains.kotlin.idea.codeinsight.utils.ImplicitReceiverInfo import org.jetbrains.kotlin.idea.codeinsight.utils.LoopToCollectionTransformUtils @@ -25,6 +36,7 @@ import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.RANGE_U import org.jetbrains.kotlin.idea.codeinsight.utils.RangeKtExpressionType.UNTIL import org.jetbrains.kotlin.idea.codeinsight.utils.getImplicitReceiverInfo import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression @@ -39,6 +51,8 @@ import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.psi.KtQualifiedExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.KtThisExpression +import org.jetbrains.kotlin.psi.KtVisitor +import org.jetbrains.kotlin.psi.KtVisitorVoid import org.jetbrains.kotlin.psi.createExpressionByPattern import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.parents @@ -47,26 +61,56 @@ import org.jetbrains.kotlin.util.match /** * Inspection that suggests replacing manual ranges like `0..() { +class ReplaceManualRangeWithIndicesCallsInspection : KotlinApplicableInspectionBase() { + + /** + * Describes how the loop index variable is used in the loop body, + * determining which quick fixes are applicable. + */ + enum class IndexUsagePattern { + /** + * Index is only used for array access: `arr[i]`. + * Can transform to: `for (element in arr)` + */ + ELEMENT_LOOP, + + /** + * Index is used both for array access and other purposes: `println("$i: ${arr[i]}")`. + * Can transform to: `for ((i, element) in arr.withIndex())` + */ + WITH_INDEX, + + /** + * Index is not used for array access, or range is not inside a for loop. + * Can only replace range with `.indices`: `for (i in arr.indices)` + */ + INDICES_ONLY + } data class Context( val explicitReceiver: KtExpression?, - val suggestElementLoop: Boolean, + val indexUsagePattern: IndexUsagePattern, val implicitReceiverInfo: ImplicitReceiverInfo?, val suggestedElementName: String?, + val arrayAccessUsages: List>, ) - override fun getProblemDescription( - range: RangeExpression, - context: Context - ): @InspectionMessage String { - return if (context.suggestElementLoop) { - KotlinBundle.message("for.loop.over.indices.could.be.replaced.with.loop.over.elements") - } else KotlinBundle.message("range.could.be.replaced.with.indices.call") + private fun getProblemDescription(context: Context): @InspectionMessage String { + return when (context.indexUsagePattern) { + IndexUsagePattern.ELEMENT_LOOP -> KotlinBundle.message("for.loop.over.indices.could.be.replaced.with.loop.over.elements") + IndexUsagePattern.WITH_INDEX -> KotlinBundle.message("for.loop.could.use.withIndex") + IndexUsagePattern.INDICES_ONLY -> KotlinBundle.message("range.could.be.replaced.with.indices.call") + } } - override fun isApplicableByPsi(range: RangeExpression): Boolean { + override fun isApplicableByPsi(element: KtExpression): Boolean { + val range = rangeExpressionByPsi(element) ?: return false + return isApplicableByPsi(range) + } + + private fun isApplicableByPsi(range: RangeExpression): Boolean { // Only ascending ranges are candidates for indices replacement if (range.type == DOWN_TO) return false @@ -81,18 +125,34 @@ class ReplaceManualRangeWithIndicesCallsInspection : AbstractRangeInspection val nameValidator = KotlinDeclarationNameValidator( @@ -104,7 +164,16 @@ class ReplaceManualRangeWithIndicesCallsInspection : AbstractRangeInspection, + ) + + /** + * Analyzes how the loop index variable is used in the loop body. + * + * @return IndexUsageAnalysis containing: + * - pattern: ELEMENT_LOOP (all array accesses), WITH_INDEX (mixed), or INDICES_ONLY (no array accesses) + * - arrayAccessUsages: list of valid array access expressions for transformation + */ + private fun analyzeIndexUsagePattern(range: RangeExpression, explicitReceiver: KtExpression?): IndexUsageAnalysis { + val forExpression = findContainingForLoop(range) + ?: return IndexUsageAnalysis(IndexUsagePattern.INDICES_ONLY, emptyList()) + val loopParam = forExpression.loopParameter?.originalElement + ?: return IndexUsageAnalysis(IndexUsagePattern.INDICES_ONLY, emptyList()) val usages = ReferencesSearch.search(loopParam).findAll() - if (usages.isEmpty()) return false + if (usages.isEmpty()) return IndexUsageAnalysis(IndexUsagePattern.INDICES_ONLY, emptyList()) - // Check that all usages are valid array accesses with the same receiver - return usages.all { reference -> + val validArrayAccesses = mutableListOf() + var otherUsageCount = 0 + + for (reference in usages) { val usage = reference.element val arrayAccess = usage.parents.match(KtContainerNode::class, last = KtArrayAccessExpression::class) - arrayAccess != null && isValidElementLoopCandidate(arrayAccess, explicitReceiver) + + if (arrayAccess != null && isValidElementLoopCandidate(arrayAccess, explicitReceiver)) { + validArrayAccesses.add(arrayAccess) + } else { + otherUsageCount++ + } } + + val pattern = when { + validArrayAccesses.isNotEmpty() && otherUsageCount == 0 -> IndexUsagePattern.ELEMENT_LOOP + validArrayAccesses.isNotEmpty() && otherUsageCount > 0 -> IndexUsagePattern.WITH_INDEX + else -> IndexUsagePattern.INDICES_ONLY + } + + return IndexUsageAnalysis(pattern, validArrayAccesses) } private fun findContainingForLoop(range: RangeExpression): KtForExpression? = @@ -203,12 +300,41 @@ class ReplaceManualRangeWithIndicesCallsInspection : AbstractRangeInspection { - return if (context.suggestElementLoop) ReplaceIndexLoopWithCollectionLoopQuickFix(context) - else ReplaceManualRangeWithIndicesCallQuickFix(context) + private fun createQuickFixes(context: Context): List> { + val indicesFix = ReplaceManualRangeWithIndicesCallQuickFix(context) + return when (context.indexUsagePattern) { + IndexUsagePattern.ELEMENT_LOOP -> listOf(ReplaceIndexLoopWithCollectionLoopQuickFix(context), indicesFix) + IndexUsagePattern.WITH_INDEX -> listOf(ReplaceWithWithIndexLoopQuickFix(context), indicesFix) + IndexUsagePattern.INDICES_ONLY -> listOf(indicesFix) + } + } + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): KtVisitor<*, *> = + object : KtVisitorVoid() { + override fun visitBinaryExpression(expression: KtBinaryExpression) { + visitTargetElement(expression, holder, isOnTheFly) + } + + override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) { + visitTargetElement(expression, holder, isOnTheFly) + } + } + + override fun InspectionManager.createProblemDescriptor( + element: KtExpression, + context: Context, + rangeInElement: com.intellij.openapi.util.TextRange?, + onTheFly: Boolean, + ): ProblemDescriptor { + val fixes = createQuickFixes(context) + return createProblemDescriptor( + element, + rangeInElement, + getProblemDescription(context), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + onTheFly, + *fixes.toTypedArray() + ) } /** @@ -264,29 +390,14 @@ class ReplaceManualRangeWithIndicesCallsInspection : AbstractRangeInspection + pointer.element?.let { updater.getWritable(it) } + } + if (arrayAccesses.isEmpty()) return + val collection = resolveCollectionExpression(project) - - // Try a single usage first - val singleUsageInfo = LoopToCollectionTransformUtils.findSingleArrayAccessUsage(loopParameter) - if (singleUsageInfo != null) { - LoopToCollectionTransformUtils.transformLoop(project, listOf(singleUsageInfo), loopParameter, loopRange, collection, elementName) - return - } - - // Handle multiple usages - val loopParam = loopParameter.originalElement ?: return - val usages = ReferencesSearch.search(loopParam).findAll() - val usageInfos = usages.mapNotNull { reference -> - val usage = reference.element - val arrayAccess = usage.parents.match(KtContainerNode::class, last = KtArrayAccessExpression::class) - if (arrayAccess != null) { - LoopToCollectionTransformUtils.LoopUsageInfo(loopParameter, usage, arrayAccess) - } else null - } - - if (usageInfos.isNotEmpty()) { - LoopToCollectionTransformUtils.transformLoop(project, usageInfos, loopParameter, loopRange, collection, elementName) - } + LoopToCollectionTransformUtils.transformLoop(project, arrayAccesses, loopParameter, loopRange, collection, elementName) } /** @@ -306,4 +417,40 @@ class ReplaceManualRangeWithIndicesCallsInspection : AbstractRangeInspection() { + override fun getFamilyName(): @IntentionFamilyName String = + KotlinBundle.message("replace.index.loop.with.withIndex.quick.fix.text") + + override fun applyFix(project: Project, element: KtExpression, updater: ModPsiUpdater) { + val forExpression = element.getStrictParentOfType() ?: return + val loopParameter = forExpression.loopParameter ?: return + val loopRange = forExpression.loopRange ?: return + val elementName = context.suggestedElementName ?: return + + // Get writable array accesses from smart pointers + val arrayAccesses = context.arrayAccessUsages.mapNotNull { pointer -> + pointer.element?.let { updater.getWritable(it) } + } + if (arrayAccesses.isEmpty()) return + + val collection = resolveCollectionExpression(project) + LoopToCollectionTransformUtils.transformLoopWithIndex( + project, arrayAccesses, loopParameter, loopRange, collection, elementName + ) + } + + private fun resolveCollectionExpression(project: Project): KtExpression { + context.explicitReceiver?.let { return it } + + context.implicitReceiverInfo?.takeUnless { it.isUnambiguousLabel }?.let { + return createImplicitThis(project, it) + } + + return KtPsiFactory(project).createThisExpression() + } + } } \ No newline at end of file diff --git a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/LoopToCollectionTransformUtils.kt b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/LoopToCollectionTransformUtils.kt index f9c3d4e1604c..f323d5581ce0 100644 --- a/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/LoopToCollectionTransformUtils.kt +++ b/plugins/kotlin/code-insight/utils/src/org/jetbrains/kotlin/idea/codeinsight/utils/LoopToCollectionTransformUtils.kt @@ -2,16 +2,14 @@ package org.jetbrains.kotlin.idea.codeinsight.utils import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElement -import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.psi.KtArrayAccessExpression -import org.jetbrains.kotlin.psi.KtContainerNode +import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.psiUtil.parents -import org.jetbrains.kotlin.util.match +import org.jetbrains.kotlin.psi.createExpressionByPattern +import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry /** * Utility functions for transforming index-based loops to collection loops. @@ -20,36 +18,13 @@ import org.jetbrains.kotlin.util.match object LoopToCollectionTransformUtils { /** - * Data class representing the result of finding loop usage patterns. - */ - data class LoopUsageInfo( - val paramElement: KtParameter, - val usageElement: PsiElement, - val arrayAccessElement: KtArrayAccessExpression - ) - - /** - * Finds the usage pattern for a loop parameter where it's used as an array index exactly once. - * - * @param loopParameter the loop parameter (e.g., `i` in `for (i in 0.., + arrayAccesses: List, loopParameter: KtParameter, loopRange: KtExpression, newLoopRange: KtExpression, @@ -66,11 +41,58 @@ object LoopToCollectionTransformUtils { val factory = KtPsiFactory(project) val newParameter = factory.createLoopParameter(elementName) - val newReferenceExpression = factory.createExpression(elementName) // Replace all array access expressions with direct element references - usageInfos.forEach { usageInfo -> - usageInfo.arrayAccessElement.replace(newReferenceExpression.copy()) + arrayAccesses.forEach { arrayAccess -> + replaceArrayAccessWithElement(factory, arrayAccess, elementName) + } + + loopParameter.replace(newParameter) + loopRange.replace(newLoopRange) + } + + /** + * Replaces an array access expression with a simple element reference. + * When inside a string template ${...}, creates the simplified $name form directly if possible. + */ + private fun replaceArrayAccessWithElement(factory: KtPsiFactory, arrayAccess: KtArrayAccessExpression, elementName: String) { + val blockEntry = arrayAccess.parent as? KtBlockStringTemplateEntry + if (blockEntry != null && canPlaceAfterSimpleNameEntry(blockEntry.nextSibling)) { + blockEntry.replace(factory.createSimpleNameStringTemplateEntry(elementName)) + } else { + arrayAccess.replace(factory.createExpression(elementName)) + } + } + + /** + * Transforms an index-based loop to a withIndex() loop by: + * 1. Replacing the loop parameter with a destructuring declaration (indexName, elementName) + * 2. Replacing array access expressions with direct element references + * 3. Replacing the loop range with collection.withIndex() + * @param project the current project + * @param arrayAccesses array access expressions to replace with element references + * @param loopParameter the original loop parameter (the index variable) + * @param loopRange the original loop range + * @param collectionExpression the collection to iterate with withIndex() + * @param elementName the name for the new element variable + */ + fun transformLoopWithIndex( + project: Project, + arrayAccesses: List, + loopParameter: KtParameter, + loopRange: KtExpression, + collectionExpression: KtExpression, + elementName: String + ) { + val factory = KtPsiFactory(project) + + val indexName = loopParameter.name ?: "index" + val newParameter = factory.createDestructuringParameter("($indexName, $elementName)") + val newLoopRange = factory.createExpressionByPattern("$0.withIndex()", collectionExpression) + + // Replace all array access expressions with direct element references + arrayAccesses.forEach { arrayAccess -> + replaceArrayAccessWithElement(factory, arrayAccess, elementName) } loopParameter.replace(newParameter) diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 27cc9c3d913e..aba3ca352c6a 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -14545,6 +14545,26 @@ public abstract class LocalInspectionTestGenerated extends AbstractK1LocalInspec public void testUsedForOtherArray() throws Exception { runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/usedForOtherArray.kt"); } + + @TestMetadata("withIndexBasic.kt") + public void testWithIndexBasic() throws Exception { + runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt"); + } + + @TestMetadata("withIndexElementNameCollision.kt") + public void testWithIndexElementNameCollision() throws Exception { + runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt"); + } + + @TestMetadata("withIndexMultipleArrayAccess.kt") + public void testWithIndexMultipleArrayAccess() throws Exception { + runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt"); + } + + @TestMetadata("withIndexRangeTo.kt") + public void testWithIndexRangeTo() throws Exception { + runTest("testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt"); + } } @RunWith(JUnit3RunnerWithInners.class) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt index 1d784d597c9d..3c4c1a9378c2 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements class Person(val name: String) fun getName(person: Person) { for (i in 0 until person.name.length) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt.after index 3db756f0a6f7..cc305e602618 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/complexReceiver.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements class Person(val name: String) fun getName(person: Person) { for (element in person.name) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt index 57b8043fa190..12003f534a42 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val element = mutableListOf("hello", "world") diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt.after index 1b993e01d020..b0302ff9adf3 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollision.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val element = mutableListOf("hello", "world") diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt index 04a2749129ad..441f9c135da6 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val element = "first" diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt.after index da001875cc3f..561f68642c6d 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionMultiple.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val element = "first" diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt index 001f4ec883fc..21e8862277e0 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val outer = listOf(listOf("a", "b"), listOf("c", "d")) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt.after index d4dc5730f1b3..94cfc3542eab 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionNestedLoop.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test() { val outer = listOf(listOf("a", "b"), listOf("c", "d")) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt index a1f79803a27d..0ed400f8b8ab 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test(element: String, list: List) { for (i in 0 until list.size) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt.after index d19afd2c078a..24c5ea1e9af9 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/elementNameCollisionParameter.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements // IGNORE_K1 fun test(element: String, list: List) { for (element1 in list) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt index bef1aeda33fb..4180bc6d9460 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun Array.test() { for (index in 0..size - 1) { val out = this[index] diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt.after index 643fc3bf889e..ddfc9ccc3a1b 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/implicitReceiverFor.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun Array.test() { for (element in this) { val out = element diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt index f57863119253..f4f77b5114ab 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun foo() { val intArray = intArrayOf(1, 2, 3, 4, 5) for (i in 0..intArray.lastIndex) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt.after index b840cf09d88d..8d460c12b210 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/lastIndex.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun foo() { val intArray = intArrayOf(1, 2, 3, 4, 5) for (element in intArray) { diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt index 2b394b4ba635..a1ecc52e1c52 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun IntArray.arrayToString(): String = buildString { for (i in 0 until size) { append(this@arrayToString[i]) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt.after index f9122e62cc52..7d40d4bda8aa 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun IntArray.arrayToString(): String = buildString { for (element in this@arrayToString) { append(element) diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt index 9ccc4e7cb0a4..f958614dd564 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with 'withIndex()' fun LongArray.arrayToString(): String = buildString { for (i in 0 until size) { if (i > 0) append(", ") diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt.after index 8caf5ba7560b..da6d0774a260 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/multipleImplicitReceivers2.kt.after @@ -1,7 +1,8 @@ // WITH_STDLIB +// FIX: Replace with 'withIndex()' fun LongArray.arrayToString(): String = buildString { - for (i in this@arrayToString.indices) { + for ((i, element) in this@arrayToString.withIndex()) { if (i > 0) append(", ") - append(this@arrayToString[i]) + append(element) } } \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt index 8229f12bafca..6b413cfb1df2 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun test(args: Array) { for (index in 0..args.size - 1) { val out = args[index] diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt.after index 6e8e5ef81688..40e9e69df057 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/simpleFor.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun test(args: Array) { for (element in args) { val out = element diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt index 26855a0b8027..1fdc7e50b183 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun main() { println(listOf(1, 2, 3).doubled()) } diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt.after index 8b241ac193c8..415c41a1f09e 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/sizeLabeled.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun main() { println(listOf(1, 2, 3).doubled()) } diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt index 26fd13f1694e..edd1e0d59e80 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun Array.test() { for (index in 0..this.size - 1) { val out = this[index] diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt.after index 643fc3bf889e..ddfc9ccc3a1b 100644 --- a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt.after +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/thisReceiverFor.kt.after @@ -1,4 +1,5 @@ // WITH_STDLIB +// FIX: Replace with loop over elements fun Array.test() { for (element in this) { val out = element diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt new file mode 100644 index 000000000000..6c7a64cae24d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt @@ -0,0 +1,8 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +fun test() { + val list = listOf("a", "b", "c") + for (i in 0 until list.size) { + println("Index $i: ${list[i]}") + } +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt.after new file mode 100644 index 000000000000..15e2d7860d2d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexBasic.kt.after @@ -0,0 +1,8 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +fun test() { + val list = listOf("a", "b", "c") + for ((i, element) in list.withIndex()) { + println("Index $i: $element") + } +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt new file mode 100644 index 000000000000..479b9c11f48a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt @@ -0,0 +1,10 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +// IGNORE_K1 +fun test() { + val element = "existing" + val list = listOf("a", "b", "c") + for (i in 0 until list.size) { + println("Index $i: ${list[i]}, also $element") + } +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt.after new file mode 100644 index 000000000000..05e382c65a55 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexElementNameCollision.kt.after @@ -0,0 +1,10 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +// IGNORE_K1 +fun test() { + val element = "existing" + val list = listOf("a", "b", "c") + for ((i, element1) in list.withIndex()) { + println("Index $i: $element1, also $element") + } +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt new file mode 100644 index 000000000000..8148bdb3a616 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexMultipleArrayAccess.kt @@ -0,0 +1,10 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +fun test() { + val list = listOf("a", "b", "c") + for (i in 0...arr.size - 1) { + println("arr[$idx] = ${arr[idx]}") + } +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt.after new file mode 100644 index 000000000000..0592a8a77d38 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceManualRangeWithIndicesCalls/withIndexRangeTo.kt.after @@ -0,0 +1,8 @@ +// WITH_STDLIB +// FIX: Replace with 'withIndex()' +fun test() { + val arr = arrayOf(1, 2, 3) + for ((idx, element) in arr.withIndex()) { + println("arr[$idx] = $element") + } +}