diff --git a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties index 5617d42fd10c..499b75822a6a 100644 --- a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties +++ b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties @@ -10,6 +10,7 @@ group.names.other.problems=Other problems group.names.probable.bugs=Probable bugs group.names.redundant.constructs=Redundant constructs group.names.style.issues=Style issues +group.names.code.migration=Code migration fix.insert.delegation.call=Insert ''{0}()'' call fix.introduce.non.null.assertion=Add non-null asserted (!!) call fix.remove.non.null.assertion=Remove unnecessary non-null assertion (!!) @@ -1788,6 +1789,7 @@ add.import.for.0=Add import for ''{0}'' add.import.for.member=Add import for member indent.raw.string=Indent raw string replace.infix.call.with.ordinary.call=Replace infix call with ordinary call +infix.call.may.be.dot.call=Infix call may be dot call insert.curly.braces.around.variable=Insert curly braces around variable add.explicit.type.arguments=Add explicit type arguments introduce.backing.property=Introduce backing property diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/InfixCallToOrdinary.html b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/InfixCallToOrdinary.html new file mode 100644 index 000000000000..03ef5e03d548 --- /dev/null +++ b/plugins/kotlin/code-insight/descriptions/resources-en/inspectionDescriptions/InfixCallToOrdinary.html @@ -0,0 +1,12 @@ + + +Reports for infix function calls that can be replaced with dot-qualified function calls. +

Example:

+

+    1 xor 2
+
+

