mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
(KTIJ-31946) RemoveForLoopIndicesIntention ported to k2, description added.
GitOrigin-RevId: ffd9b687c2e846ee25f37558f5386c7c5c90a8e1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3fbc56ed97
commit
6a444c675a
+5
@@ -0,0 +1,5 @@
|
||||
fun foo(bar: List<String>) {
|
||||
for (<spot>value: String in bar</spot>) {
|
||||
println(value)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun foo(bar: List<String>) {
|
||||
for (<spot>(index : Int, value: String) in bar.withIndex()</spot>) {
|
||||
println(value)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports <code>for</code> loops iterating over a collection using the <code>withIndex()</code> function and not using the index variable.
|
||||
</body>
|
||||
</html>
|
||||
+7
@@ -248,6 +248,13 @@
|
||||
<categoryKey>group.names.kotlin</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<language>kotlin</language>
|
||||
<className>org.jetbrains.kotlin.idea.k2.codeinsight.intentions.RemoveForLoopIndicesIntention</className>
|
||||
<bundleName>messages.KotlinBundle</bundleName>
|
||||
<categoryKey>group.names.kotlin</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<language>kotlin</language>
|
||||
<className>org.jetbrains.kotlin.idea.k2.codeinsight.intentions.ConvertPropertyGetterToInitializerIntention</className>
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// 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.k2.codeinsight.intentions
|
||||
|
||||
import com.intellij.codeInspection.util.IntentionFamilyName
|
||||
import com.intellij.modcommand.ActionContext
|
||||
import com.intellij.modcommand.ModPsiUpdater
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.successfulFunctionCallOrNull
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.symbol
|
||||
import org.jetbrains.kotlin.idea.base.codeInsight.handlers.fixers.range
|
||||
import org.jetbrains.kotlin.idea.base.psi.relativeTo
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.intentions.KotlinApplicableModCommandAction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
|
||||
class RemoveForLoopIndicesIntention :
|
||||
KotlinApplicableModCommandAction<KtForExpression, RemoveForLoopIndicesIntention.Context>(KtForExpression::class) {
|
||||
private val WITH_INDEX_NAME = "withIndex"
|
||||
private val WITH_INDEX_FQ_NAMES: Set<FqName> by lazy {
|
||||
sequenceOf("collections", "sequences", "text", "ranges").map { FqName("kotlin.$it.$WITH_INDEX_NAME") }.toSet()
|
||||
}
|
||||
|
||||
data class Context(val elementVar: KtDestructuringDeclarationEntry)
|
||||
|
||||
override fun getFamilyName(): @IntentionFamilyName String =
|
||||
KotlinBundle.message("remove.indices.in.for.loop")
|
||||
|
||||
override fun getApplicableRanges(element: KtForExpression): List<TextRange> {
|
||||
val indexVar = getIndexVar(element) ?: return emptyList()
|
||||
return listOfNotNull(indexVar.nameIdentifier?.range?.relativeTo(element))
|
||||
}
|
||||
|
||||
override fun isApplicableByPsi(element: KtForExpression): Boolean {
|
||||
val multiParameter = element.destructuringDeclaration ?: return false
|
||||
return multiParameter.entries.size == 2
|
||||
}
|
||||
|
||||
override fun KaSession.prepareContext(element: KtForExpression): Context? {
|
||||
val loopRange = element.loopRange as? KtDotQualifiedExpression ?: return null
|
||||
val multiParameter = element.destructuringDeclaration ?: return null
|
||||
|
||||
val functionCall = loopRange.resolveToCall()?.successfulFunctionCallOrNull()?.symbol?.callableId?.asSingleFqName() ?: return null
|
||||
if (functionCall !in WITH_INDEX_FQ_NAMES) return null
|
||||
val indexVar = multiParameter.entries[0]
|
||||
if (ReferencesSearch.search(indexVar).any()) return null
|
||||
|
||||
val elementVar = multiParameter.entries[1]
|
||||
return Context(elementVar)
|
||||
}
|
||||
|
||||
override fun invoke(
|
||||
actionContext: ActionContext,
|
||||
element: KtForExpression,
|
||||
elementContext: Context,
|
||||
updater: ModPsiUpdater
|
||||
) {
|
||||
val loopRange = element.loopRange as KtDotQualifiedExpression
|
||||
|
||||
val psiFactory = KtPsiFactory(element.project)
|
||||
val loop = psiFactory.createExpressionByPattern("for ($0 in _) {}", elementContext.elementVar.text) as KtForExpression
|
||||
|
||||
loop.loopParameter?.let { element.loopParameter?.replace(it) }
|
||||
loopRange.replace(loopRange.receiverExpression)
|
||||
}
|
||||
|
||||
private fun getIndexVar(element: KtForExpression): KtDestructuringDeclarationEntry? {
|
||||
val multiParameter = element.destructuringDeclaration ?: return null
|
||||
if (multiParameter.entries.size != 2) return null
|
||||
return multiParameter.entries[0]
|
||||
}
|
||||
}
|
||||
+49
@@ -3330,6 +3330,55 @@ public abstract class K2IntentionTestGenerated extends AbstractK2IntentionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("../../../idea/tests/testData/intentions/removeForLoopIndices")
|
||||
public static class RemoveForLoopIndices extends AbstractK2IntentionTest {
|
||||
@java.lang.Override
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final KotlinPluginMode getPluginMode() {
|
||||
return KotlinPluginMode.K2;
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("inapplicableForLoop.kt")
|
||||
public void testInapplicableForLoop() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/inapplicableForLoop.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inapplicableIndexUse.kt")
|
||||
public void testInapplicableIndexUse() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/inapplicableIndexUse.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inapplicableOverridenFunction.kt")
|
||||
public void testInapplicableOverridenFunction() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/inapplicableOverridenFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("loopWithType.kt")
|
||||
public void testLoopWithType() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/loopWithType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleLoopWithIndices.kt")
|
||||
public void testSimpleLoopWithIndices() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/simpleLoopWithIndices.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleLoopWithIndicesOverCharSequence.kt")
|
||||
public void testSimpleLoopWithIndicesOverCharSequence() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/simpleLoopWithIndicesOverCharSequence.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleLoopWithIndicesOverSequence.kt")
|
||||
public void testSimpleLoopWithIndicesOverSequence() throws Exception {
|
||||
runTest("../../../idea/tests/testData/intentions/removeForLoopIndices/simpleLoopWithIndicesOverSequence.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("../../../idea/tests/testData/intentions/addWhenRemainingBranches")
|
||||
public static class AddWhenRemainingBranches extends AbstractK2IntentionTest {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.k2.codeinsight.intentions.RemoveForLoopIndicesIntention
|
||||
+1
@@ -34,6 +34,7 @@ internal fun MutableTWorkspace.generateK2IntentionTests() {
|
||||
model("${idea}intentions/convertStringTemplateToBuildStringMultiDollarPrefix", pattern = pattern)
|
||||
model("${idea}intentions/convertFilteringFunctionWithDemorgansLaw", pattern = pattern)
|
||||
model("${idea}intentions/convertToBlockBody", pattern = pattern)
|
||||
model("${idea}intentions/removeForLoopIndices", pattern = pattern)
|
||||
model("${idea}intentions/addWhenRemainingBranches", pattern = pattern)
|
||||
model("${idea}intentions/convertToConcatenatedString", pattern = pattern)
|
||||
model("${idea}intentions/convertToStringTemplate", pattern = pattern)
|
||||
|
||||
Reference in New Issue
Block a user