diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOrdinaryAssignmentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOrdinaryAssignmentIntention.kt index 037c314fa5c..3931b4389ea 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOrdinaryAssignmentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOrdinaryAssignmentIntention.kt @@ -8,21 +8,23 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.codeInsight.intention.LowPriorityAction import com.intellij.openapi.editor.Editor import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.createExpressionByPattern +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class ReplaceWithOrdinaryAssignmentIntention : SelfTargetingIntention( KtBinaryExpression::class.java, KotlinBundle.lazyMessage("replace.with.ordinary.assignment") ), LowPriorityAction { override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean { + val operationReference = element.operationReference + if (!operationReference.textRange.containsOffset(caretOffset)) return false if (element.operationToken !in KtTokens.AUGMENTED_ASSIGNMENTS) return false - if (element.left !is KtNameReferenceExpression) return false + val left = element.left ?: return false + if ((left.safeAs()?.selectorExpression ?: left) !is KtNameReferenceExpression) return false if (element.right == null) return false - return element.operationReference.textRange.containsOffset(caretOffset) + return operationReference.mainReference.resolve().safeAs()?.name?.endsWith("Assign") != true } override fun applyTo(element: KtBinaryExpression, editor: Editor?) { diff --git a/idea/testData/intentions/replaceWithOrdinaryAssignment/minusAssignOperatorFun.kt b/idea/testData/intentions/replaceWithOrdinaryAssignment/minusAssignOperatorFun.kt new file mode 100644 index 00000000000..bf31689856a --- /dev/null +++ b/idea/testData/intentions/replaceWithOrdinaryAssignment/minusAssignOperatorFun.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +operator fun Int.minusAssign(element: Int) {} + +fun test() { + val x = 1 + x -= 9 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithOrdinaryAssignment/mutableList.kt b/idea/testData/intentions/replaceWithOrdinaryAssignment/mutableList.kt new file mode 100644 index 00000000000..792fda02f33 --- /dev/null +++ b/idea/testData/intentions/replaceWithOrdinaryAssignment/mutableList.kt @@ -0,0 +1,6 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME +fun main() { + val mutableList = mutableListOf(4, 5, 6, 7, 8) + mutableList += 9 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithOrdinaryAssignment/plusAssignOperatorFun.kt b/idea/testData/intentions/replaceWithOrdinaryAssignment/plusAssignOperatorFun.kt new file mode 100644 index 00000000000..7a1aa5b0839 --- /dev/null +++ b/idea/testData/intentions/replaceWithOrdinaryAssignment/plusAssignOperatorFun.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +operator fun Int.plusAssign(element: Int) {} + +fun test() { + val x = 1 + x += 9 +} diff --git a/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt b/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt new file mode 100644 index 00000000000..d5edf99798b --- /dev/null +++ b/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt @@ -0,0 +1,8 @@ +class Foo { + var x: Int = 1 +} + +fun main() { + val foo = Foo() + foo.x += 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt.after b/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt.after new file mode 100644 index 00000000000..1d8cbf8d48f --- /dev/null +++ b/idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt.after @@ -0,0 +1,8 @@ +class Foo { + var x: Int = 1 +} + +fun main() { + val foo = Foo() + foo.x = foo.x + 1 +} \ No newline at end of file diff --git a/idea/testData/quickfix/allowResolveInWriteAction.txt b/idea/testData/quickfix/allowResolveInWriteAction.txt index cf806580272..29c3a220e09 100644 --- a/idea/testData/quickfix/allowResolveInWriteAction.txt +++ b/idea/testData/quickfix/allowResolveInWriteAction.txt @@ -18,6 +18,7 @@ org.jetbrains.kotlin.idea.intentions.ConvertPropertyInitializerToGetterIntention org.jetbrains.kotlin.idea.intentions.CreateKotlinSubClassIntention org.jetbrains.kotlin.idea.intentions.MoveMemberToCompanionObjectIntention org.jetbrains.kotlin.idea.intentions.MovePropertyToConstructorIntention +org.jetbrains.kotlin.idea.intentions.ReplaceWithOrdinaryAssignmentIntention org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention org.jetbrains.kotlin.idea.quickfix.AddAnnotationTargetFix org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix diff --git a/idea/testData/quickfix/assignOperatorAmbiguity/changeToVal/classVariable.kt b/idea/testData/quickfix/assignOperatorAmbiguity/changeToVal/classVariable.kt index 8d4fbff5b16..a7a744ecfcd 100644 --- a/idea/testData/quickfix/assignOperatorAmbiguity/changeToVal/classVariable.kt +++ b/idea/testData/quickfix/assignOperatorAmbiguity/changeToVal/classVariable.kt @@ -1,7 +1,6 @@ // "Change 'list' to val" "false" // ACTION: Replace overloaded operator with function call // ACTION: Replace with 'plusAssign()' call -// ACTION: Replace with ordinary assignment // ERROR: Assignment operators ambiguity:
public operator fun Collection.plus(element: Int): List defined in kotlin.collections
public inline operator fun MutableCollection.plusAssign(element: Int): Unit defined in kotlin.collections // WITH_RUNTIME diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 2511560132d..d8a8fcd66ee 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -15607,6 +15607,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/complexRightExpression.kt"); } + @TestMetadata("minusAssignOperatorFun.kt") + public void testMinusAssignOperatorFun() throws Exception { + runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/minusAssignOperatorFun.kt"); + } + + @TestMetadata("mutableList.kt") + public void testMutableList() throws Exception { + runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/mutableList.kt"); + } + @TestMetadata("nonAssignmentExpression.kt") public void testNonAssignmentExpression() throws Exception { runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/nonAssignmentExpression.kt"); @@ -15617,6 +15627,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/nonAugmentedAssign.kt"); } + @TestMetadata("plusAssignOperatorFun.kt") + public void testPlusAssignOperatorFun() throws Exception { + runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/plusAssignOperatorFun.kt"); + } + + @TestMetadata("qualifiedExpression.kt") + public void testQualifiedExpression() throws Exception { + runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/qualifiedExpression.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("idea/testData/intentions/replaceWithOrdinaryAssignment/simple.kt");