JS: support callable references on suspend functions (KT-30987 fixed)

This commit is contained in:
Anton Bannykh
2019-04-16 18:09:17 +03:00
parent aff8a3f97f
commit 052ddd60ce
12 changed files with 97 additions and 14 deletions
@@ -44,17 +44,14 @@ class CoroutineTransformer : JsVisitorWithContextImpl() {
return super.visit(x, ctx)
}
override fun visit(x: JsFunction, ctx: JsContext<*>): Boolean {
override fun endVisit(x: JsFunction, ctx: JsContext<*>) {
if (x.isInlineableCoroutineBody) {
x.body = transformCoroutineMetadataToSpecialFunctions(x.body)
return false
}
if (x.coroutineMetadata != null) {
lastStatementLevelContext.addPrevious(CoroutineFunctionTransformer(x, functionName[x]).transform())
x.coroutineMetadata = null
return false
}
return super.visit(x, ctx)
}
override fun visit(x: JsVars.JsVar, ctx: JsContext<*>): Boolean {
@@ -5072,6 +5072,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
}
@TestMetadata("simpleSuspendCallableReference.kt")
public void testSimpleSuspendCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
}
@TestMetadata("simpleWithHandleResult.kt")
public void testSimpleWithHandleResult_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines");
@@ -5397,6 +5397,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
}
@TestMetadata("simpleSuspendCallableReference.kt")
public void testSimpleSuspendCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
}
@TestMetadata("simpleWithHandleResult.kt")
public void testSimpleWithHandleResult_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
@@ -540,9 +540,11 @@ public class TranslationContext {
@Nullable
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
JsExpression nameRef = captureIfNeedAndGetCapturedName(descriptor);
if (nameRef != null) {
return nameRef;
if (continuationParameterDescriptor != descriptor) {
JsExpression nameRef = captureIfNeedAndGetCapturedName(descriptor);
if (nameRef != null) {
return nameRef;
}
}
JsExpression alias = aliasingContext.getAliasForDescriptor(descriptor);
@@ -24,9 +24,7 @@ import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.js.translate.utils.finalElement
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getFunctionResolvedCallWithAssert
@@ -127,7 +125,18 @@ object CallableReferenceTranslator {
val type = functionDescriptor.valueParameters[index].type
aliases[valueArg.getArgumentExpression()!!] = TranslationUtils.coerce(context, paramRef, type)
}
val functionContext = context.innerBlock(function.body).innerContextWithAliasesForExpressions(aliases)
var functionContext = context.innerBlock(function.body).innerContextWithAliasesForExpressions(aliases).inner(functionDescriptor)
functionContext.continuationParameterDescriptor?.let { continuationDescriptor ->
function.parameters += JsParameter(context.getNameForDescriptor(continuationDescriptor))
functionContext = functionContext.innerContextWithDescriptorsAliased(mapOf(continuationDescriptor to JsAstUtils.stateMachineReceiver()))
}
if (functionDescriptor.isSuspend) {
function.fillCoroutineMetadata(functionContext, descriptor, hasController = false)
}
val invocation = CallTranslator.translate(functionContext, fakeResolvedCall, receiverParam)
function.body.statements += JsReturn(TranslationUtils.coerce(context, invocation, context.currentModule.builtIns.anyType))