diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt index 48ac6bb0bb2..30b73c021b1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor +import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze @@ -49,17 +50,20 @@ public class ReplaceWithOperatorAssignmentIntention : JetSelfTargetingOffsetInde val operationToken = expression.getOperationToken() setText("Replace with ${expression.getOperationReference().getText()}= expression") + val expressionLeft = expression.getLeft() + val expressionRight = expression.getRight() return when { - variableExpression.matches(expression.getLeft()) -> { - operationToken == JetTokens.PLUS || operationToken == JetTokens.MINUS || operationToken == JetTokens.MUL || operationToken == JetTokens.DIV || operationToken == JetTokens.PERC + variableExpression.matches(expressionLeft) -> { + isArithmeticOperation(operationToken) } - variableExpression.matches(expression.getRight()) -> { - isPrimitiveOperation && (operationToken == JetTokens.PLUS || operationToken == JetTokens.MUL) + variableExpression.matches(expressionRight) -> { + isPrimitiveOperation && isCommutative(operationToken) } - expression.getLeft() is JetBinaryExpression -> { - isPrimitiveOperation && checkExpressionRepeat(variableExpression, expression.getLeft() as JetBinaryExpression) + expressionLeft is JetBinaryExpression -> { + val sameCommutativeOperation = expressionLeft.getOperationToken() == operationToken && isCommutative(operationToken) + isPrimitiveOperation && sameCommutativeOperation && checkExpressionRepeat(variableExpression, expressionLeft) } else -> { @@ -68,6 +72,13 @@ public class ReplaceWithOperatorAssignmentIntention : JetSelfTargetingOffsetInde } } + private fun isCommutative(operationToken: IElementType) = operationToken == JetTokens.PLUS || operationToken == JetTokens.MUL + private fun isArithmeticOperation(operationToken: IElementType) = operationToken == JetTokens.PLUS || + operationToken == JetTokens.MINUS || + operationToken == JetTokens.MUL || + operationToken == JetTokens.DIV || + operationToken == JetTokens.PERC + override fun applyTo(element: JetBinaryExpression, editor: Editor) { val replacement = buildOperatorAssignmentText( element.getLeft() as JetSimpleNameExpression, diff --git a/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperators.kt b/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperators.kt index 83bbbeccc02..2adf22e0c02 100644 --- a/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperators.kt +++ b/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperators.kt @@ -1,5 +1,5 @@ // IS_APPLICABLE: false fun foo() { var x = 0 - x = x / 1 + 1 + x = x / 1 + 1 } \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt b/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt index 1e25c359d77..16835e68df3 100644 --- a/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt +++ b/idea/testData/intentions/replaceWithOperatorAssignment/illegalMultipleOperatorsMiddle.kt @@ -2,5 +2,5 @@ fun foo() { var x = 0 val y = 0 - x = y / x + 0 + x = y / x + 0 } \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithOperatorAssignment/nonCommutativeRepeat.kt b/idea/testData/intentions/replaceWithOperatorAssignment/nonCommutativeRepeat.kt new file mode 100644 index 00000000000..e8029e6c30d --- /dev/null +++ b/idea/testData/intentions/replaceWithOperatorAssignment/nonCommutativeRepeat.kt @@ -0,0 +1,5 @@ +// IS_APPLICABLE: false +fun foo() { + var x = 0 + x = x - 1 - 1 +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index e8901f44991..6aa0ad18581 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -6059,6 +6059,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("nonCommutativeRepeat.kt") + public void testNonCommutativeRepeat() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/replaceWithOperatorAssignment/nonCommutativeRepeat.kt"); + doTest(fileName); + } + @TestMetadata("nonRepeatingAssignment.kt") public void testNonRepeatingAssignment() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/replaceWithOperatorAssignment/nonRepeatingAssignment.kt");