From c285e5ba3b9b61fb8cf504cfee4f0d02e0d75633 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 14 Dec 2016 14:40:49 +0300 Subject: [PATCH] JS: add tests too prove that operator conventions are correctly inlined. Support inlining of `invoke` operator. See KT-7588 --- .../js/test/semantics/BoxJsTestGenerated.java | 12 ++++ .../callTranslator/CallTranslator.kt | 7 +- .../testData/box/inline/operators.kt | 71 +++++++++++++++++++ .../box/inlineMultiModule/operators.kt | 26 +++++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 js/js.translator/testData/box/inline/operators.kt create mode 100644 js/js.translator/testData/box/inlineMultiModule/operators.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index cb98efdceb3..40c7b6ac05e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -3890,6 +3890,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("operators.kt") + public void testOperators() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inline/operators.kt"); + doTest(fileName); + } + @TestMetadata("params.kt") public void testParams() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inline/params.kt"); @@ -4541,6 +4547,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("operators.kt") + public void testOperators() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/operators.kt"); + doTest(fileName); + } + @TestMetadata("parameterWithDefaultValue.kt") public void testParameterWithDefaultValue() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/parameterWithDefaultValue.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt index 2756a472320..0fbbee24542 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.callTranslator import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.metadata.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -106,11 +107,13 @@ private fun translateCall(context: TranslationContext, translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(newReceiver)) } else { val dispatchReceiver = CallTranslator.translateGet(context, variableCall, null) + val isFunctionType = resolvedCall.variableCall.resultingDescriptor.type.isFunctionTypeOrSubtype + val inlineCall = if (isFunctionType) resolvedCall.variableCall else resolvedCall if (explicitReceivers.extensionOrDispatchReceiver == null) { - translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(dispatchReceiver)) + translateFunctionCall(context, resolvedCall.functionCall, inlineCall, ExplicitReceivers(dispatchReceiver)) } else { - translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, + translateFunctionCall(context, resolvedCall.functionCall, inlineCall, ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver)) } } diff --git a/js/js.translator/testData/box/inline/operators.kt b/js/js.translator/testData/box/inline/operators.kt new file mode 100644 index 00000000000..3dc599b051f --- /dev/null +++ b/js/js.translator/testData/box/inline/operators.kt @@ -0,0 +1,71 @@ +// CHECK_NOT_CALLED_IN_SCOPE: function=plus_za3lpa$ scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=plus scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=invoke scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=get_za3lpa$ scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=set_vux9f0$ scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=dec scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=minus_za3lpa$ scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=invoke_rksjo2$ scope=test + +class A { + inline operator fun plus(a: Int) = a + 10 +} + +class B + +inline operator fun B.plus(b: Int) = b + 20 + +object O { + inline operator fun invoke() = 42 + + inline operator fun Int.invoke(other: Int) = this + other + + fun test() = (1200)(34) +} + +object R { + inline operator fun get(i: Int) = 99 + i +} + +object S { + var lastResult = 0 + + inline operator fun set(i: Int, value: Int) { + lastResult = i + value + } +} + +class N(val value: Int) { + inline operator fun minus(other: Int) = N(value - other) + + inline operator fun dec() = N(value - 1) +} + +fun box(): String { + var result = A() + 1 + if (result != 11) return "fail: member operator: $result" + + result = B() + 2 + if (result != 22) return "fail: extension operator: $result" + + result = O() + if (result != 42) return "fail: invoke operator: $result" + + result = O.test() + if (result != 1234) return "fail: extension invoke operator: $result" + + result = R[1] + if (result != 100) return "fail: get operator: $result" + + S[2] = 3 + result = S.lastResult + if (result != 5) return "fail: set operator: $result" + + var n = N(10) + n-- + if (n.value != 9) return "fail: decrement: ${n.value}" + n -= 3 + if (n.value != 6) return "fail: augmented assignment: ${n.value}" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/inlineMultiModule/operators.kt b/js/js.translator/testData/box/inlineMultiModule/operators.kt new file mode 100644 index 00000000000..9ab6883d3ac --- /dev/null +++ b/js/js.translator/testData/box/inlineMultiModule/operators.kt @@ -0,0 +1,26 @@ +// MODULE: lib +// FILE: lib.kt + +class A { + inline operator fun plus(a: Int) = a + 10 +} + +class B + +inline operator fun B.plus(b: Int) = b + 20 + +// MODULE: main(lib) +// FILE: main.kt + +// CHECK_NOT_CALLED_IN_SCOPE: function=plus_za3lpa$ scope=box +// CHECK_NOT_CALLED_IN_SCOPE: function=plus scope=box + +fun box(): String { + var result = A() + 1 + if (result != 11) return "fail: member operator" + + result = B() + 2 + if (result != 22) return "fail: extension operator" + + return "OK" +} \ No newline at end of file