diff --git a/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections.k2.xml b/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections.k2.xml
index b104b796625c..67c0d6a3a3fe 100644
--- a/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections.k2.xml
+++ b/plugins/kotlin/code-insight/inspections-k2/resources/kotlin.code-insight.inspections.k2.xml
@@ -996,5 +996,13 @@
language="kotlin"
key="inspection.copy.without.named.arguments.display.name" bundle="messages.KotlinBundle"/>
+
+
diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/ReplaceToWithInfixFormInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/ReplaceToWithInfixFormInspection.kt
new file mode 100644
index 000000000000..d599e81851ab
--- /dev/null
+++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/ReplaceToWithInfixFormInspection.kt
@@ -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() {
+ 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 = ReplaceToWithInfixFormQuickFix()
+}
+
+private class ReplaceToWithInfixFormQuickFix : KotlinModCommandQuickFix() {
+ 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
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 fa015016f194..b363170c73a6 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
@@ -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 {
diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/.k2Inspection b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/.k2Inspection
new file mode 100644
index 000000000000..3690bdcf24e8
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/replaceToWithInfixForm/.k2Inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.k2.codeinsight.inspections.ReplaceToWithInfixFormInspection
\ No newline at end of file
diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
index c7fa67a6d623..da87b47e65e6 100644
--- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
+++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/codeinsight/GenerateK2InspectionTests.kt
@@ -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")