From 5089df2441448d19d2b45245259b8a9c93ca5077 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Mon, 11 Feb 2019 23:36:29 +0300 Subject: [PATCH] Fix convert unary operator to function call #KT-25501 Fixed --- .../intentions/OperatorToFunctionIntention.kt | 90 +++++++++---------- .../ReplaceCallWithUnaryOperatorIntention.kt | 18 ++-- .../replaceCallWithUnaryOperator/dec.kt | 8 ++ .../replaceCallWithUnaryOperator/inc.kt | 8 ++ ...ApplicablePostfixPlusPlusInIfExpression.kt | 9 ++ ...ablePostfixPlusPlusInNestedIfExpression.kt | 9 ++ .../notApplicablePostfixPlusPlusInProperty.kt | 5 ++ ...plicablePostfixPlusPlusInWhenExpression.kt | 8 ++ .../postfixMinusMinus.kt.after | 2 +- .../postfixPlusPlusInIfExpression.kt | 8 ++ .../postfixPlusPlusInIfExpression.kt.after | 8 ++ .../postfixPlusPlusInLoop.kt | 6 ++ .../postfixPlusPlusInLoop.kt.after | 6 ++ .../postfixPlusPlusInWhenExpression.kt | 7 ++ .../postfixPlusPlusInWhenExpression.kt.after | 7 ++ .../prefixPlusPlus.kt.after | 2 +- .../intentions/IntentionTestGenerated.java | 45 ++++++++++ 17 files changed, 188 insertions(+), 58 deletions(-) create mode 100644 idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/dec.kt create mode 100644 idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/inc.kt create mode 100644 idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInIfExpression.kt create mode 100644 idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInNestedIfExpression.kt create mode 100644 idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInProperty.kt create mode 100644 idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInWhenExpression.kt create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt.after create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt.after create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt create mode 100644 idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt.after diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt index 5433dd872af..99eca9a9d2a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt @@ -21,8 +21,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.caches.resolve.* import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.references.ReferenceAccess import org.jetbrains.kotlin.idea.references.readWriteAccess @@ -30,30 +29,37 @@ import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector +import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.util.OperatorNameConventions -class OperatorToFunctionIntention : SelfTargetingIntention(KtExpression::class.java, "Replace overloaded operator with function call") { +class OperatorToFunctionIntention : + SelfTargetingIntention(KtExpression::class.java, "Replace overloaded operator with function call") { companion object { - private fun isApplicablePrefix(element: KtPrefixExpression, caretOffset: Int): Boolean { + private fun isApplicableUnary(element: KtUnaryExpression, caretOffset: Int): Boolean { val opRef = element.operationReference if (!opRef.textRange.containsOffset(caretOffset)) return false return when (opRef.getReferencedNameElementType()) { - KtTokens.PLUS, KtTokens.MINUS, KtTokens.PLUSPLUS, KtTokens.MINUSMINUS, KtTokens.EXCL -> true + KtTokens.PLUS, KtTokens.MINUS, KtTokens.EXCL -> true + KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> !isUsedAsExpression(element) else -> false } } - private fun isApplicablePostfix(element: KtPostfixExpression, caretOffset: Int): Boolean { - val opRef = element.operationReference - if (!opRef.textRange.containsOffset(caretOffset)) return false - if (element.baseExpression == null) return false - return when (opRef.getReferencedNameElementType()) { - KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> true - else -> false - } + // TODO: replace to `element.isUsedAsExpression(element.analyze(BodyResolveMode.PARTIAL_WITH_CFA))` after fix KT-25682 + private fun isUsedAsExpression(element: KtExpression): Boolean { + val parent = element.parent + return if (parent is KtBlockExpression) parent.lastBlockStatementOrThis() == element && parentIsUsedAsExpression(parent.parent) + else parentIsUsedAsExpression(parent) + } + + private fun parentIsUsedAsExpression(element: PsiElement): Boolean = when (val parent = element.parent) { + is KtLoopExpression, is KtFile -> false + is KtIfExpression, is KtWhenExpression -> (parent as KtExpression).isUsedAsExpression(parent.analyze(BodyResolveMode.PARTIAL_WITH_CFA)) + else -> true } private fun isApplicableBinary(element: KtBinaryExpression, caretOffset: Int): Boolean { @@ -95,13 +101,12 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre return false } - private fun convertPrefix(element: KtPrefixExpression): KtExpression { + private fun convertUnary(element: KtUnaryExpression): KtExpression { val op = element.operationReference.getReferencedNameElementType() val operatorName = when (op) { + KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> return convertUnaryWithAssignFix(element) KtTokens.PLUS -> OperatorNameConventions.UNARY_PLUS KtTokens.MINUS -> OperatorNameConventions.UNARY_MINUS - KtTokens.PLUSPLUS -> OperatorNameConventions.INC - KtTokens.MINUSMINUS -> OperatorNameConventions.DEC KtTokens.EXCL -> OperatorNameConventions.NOT else -> return element } @@ -110,7 +115,7 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre return element.replace(transformed) as KtExpression } - private fun convertPostFix(element: KtPostfixExpression): KtExpression { + private fun convertUnaryWithAssignFix(element: KtUnaryExpression): KtExpression { val op = element.operationReference.getReferencedNameElementType() val operatorName = when (op) { KtTokens.PLUSPLUS -> OperatorNameConventions.INC @@ -118,7 +123,7 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre else -> return element } - val transformed = KtPsiFactory(element).createExpressionByPattern("$0.$1()", element.baseExpression!!, operatorName) + val transformed = KtPsiFactory(element).createExpressionByPattern("$0 = $0.$1()", element.baseExpression!!, operatorName) return element.replace(transformed) as KtExpression } @@ -188,8 +193,7 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre appendExpressions(element.indexExpressions) appendFixedText(",") appendExpression(parent.right) - } - else { + } else { appendFixedText("get(") appendExpressions(element.indexExpressions) } @@ -234,8 +238,7 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre val commentSaver = CommentSaver(elementToBeReplaced, saveLineBreaks = true) val result = when (element) { - is KtPrefixExpression -> convertPrefix(element) - is KtPostfixExpression -> convertPostFix(element) + is KtUnaryExpression -> convertUnary(element) is KtBinaryExpression -> convertBinary(element) is KtArrayAccessExpression -> convertArrayAccess(element) is KtCallExpression -> convertCall(element) @@ -244,40 +247,29 @@ class OperatorToFunctionIntention : SelfTargetingIntention(KtExpre commentSaver.restore(result) - val callName = findCallName(result) - ?: error("No call name found in ${result.text}") + val callName = findCallName(result) ?: error("No call name found in ${result.text}") return result to callName } - private fun findCallName(result: KtExpression): KtSimpleNameExpression? { - return when (result) { - is KtBinaryExpression -> { - if (KtPsiUtil.isAssignment(result)) - findCallName(result.right!!) - else - findCallName(result.left!!) - } - - is KtUnaryExpression -> { - result.baseExpression?.let { findCallName(it) } - } - - is KtParenthesizedExpression -> result.expression?.let { findCallName(it) } - - else -> result.getQualifiedElementSelector() as KtSimpleNameExpression? + private fun findCallName(result: KtExpression): KtSimpleNameExpression? = when (result) { + is KtBinaryExpression -> { + if (KtPsiUtil.isAssignment(result)) + findCallName(result.right!!) + else + findCallName(result.left!!) } + is KtUnaryExpression -> result.baseExpression?.let { findCallName(it) } + is KtParenthesizedExpression -> result.expression?.let { findCallName(it) } + else -> result.getQualifiedElementSelector() as KtSimpleNameExpression? } } - override fun isApplicableTo(element: KtExpression, caretOffset: Int): Boolean { - return when (element) { - is KtPrefixExpression -> isApplicablePrefix(element, caretOffset) - is KtPostfixExpression -> isApplicablePostfix(element, caretOffset) - is KtBinaryExpression -> isApplicableBinary(element, caretOffset) - is KtArrayAccessExpression -> isApplicableArrayAccess(element, caretOffset) - is KtCallExpression -> isApplicableCall(element, caretOffset) - else -> false - } + override fun isApplicableTo(element: KtExpression, caretOffset: Int): Boolean = when (element) { + is KtUnaryExpression -> isApplicableUnary(element, caretOffset) + is KtBinaryExpression -> isApplicableBinary(element, caretOffset) + is KtArrayAccessExpression -> isApplicableArrayAccess(element, caretOffset) + is KtCallExpression -> isApplicableCall(element, caretOffset) + else -> false } override fun applyTo(element: KtExpression, editor: Editor?) { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithUnaryOperatorIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithUnaryOperatorIntention.kt index 6fd5e3ac05b..8e3ae726dc5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithUnaryOperatorIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithUnaryOperatorIntention.kt @@ -23,15 +23,19 @@ import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention import org.jetbrains.kotlin.idea.intentions.callExpression import org.jetbrains.kotlin.idea.intentions.calleeName import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue +import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtDotQualifiedExpression import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.createExpressionByPattern import org.jetbrains.kotlin.types.expressions.OperatorConventions -class ReplaceCallWithUnaryOperatorIntention : SelfTargetingRangeIntention(KtDotQualifiedExpression::class.java, "Replace call with unary operator"), HighPriorityAction { +class ReplaceCallWithUnaryOperatorIntention : + SelfTargetingRangeIntention(KtDotQualifiedExpression::class.java, "Replace call with unary operator"), + HighPriorityAction { override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? { val operation = operation(element.calleeName) ?: return null + if (!isApplicableOperation(operation)) return null val call = element.callExpression ?: return null if (call.typeArgumentList != null) return null @@ -39,18 +43,18 @@ class ReplaceCallWithUnaryOperatorIntention : SelfTargetingRangeIntention() +} diff --git a/idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/inc.kt b/idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/inc.kt new file mode 100644 index 00000000000..6fe51a12d01 --- /dev/null +++ b/idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/inc.kt @@ -0,0 +1,8 @@ +// IS_APPLICABLE: false +fun test() { + class Test { + operator fun inc(): Test = Test() + } + val test = Test() + test.inc() +} diff --git a/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInIfExpression.kt b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInIfExpression.kt new file mode 100644 index 00000000000..7381bb4c29d --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInIfExpression.kt @@ -0,0 +1,9 @@ +// IS_APPLICABLE: false +fun foo() { + var a = 0 + val b = if (true) { + a++ + } else { + a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInNestedIfExpression.kt b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInNestedIfExpression.kt new file mode 100644 index 00000000000..6ed239cdbde --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInNestedIfExpression.kt @@ -0,0 +1,9 @@ +// IS_APPLICABLE: false +fun foo() { + var a = 0 + val b = if (false) { + if (true) { + a++ + } else a + } else a +} diff --git a/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInProperty.kt b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInProperty.kt new file mode 100644 index 00000000000..5490d8e76a5 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInProperty.kt @@ -0,0 +1,5 @@ +// IS_APPLICABLE: false +fun foo() { + var a = 0 + val b = a++ +} diff --git a/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInWhenExpression.kt b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInWhenExpression.kt new file mode 100644 index 00000000000..20affa88766 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInWhenExpression.kt @@ -0,0 +1,8 @@ +// IS_APPLICABLE: false +fun foo() { + var a = 0 + val b = when { + true -> a++ + else -> a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixMinusMinus.kt.after b/idea/testData/intentions/operatorToFunction/postfixMinusMinus.kt.after index 56091438b24..d5d57713983 100644 --- a/idea/testData/intentions/operatorToFunction/postfixMinusMinus.kt.after +++ b/idea/testData/intentions/operatorToFunction/postfixMinusMinus.kt.after @@ -1,4 +1,4 @@ fun foo() { var a = 5 - a.dec() + a = a.dec() } diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt new file mode 100644 index 00000000000..b0ac6320451 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt @@ -0,0 +1,8 @@ +fun foo() { + var a = 0 + if (true) { + a++ + } else { + a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt.after b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt.after new file mode 100644 index 00000000000..410646075b0 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt.after @@ -0,0 +1,8 @@ +fun foo() { + var a = 0 + if (true) { + a = a.inc() + } else { + a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt new file mode 100644 index 00000000000..acabb4c2e8a --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt @@ -0,0 +1,6 @@ +fun foo() { + var a = 0 + for (i in 0..42) + a++ + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt.after b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt.after new file mode 100644 index 00000000000..929260e8788 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt.after @@ -0,0 +1,6 @@ +fun foo() { + var a = 0 + for (i in 0..42) + a = a.inc() + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt new file mode 100644 index 00000000000..c3bfa6d78ca --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt @@ -0,0 +1,7 @@ +fun foo() { + var a = 0 + when { + true -> a++ + else -> a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt.after b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt.after new file mode 100644 index 00000000000..7ecbbce1548 --- /dev/null +++ b/idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt.after @@ -0,0 +1,7 @@ +fun foo() { + var a = 0 + when { + true -> a = a.inc() + else -> a-- + } +} diff --git a/idea/testData/intentions/operatorToFunction/prefixPlusPlus.kt.after b/idea/testData/intentions/operatorToFunction/prefixPlusPlus.kt.after index c4aa68e20ce..3db22355543 100644 --- a/idea/testData/intentions/operatorToFunction/prefixPlusPlus.kt.after +++ b/idea/testData/intentions/operatorToFunction/prefixPlusPlus.kt.after @@ -1,4 +1,4 @@ fun foo() { var a = 0 - a.inc() + a = a.inc() } diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index fccfedb1cf2..b55ff82d587 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -4187,6 +4187,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/complexPlus.kt"); } + @TestMetadata("dec.kt") + public void testDec() throws Exception { + runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/dec.kt"); + } + @TestMetadata("extensionFunction.kt") public void testExtensionFunction() throws Exception { runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/extensionFunction.kt"); @@ -4197,6 +4202,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/functionLiteralArgument.kt"); } + @TestMetadata("inc.kt") + public void testInc() throws Exception { + runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/inc.kt"); + } + @TestMetadata("minusSanityTest.kt") public void testMinusSanityTest() throws Exception { runTest("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/minusSanityTest.kt"); @@ -13138,6 +13148,26 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/operatorToFunction/notApplicableNewClassObject.kt"); } + @TestMetadata("notApplicablePostfixPlusPlusInIfExpression.kt") + public void testNotApplicablePostfixPlusPlusInIfExpression() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInIfExpression.kt"); + } + + @TestMetadata("notApplicablePostfixPlusPlusInNestedIfExpression.kt") + public void testNotApplicablePostfixPlusPlusInNestedIfExpression() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInNestedIfExpression.kt"); + } + + @TestMetadata("notApplicablePostfixPlusPlusInProperty.kt") + public void testNotApplicablePostfixPlusPlusInProperty() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInProperty.kt"); + } + + @TestMetadata("notApplicablePostfixPlusPlusInWhenExpression.kt") + public void testNotApplicablePostfixPlusPlusInWhenExpression() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/notApplicablePostfixPlusPlusInWhenExpression.kt"); + } + @TestMetadata("pluPlus.kt") public void testPluPlus() throws Exception { runTest("idea/testData/intentions/operatorToFunction/pluPlus.kt"); @@ -13148,6 +13178,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/operatorToFunction/postfixMinusMinus.kt"); } + @TestMetadata("postfixPlusPlusInIfExpression.kt") + public void testPostfixPlusPlusInIfExpression() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/postfixPlusPlusInIfExpression.kt"); + } + + @TestMetadata("postfixPlusPlusInLoop.kt") + public void testPostfixPlusPlusInLoop() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/postfixPlusPlusInLoop.kt"); + } + + @TestMetadata("postfixPlusPlusInWhenExpression.kt") + public void testPostfixPlusPlusInWhenExpression() throws Exception { + runTest("idea/testData/intentions/operatorToFunction/postfixPlusPlusInWhenExpression.kt"); + } + @TestMetadata("prefixPlus.kt") public void testPrefixPlus() throws Exception { runTest("idea/testData/intentions/operatorToFunction/prefixPlus.kt");