From 818b197169d3e57b9a81830e67d52576136babf6 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Wed, 6 May 2015 17:23:21 +0300 Subject: [PATCH] JS: support reified usage in extension functions --- .../test/semantics/ReifiedTestGenerated.java | 6 +++++ .../callTranslator/FunctionCallCases.kt | 23 ++++++++----------- .../reference/CallArgumentTranslator.kt | 12 ++++++---- .../testData/reified/cases/extensionFun.kt | 17 ++++++++++++++ 4 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 js/js.translator/testData/reified/cases/extensionFun.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ReifiedTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ReifiedTestGenerated.java index d6cd616a828..6eba0e01c1f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ReifiedTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ReifiedTestGenerated.java @@ -41,6 +41,12 @@ public class ReifiedTestGenerated extends AbstractReifiedTest { doTest(fileName); } + @TestMetadata("extensionFun.kt") + public void testExtensionFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/reified/cases/extensionFun.kt"); + doTest(fileName); + } + @TestMetadata("extensionLambda.kt") public void testExtensionLambda() throws Exception { String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/reified/cases/extensionLambda.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt index b9561a3d31a..fa6e9b5e0d8 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt @@ -36,17 +36,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.expressions.OperatorConventions import java.util.ArrayList -public fun addReceiverToArgs(receiver: JsExpression, arguments: List): List { - if (arguments.isEmpty()) - return SmartList(receiver) - - val argumentList = ArrayList(1 + arguments.size()) - argumentList.add(receiver) - argumentList.addAll(arguments) - return argumentList +public fun CallArgumentTranslator.ArgumentsInfo.argsWithReceiver(receiver: JsExpression): List { + val allArguments = ArrayList(1 + reifiedArguments.size() + valueArguments.size()) + allArguments.addAll(reifiedArguments) + allArguments.add(receiver) + allArguments.addAll(valueArguments) + return allArguments } - // call may be native and|or with spreadOperator object DefaultFunctionCallCase : FunctionCallCase { // TODO: refactor after fix ArgumentsInfo - duplicate code @@ -118,13 +115,13 @@ object DefaultFunctionCallCase : FunctionCallCase { functionRef } - return JsInvocation(referenceToCall, addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments)) + return JsInvocation(referenceToCall, argumentsInfo.argsWithReceiver(extensionReceiver!!)) } override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native val functionRef = JsNameRef(functionName, dispatchReceiver!!) - return JsInvocation(functionRef, addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments)) + return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!)) } } @@ -200,7 +197,7 @@ object InvokeIntrinsic : FunctionCallCase { * extLambda.call(obj, some, args) */ override fun FunctionCallInfo.bothReceivers(): JsExpression { - return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments)) + return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), argumentsInfo.argsWithReceiver(extensionReceiver!!)) } } @@ -227,7 +224,7 @@ object SuperCallCase : FunctionCallCase { // TODO: spread operator val prototypeClass = JsNameRef(Namer.getPrototypeName(), dispatchReceiver!!) val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass)) - return JsInvocation(functionRef, addReceiverToArgs(JsLiteral.THIS, argumentsInfo.translateArguments)) + return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(JsLiteral.THIS)) } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt index 4e9e60368d2..8afd3e80aee 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallArgumentTranslator.kt @@ -45,10 +45,14 @@ public class CallArgumentTranslator private ( ) : AbstractTranslator(context) { public data class ArgumentsInfo( - public val translateArguments: List, + public val valueArguments: List, public val hasSpreadOperator: Boolean, - public val cachedReceiver: TemporaryConstVariable? - ) + public val cachedReceiver: TemporaryConstVariable?, + public val reifiedArguments: List = listOf() + ) { + public val translateArguments: List + get() = reifiedArguments + valueArguments + } private enum class ArgumentsKind { HAS_EMPTY_EXPRESSION_ARGUMENT @@ -349,5 +353,5 @@ private fun Map.addReifiedTypeArgsTo( reifiedTypeArguments.add(isCheckCallable) } - return info.copy(translateArguments = reifiedTypeArguments + info.translateArguments) + return info.copy(reifiedArguments = reifiedTypeArguments) } diff --git a/js/js.translator/testData/reified/cases/extensionFun.kt b/js/js.translator/testData/reified/cases/extensionFun.kt new file mode 100644 index 00000000000..473d2af3893 --- /dev/null +++ b/js/js.translator/testData/reified/cases/extensionFun.kt @@ -0,0 +1,17 @@ +package foo + +// CHECK_NOT_CALLED: canBeCastedTo + +open class A +class B +class C : A() + +inline fun Any.canBeCastedTo(): Boolean = this is T + +fun box(): String { + assertEquals(true, A().canBeCastedTo(), "A().canBeCastedTo()") + assertEquals(false, A().canBeCastedTo(), "A().canBeCastedTo()") + assertEquals(true, C().canBeCastedTo(), "C().canBeCastedTo()") + + return "OK" +} \ No newline at end of file