diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt index 41f0cc24c14..281b9149f0b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt @@ -365,3 +365,5 @@ fun E.createSmartPointer(): SmartPsiElementPointer = fun PsiElement.before(element: PsiElement) = textRange.endOffset <= element.textRange.startOffset +inline fun PsiElement.getLastParentOfTypeInRow() = parents.takeWhile { it is T }.lastOrNull() + diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt index 3ef0c77fe3f..5df28d8b6f6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt @@ -19,10 +19,13 @@ package org.jetbrains.kotlin.idea.intentions.conventionNameCalls import com.intellij.codeInsight.intention.HighPriorityAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.intentions.* +import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @@ -45,7 +48,7 @@ class ReplaceCallWithBinaryOperatorIntention : SelfTargetingRangeIntention() ?: this).parent as? KtPrefixExpression + + private fun operation(calleeExpression: KtSimpleNameExpression): KtSingleValueToken? { val identifier = calleeExpression.getReferencedNameAsName() if (identifier == OperatorNameConventions.EQUALS) { - return KtTokens.EQEQ.value + val prefixExpression = calleeExpression.parent?.parent?.getWrappingPrefixExpressionIfAny() + return if (prefixExpression != null && prefixExpression.operationToken == KtTokens.EXCL) KtTokens.EXCLEQ + else KtTokens.EQEQ } - return OperatorConventions.BINARY_OPERATION_NAMES.inverse()[identifier]?.value + return OperatorConventions.BINARY_OPERATION_NAMES.inverse()[identifier] } } diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt new file mode 100644 index 00000000000..cb4b458cf59 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '!=' operator + +val x = !2.equals(3) \ No newline at end of file diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt.after b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt.after new file mode 100644 index 00000000000..d750166c834 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt.after @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '!=' operator + +val x = 2 != 3 \ No newline at end of file diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt new file mode 100644 index 00000000000..98e40f7ff06 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '!=' operator + +val x = !(2.equals(3)) \ No newline at end of file diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt.after b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt.after new file mode 100644 index 00000000000..d750166c834 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt.after @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '!=' operator + +val x = 2 != 3 \ No newline at end of file diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt new file mode 100644 index 00000000000..7a6fefbf036 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '==' operator + +val x = !(2.equals(3) && 4.equals(5)) \ No newline at end of file diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt.after b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt.after new file mode 100644 index 00000000000..70ff72fd904 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt.after @@ -0,0 +1,3 @@ +// INTENTION_TEXT: Replace with '==' operator + +val x = !(2 == 3 && 4.equals(5)) \ 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 6b782e173d6..1d82d627d75 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -2780,6 +2780,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("notEquals.kt") + public void testNotEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEquals.kt"); + doTest(fileName); + } + + @TestMetadata("notEqualsBrackets.kt") + public void testNotEqualsBrackets() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBrackets.kt"); + doTest(fileName); + } + + @TestMetadata("notEqualsBracketsComplex.kt") + public void testNotEqualsBracketsComplex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/notEqualsBracketsComplex.kt"); + doTest(fileName); + } + @TestMetadata("plusSanityTest.kt") public void testPlusSanityTest() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/plusSanityTest.kt");