+    1.xor(2)
+
+ + \ No newline at end of file diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/after.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/after.kt.template deleted file mode 100644 index 3f1b4bf90372..000000000000 --- a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/after.kt.template +++ /dev/null @@ -1 +0,0 @@ -1.xor(2) diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/before.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/before.kt.template deleted file mode 100644 index fb030fcdb5ed..000000000000 --- a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/before.kt.template +++ /dev/null @@ -1 +0,0 @@ -1 xor 2 diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/description.html b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/description.html deleted file mode 100644 index 442422b575c4..000000000000 --- a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/InfixCallToOrdinaryIntention/description.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Converts an infix function call to a dot-qualified function call. - - \ No newline at end of file diff --git a/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml b/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml index 0f481436d1be..3081b9cb24bf 100644 --- a/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml +++ b/plugins/kotlin/code-insight/inspections-shared/resources/kotlin.code-insight.inspections.shared.xml @@ -331,5 +331,13 @@ language="kotlin" key="inspection.redundant.labeled.return.on.last.expression.in.lambda.display.name" bundle="messages.KotlinBundle"/> + + diff --git a/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/InfixCallToOrdinaryInspection.kt b/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/InfixCallToOrdinaryInspection.kt new file mode 100644 index 000000000000..5e0b30657cc2 --- /dev/null +++ b/plugins/kotlin/code-insight/inspections-shared/src/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/InfixCallToOrdinaryInspection.kt @@ -0,0 +1,58 @@ +// Copyright 2000-2024 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.LocalInspectionToolSession +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.modcommand.ModPsiUpdater +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.AbstractKotlinApplicableInspection +import org.jetbrains.kotlin.idea.codeinsight.api.applicators.KotlinApplicabilityRange +import org.jetbrains.kotlin.idea.codeinsight.api.applicators.applicabilityRange +import org.jetbrains.kotlin.idea.codeinsights.impl.base.applicators.ApplicabilityRanges +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.startOffset + +internal class InfixCallToOrdinaryInspection : AbstractKotlinApplicableInspection() { + override fun getProblemDescription(element: KtBinaryExpression) = KotlinBundle.message("replace.infix.call.with.ordinary.call") + + override fun apply(element: KtBinaryExpression, project: Project, updater: ModPsiUpdater) { + convertInfixCallToOrdinary(element) + } + + override fun getActionFamilyName() = KotlinBundle.message("replace.infix.call.with.ordinary.call") + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor = + binaryExpressionVisitor { + visitTargetElement(it, holder, isOnTheFly) + } + + override fun getActionName(element: KtBinaryExpression): String = KotlinBundle.message("replace.infix.call.with.ordinary.call") + + override fun getApplicabilityRange(): KotlinApplicabilityRange = applicabilityRange { + it.operationReference.textRangeInParent + } + + override fun isApplicableByPsi(element: KtBinaryExpression): Boolean { + return !(element.operationToken != KtTokens.IDENTIFIER || element.left == null || element.right == null) + } +} + +fun convertInfixCallToOrdinary(element: KtBinaryExpression): KtExpression { + val argument = KtPsiUtil.safeDeparenthesize(element.right!!) + val pattern = "$0.$1" + when (argument) { + is KtLambdaExpression -> " $2:'{}'" + else -> "($2)" + } + + val replacement = KtPsiFactory(element.project).createExpressionByPattern( + pattern, + element.left!!, + element.operationReference, + argument + ) + + return element.replace(replacement) as KtExpression +} \ No newline at end of file diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java index a26f1df9eed3..6c808f17ca88 100644 --- a/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-shared/tests/k1/test/org/jetbrains/kotlin/idea/codeInsight/inspections/shared/SharedK1LocalInspectionTestGenerated.java @@ -428,6 +428,44 @@ public abstract class SharedK1LocalInspectionTestGenerated extends AbstractShare } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/inspectionsLocal/infixCallToOrdinary") + public static class InfixCallToOrdinary extends AbstractSharedK1LocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("functionCallAfterInfixCall.kt") + public void testFunctionCallAfterInfixCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt"); + } + + @TestMetadata("functionLiteralArgument.kt") + public void testFunctionLiteralArgument() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt"); + } + + @TestMetadata("nonApplicableBinaryOperation.kt") + public void testNonApplicableBinaryOperation() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/nonApplicableBinaryOperation.kt"); + } + + @TestMetadata("nullAssertedCall.kt") + public void testNullAssertedCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt"); + } + + @TestMetadata("parenthesesAroundRightHandArgument.kt") + public void testParenthesesAroundRightHandArgument() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt"); + } + + @TestMetadata("simpleInfixFunctionCall.kt") + public void testSimpleInfixFunctionCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/inspectionsLocal/javaIoSerializableObjectMustHaveReadResolve") public static class JavaIoSerializableObjectMustHaveReadResolve extends AbstractSharedK1LocalInspectionTest { diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java index 9ada3582bade..9c7c9d4f315e 100644 --- a/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-shared/tests/k2/test/org/jetbrains/kotlin/idea/k2/codeInsight/inspections/shared/SharedK2LocalInspectionTestGenerated.java @@ -428,6 +428,44 @@ public abstract class SharedK2LocalInspectionTestGenerated extends AbstractShare } } + @RunWith(JUnit3RunnerWithInners.class) + @TestMetadata("../testData/inspectionsLocal/infixCallToOrdinary") + public static class InfixCallToOrdinary extends AbstractSharedK2LocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("functionCallAfterInfixCall.kt") + public void testFunctionCallAfterInfixCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt"); + } + + @TestMetadata("functionLiteralArgument.kt") + public void testFunctionLiteralArgument() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt"); + } + + @TestMetadata("nonApplicableBinaryOperation.kt") + public void testNonApplicableBinaryOperation() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/nonApplicableBinaryOperation.kt"); + } + + @TestMetadata("nullAssertedCall.kt") + public void testNullAssertedCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt"); + } + + @TestMetadata("parenthesesAroundRightHandArgument.kt") + public void testParenthesesAroundRightHandArgument() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt"); + } + + @TestMetadata("simpleInfixFunctionCall.kt") + public void testSimpleInfixFunctionCall() throws Exception { + runTest("../testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt"); + } + } + @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("../testData/inspectionsLocal/javaIoSerializableObjectMustHaveReadResolve") public static class JavaIoSerializableObjectMustHaveReadResolve extends AbstractSharedK2LocalInspectionTest { diff --git a/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/.inspection b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/.inspection new file mode 100644 index 000000000000..ddacf7c49fc4 --- /dev/null +++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.codeInsight.inspections.shared.InfixCallToOrdinaryInspection diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionCallAfterInfixCall.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionCallAfterInfixCall.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionCallAfterInfixCall.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionCallAfterInfixCall.kt.after rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionCallAfterInfixCall.kt.after diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionLiteralArgument.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionLiteralArgument.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionLiteralArgument.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/functionLiteralArgument.kt.after rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/functionLiteralArgument.kt.after diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nonApplicableBinaryOperation.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nonApplicableBinaryOperation.kt similarity index 63% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nonApplicableBinaryOperation.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nonApplicableBinaryOperation.kt index 3d932d3d0924..a7b6b2fa3ab0 100644 --- a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nonApplicableBinaryOperation.kt +++ b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nonApplicableBinaryOperation.kt @@ -1,4 +1,4 @@ -// IS_APPLICABLE: false +// PROBLEM: none fun foo(x: String) { x == x } diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nullAssertedCall.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nullAssertedCall.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nullAssertedCall.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/nullAssertedCall.kt.after rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/nullAssertedCall.kt.after diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt.after rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt.after diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/simpleInfixFunctionCall.kt b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/simpleInfixFunctionCall.kt rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/simpleInfixFunctionCall.kt.after b/plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt.after similarity index 100% rename from plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/simpleInfixFunctionCall.kt.after rename to plugins/kotlin/code-insight/inspections-shared/tests/testData/inspectionsLocal/infixCallToOrdinary/simpleInfixFunctionCall.kt.after diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/InfixCallFixActionFactory.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/InfixCallFixActionFactory.kt deleted file mode 100644 index 15ecb4baa144..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/inspections/InfixCallFixActionFactory.kt +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - -package org.jetbrains.kotlin.idea.inspections - -import com.intellij.codeInsight.intention.IntentionAction -import com.intellij.codeInspection.IntentionWrapper -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2 -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention -import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory -import org.jetbrains.kotlin.idea.refactoring.canRefactor -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtOperationReferenceExpression - -object InfixCallFixActionFactory : KotlinSingleIntentionActionFactory() { - override fun createAction(diagnostic: Diagnostic): IntentionAction? { - val functionDescriptor = (diagnostic as? DiagnosticWithParameters2<*, *, *>)?.a as? FunctionDescriptor ?: return null - val target = DescriptorToSourceUtilsIde.getAnyDeclaration(diagnostic.psiFile.project, functionDescriptor) - as? KtModifierListOwner - if (target == null || target.canRefactor()) { - // we'll fix the problem by adding the 'infix' modifier to the target - return null - } - - if ((diagnostic.psiElement as? KtOperationReferenceExpression)?.parent !is KtBinaryExpression) return null - return IntentionWrapper(InfixCallToOrdinaryIntention()) - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt deleted file mode 100644 index 763504f38c7a..000000000000 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - -package org.jetbrains.kotlin.idea.intentions - -import com.intellij.openapi.editor.Editor -import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingIntention -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* - -class InfixCallToOrdinaryIntention : SelfTargetingIntention( - KtBinaryExpression::class.java, - KotlinBundle.lazyMessage("replace.infix.call.with.ordinary.call") -) { - override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean { - if (element.operationToken != KtTokens.IDENTIFIER || element.left == null || element.right == null) return false - return element.operationReference.textRange.containsOffset(caretOffset) - } - - override fun applyTo(element: KtBinaryExpression, editor: Editor?) { - Holder.convert(element) - } - - object Holder { - fun convert(element: KtBinaryExpression): KtExpression { - val argument = KtPsiUtil.safeDeparenthesize(element.right!!) - val pattern = "$0.$1" + when (argument) { - is KtLambdaExpression -> " $2:'{}'" - else -> "($2)" - } - - val replacement = KtPsiFactory(element.project).createExpressionByPattern( - pattern, - element.left!!, - element.operationReference.text, - argument - ) - - return element.replace(replacement) as KtExpression - } - } -} diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 474a45182db7..2622483eff82 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.idea.codeinsights.impl.base.quickFix.ChangeVariableM import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementAsConstructorParameter import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler import org.jetbrains.kotlin.idea.inspections.AddModifierFixFactory -import org.jetbrains.kotlin.idea.inspections.InfixCallFixActionFactory import org.jetbrains.kotlin.idea.inspections.RemoveAnnotationFix import org.jetbrains.kotlin.idea.intentions.* import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.* @@ -549,7 +548,6 @@ class QuickFixRegistrar : QuickFixContributor { OPERATOR_MODIFIER_REQUIRED.registerFactory(ImportForMissingOperatorFactory) INFIX_MODIFIER_REQUIRED.registerFactory(AddModifierFixFactory(INFIX_KEYWORD)) - INFIX_MODIFIER_REQUIRED.registerFactory(InfixCallFixActionFactory) UNDERSCORE_IS_RESERVED.registerFactory(RenameUnderscoreFix) diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt index f54d0c01a3af..6ba14b214ef9 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.base.psi.unifier.KotlinPsiUnificationResult.Str import org.jetbrains.kotlin.idea.base.psi.unifier.KotlinPsiUnificationResult.WeakSuccess import org.jetbrains.kotlin.idea.base.psi.unifier.toRange import org.jetbrains.kotlin.idea.base.resources.KotlinBundle +import org.jetbrains.kotlin.idea.codeInsight.inspections.shared.convertInfixCallToOrdinary import org.jetbrains.kotlin.idea.codeinsights.impl.base.inspections.OperatorToFunctionConverter import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.appendElement @@ -34,7 +35,6 @@ import org.jetbrains.kotlin.idea.core.moveInsideParenthesesAndReplaceWith import org.jetbrains.kotlin.idea.core.toVisibility import org.jetbrains.kotlin.idea.inspections.PublicApiImplicitTypeInspection import org.jetbrains.kotlin.idea.inspections.UseExpressionBodyInspection -import org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeArgumentsIntention import org.jetbrains.kotlin.idea.refactoring.introduce.* import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.* @@ -292,7 +292,7 @@ private fun makeCall( val newNameExpression = when (val operationExpression = anchor.parent as? KtOperationExpression ?: return null) { is KtUnaryExpression -> OperatorToFunctionConverter.convert(operationExpression).second is KtBinaryExpression -> { - InfixCallToOrdinaryIntention.Holder.convert(operationExpression).getCalleeExpressionIfAny() + convertInfixCallToOrdinary(operationExpression).getCalleeExpressionIfAny() } else -> null } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java index c38b4a77b55a..9448429e8731 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/K1IntentionTestGenerated.java @@ -10949,44 +10949,6 @@ public abstract class K1IntentionTestGenerated extends AbstractK1IntentionTest { } } - @RunWith(JUnit3RunnerWithInners.class) - @TestMetadata("testData/intentions/infixCallToOrdinary") - public static class InfixCallToOrdinary extends AbstractK1IntentionTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); - } - - @TestMetadata("functionCallAfterInfixCall.kt") - public void testFunctionCallAfterInfixCall() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/functionCallAfterInfixCall.kt"); - } - - @TestMetadata("functionLiteralArgument.kt") - public void testFunctionLiteralArgument() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/functionLiteralArgument.kt"); - } - - @TestMetadata("nonApplicableBinaryOperation.kt") - public void testNonApplicableBinaryOperation() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/nonApplicableBinaryOperation.kt"); - } - - @TestMetadata("nullAssertedCall.kt") - public void testNullAssertedCall() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/nullAssertedCall.kt"); - } - - @TestMetadata("parenthesesAroundRightHandArgument.kt") - public void testParenthesesAroundRightHandArgument() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/parenthesesAroundRightHandArgument.kt"); - } - - @TestMetadata("simpleInfixFunctionCall.kt") - public void testSimpleInfixFunctionCall() throws Exception { - runTest("testData/intentions/infixCallToOrdinary/simpleInfixFunctionCall.kt"); - } - } - @RunWith(JUnit3RunnerWithInners.class) @TestMetadata("testData/intentions/insertCurlyBracesToTemplate") public static class InsertCurlyBracesToTemplate extends AbstractK1IntentionTest { diff --git a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/.intention b/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/.intention deleted file mode 100644 index db03b3260af1..000000000000 --- a/plugins/kotlin/idea/tests/testData/intentions/infixCallToOrdinary/.intention +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention diff --git a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/infixCall2.before.Main.kt b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/infixCall2.before.Main.kt index 220150f8f64d..aaddc8201ce2 100644 --- a/plugins/kotlin/idea/tests/testData/quickfix/autoImports/infixCall2.before.Main.kt +++ b/plugins/kotlin/idea/tests/testData/quickfix/autoImports/infixCall2.before.Main.kt @@ -2,7 +2,7 @@ // ERROR: Unresolved reference: foo // ACTION: Create extension function 'H.foo' // ACTION: Create member function 'H.foo' -// ACTION: Replace infix call with ordinary call +// FIX: Replace infix call with ordinary call package h diff --git a/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml b/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml index bb03092f651e..edb0fab671eb 100644 --- a/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml +++ b/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml @@ -217,13 +217,6 @@ group.names.kotlin - - kotlin - org.jetbrains.kotlin.idea.intentions.InfixCallToOrdinaryIntention - messages.KotlinBundle - group.names.kotlin - - kotlin org.jetbrains.kotlin.idea.intentions.ToInfixCallIntention