[kotlin] Port ReplaceToWithInfixFormInspection to K2

#KTIJ-31928 Fixed

GitOrigin-RevId: ad79eb0499fcd13efb446f41e94c04ac5afbdd16
This commit is contained in:
Andrey Cherkasov
2025-05-23 20:29:37 +00:00
committed by intellij-monorepo-bot
parent 64faa4b355
commit 8b6dd5ef89
5 changed files with 115 additions and 0 deletions
@@ -996,5 +996,13 @@
language="kotlin"
key="inspection.copy.without.named.arguments.display.name" bundle="messages.KotlinBundle"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.k2.codeinsight.inspections.ReplaceToWithInfixFormInspection"
groupPath="Kotlin"
groupBundle="messages.KotlinBundle" groupKey="group.names.style.issues"
enabledByDefault="true"
level="WEAK WARNING"
language="kotlin"
key="inspection.replace.to.with.infix.form.display.name" bundle="messages.KotlinBundle"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,76 @@
// 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.inspections
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 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.analysis.api.symbols.KaNamedFunctionSymbol
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
import org.jetbrains.kotlin.idea.codeinsight.api.applicable.asUnit
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.callExpression
import org.jetbrains.kotlin.psi.*
private const val TO_FUNCTION_NAME = "to"
internal class ReplaceToWithInfixFormInspection : KotlinApplicableInspectionBase.Simple<KtDotQualifiedExpression, Unit>() {
override fun buildVisitor(
holder: ProblemsHolder,
isOnTheFly: Boolean,
): KtVisitor<*, *> = dotQualifiedExpressionVisitor {
visitTargetElement(it, holder, isOnTheFly)
}
override fun getProblemDescription(
element: KtDotQualifiedExpression,
context: Unit,
): @InspectionMessage String = KotlinBundle.message("inspection.replace.to.with.infix.form.display.name")
override fun isApplicableByPsi(element: KtDotQualifiedExpression): Boolean {
val callExpression = element.callExpression ?: return false
return callExpression.valueArguments.size == 1 &&
callExpression.typeArgumentList == null &&
element.calleeName == TO_FUNCTION_NAME
}
override fun KaSession.prepareContext(element: KtDotQualifiedExpression): Unit? {
val call = element.resolveToCall()?.successfulFunctionCallOrNull() ?: return null
val functionSymbol = call.symbol as? KaNamedFunctionSymbol ?: return null
return functionSymbol.isInfix.asUnit
}
override fun createQuickFix(
element: KtDotQualifiedExpression,
context: Unit,
): KotlinModCommandQuickFix<KtDotQualifiedExpression> = ReplaceToWithInfixFormQuickFix()
}
private class ReplaceToWithInfixFormQuickFix : KotlinModCommandQuickFix<KtDotQualifiedExpression>() {
override fun getFamilyName(): @IntentionFamilyName String =
KotlinBundle.message("replace.to.with.infix.form.quickfix.text")
override fun applyFix(
project: Project,
element: KtDotQualifiedExpression,
updater: ModPsiUpdater,
) {
val argumentExpression = element.callExpression?.valueArguments?.first()?.getArgumentExpression() ?: return
val newExpression = createInfixExpression(project, element.receiverExpression, argumentExpression)
element.replace(newExpression)
}
private fun createInfixExpression(
project: Project,
receiver: KtExpression,
argument: KtExpression,
): KtExpression = KtPsiFactory(project).createExpressionByPattern("$0 to $1", receiver, argument)
}
private val KtQualifiedExpression.calleeName: String?
get() = (callExpression?.calleeExpression as? KtNameReferenceExpression)?.text
@@ -13833,6 +13833,35 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/inspectionsLocal/replaceToWithInfixForm")
public static class ReplaceToWithInfixForm extends AbstractK2LocalInspectionTest {
@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("base.kt")
public void testBase() throws Exception {
runTest("../../../idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/base.kt");
}
@TestMetadata("nonPair.kt")
public void testNonPair() throws Exception {
runTest("../../../idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/nonPair.kt");
}
@TestMetadata("typeArguments.kt")
public void testTypeArguments() throws Exception {
runTest("../../../idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/typeArguments.kt");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../../idea/tests/testData/inspectionsLocal/addOperatorModifier")
public static class AddOperatorModifier extends AbstractK2LocalInspectionTest {
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.k2.codeinsight.inspections.ReplaceToWithInfixFormInspection
@@ -90,6 +90,7 @@ internal fun MutableTWorkspace.generateK2InspectionTests() {
model("${idea}/inspectionsLocal/canBeVal")
model("${idea}/inspectionsLocal/replaceSubstring")
model("${idea}/inspectionsLocal/replaceWithIgnoreCaseEquals")
model("${idea}/inspectionsLocal/replaceToWithInfixForm")
model("${idea}/inspectionsLocal/addOperatorModifier")
model("${idea}/inspectionsLocal/kotlinUnreachableCode")
model("${idea}/inspectionsLocal/removeRedundantLabel")