From 289efb89842db07c2e8214de05ebe210991f71b3 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Mon, 8 Jun 2015 19:36:08 +0300 Subject: [PATCH] JS backend: don't fail when invoke call got extension receiver implicitly #EA-67456 Fixed --- .../test/semantics/InvokeConventionTest.java | 4 ++++ .../translate/callTranslator/CallTranslator.kt | 12 ++++++++---- ...icitDispatchReceiverAndExtensionReceiver.kt | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 js/js.translator/testData/expression/invoke/cases/invokeWithImplicitDispatchReceiverAndExtensionReceiver.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InvokeConventionTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InvokeConventionTest.java index 756f205e142..1fc30e34685 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InvokeConventionTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InvokeConventionTest.java @@ -61,4 +61,8 @@ public final class InvokeConventionTest extends AbstractExpressionTest { public void testInheritFromFunctionTraits() throws Exception { checkFooBoxIsOk(); } + + public void testInvokeWithImplicitDispatchReceiverAndExtensionReceiver() throws Exception { + checkFooBoxIsOk(); + } } 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 6a3b52414ab..488903971a1 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 @@ -28,11 +28,11 @@ import org.jetbrains.kotlin.psi.Call.CallType import org.jetbrains.kotlin.resolve.calls.CallResolverUtil import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall +import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.NO_EXPLICIT_RECEIVER import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import kotlin.platform.platformStatic -import kotlin.test.assertNotNull object CallTranslator { jvmOverloads @@ -131,12 +131,16 @@ fun computeExplicitReceiversForInvoke( val dispatchReceiver = resolvedCall.getDispatchReceiver() val extensionReceiver = resolvedCall.getExtensionReceiver() - if (dispatchReceiver.exists() && extensionReceiver.exists()) { - assertNotNull(explicitReceivers.extensionOrDispatchReceiver, "No explicit receiver for 'invoke' resolved call with both receivers: $callElement") + if (dispatchReceiver.exists() && extensionReceiver.exists() && resolvedCall.getExplicitReceiverKind() == ExplicitReceiverKind.BOTH_RECEIVERS) { + assert(explicitReceivers.extensionOrDispatchReceiver != null) { + "No explicit receiver for 'invoke' resolved call with both receivers: $callElement, text: ${callElement.getText()}" + + "Dispatch receiver: $dispatchReceiver Extension receiver: $extensionReceiver" + } } else { assert(explicitReceivers.extensionOrDispatchReceiver == null) { - "Non trivial explicit receiver ${explicitReceivers.extensionOrDispatchReceiver}\n for 'invoke' resolved call: $callElement\n" + + "Non trivial explicit receiver ${explicitReceivers.extensionOrDispatchReceiver}\n" + + "for 'invoke' resolved call: $callElement, text: ${callElement.getText()}\n" + "Dispatch receiver: $dispatchReceiver Extension receiver: $extensionReceiver" } } diff --git a/js/js.translator/testData/expression/invoke/cases/invokeWithImplicitDispatchReceiverAndExtensionReceiver.kt b/js/js.translator/testData/expression/invoke/cases/invokeWithImplicitDispatchReceiverAndExtensionReceiver.kt new file mode 100644 index 00000000000..d0f0c2b23ba --- /dev/null +++ b/js/js.translator/testData/expression/invoke/cases/invokeWithImplicitDispatchReceiverAndExtensionReceiver.kt @@ -0,0 +1,18 @@ +package foo + +fun A.f(s: String) = value + s + +class A(val value: String) { + fun bar(s: String) = (::f)(s) +} + +fun A.baz(s: String) = (::f)(s) + +fun box(): String { + val a = A("aaa") + + assertEquals("aaa.bar()", a.bar(".bar()")) + assertEquals("aaa.baz()", a.baz(".baz()")) + + return "OK" +}