JS: fix translation of suspend lambda when it's not passed to another function

This commit is contained in:
Alexey Andreev
2017-01-23 15:05:08 +03:00
parent 1a5e0e4b06
commit 8040d781b4
5 changed files with 21 additions and 51 deletions
@@ -1,6 +1,5 @@
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND: JS
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
@@ -5864,13 +5864,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
doTest(fileName);
}
@TestMetadata("manyParameters.kt")
@@ -446,13 +446,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@Override
@NotNull
public JsNode visitLambdaExpression(@NotNull KtLambdaExpression expression, @NotNull TranslationContext context) {
return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral(), null);
return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral());
}
@Override
@NotNull
public JsNode visitNamedFunction(@NotNull KtNamedFunction expression, @NotNull TranslationContext context) {
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, null);
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression);
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
JsNameRef nameRef = (JsNameRef) ReferenceTranslator.translateAsValueReference(descriptor, context);
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.js.translate.expression
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.js.backend.ast.*
@@ -38,13 +37,9 @@ import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.types.KotlinType
class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) {
fun translate(
declaration: KtDeclarationWithBody,
continuationType: KotlinType? = null
): JsExpression {
fun translate(declaration: KtDeclarationWithBody): JsExpression {
val invokingContext = context()
val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration)
@@ -80,7 +75,7 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
lambda.name = tracker.getNameForCapturedDescriptor(descriptor)
}
lambdaCreator.name.staticRef = lambdaCreator
lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor, continuationType)
lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor)
return lambdaCreator.withCapturedParameters(descriptor, descriptor.wrapContextForCoroutineIfNecessary(functionContext),
invokingContext)
}
@@ -96,15 +91,15 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
lambda.isLocal = true
invokingContext.addDeclarationStatement(lambda.makeStmt())
lambda.fillCoroutineMetadata(invokingContext, descriptor, continuationType)
lambda.fillCoroutineMetadata(invokingContext, descriptor)
lambda.name.staticRef = lambda
return getReferenceToLambda(invokingContext, descriptor, lambda.name)
}
fun JsFunction.fillCoroutineMetadata(context: TranslationContext, descriptor: FunctionDescriptor, continuationType: KotlinType?) {
if (continuationType == null) return
fun JsFunction.fillCoroutineMetadata(context: TranslationContext, descriptor: FunctionDescriptor) {
if (!descriptor.isSuspend) return
fillCoroutineMetadata(context, descriptor, hasController = continuationType.isBuiltinExtensionFunctionalType, isLambda = true)
fillCoroutineMetadata(context, descriptor, hasController = descriptor.extensionReceiverParameter != null, isLambda = true)
}
fun ValueParameterDescriptorImpl.WithDestructuringDeclaration.translate(context: TranslationContext): JsVars {
@@ -16,24 +16,26 @@
package org.jetbrains.kotlin.js.translate.reference
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.LiteralFunctionTranslator
import org.jetbrains.kotlin.js.translate.expression.PatternTranslator
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
@@ -151,26 +153,11 @@ class CallArgumentTranslator private constructor(
context: TranslationContext,
resolvedCall: ResolvedCall<*>
): Map<ValueArgument, JsExpression> {
val argsToParameters = resolvedCall.valueArguments
.flatMap { (param, args) -> args.arguments.map { param to it } }
.associate { (param, arg) -> arg to param }
val argumentContexts = resolvedCall.call.valueArguments.associate { it to context.innerBlock() }
var result = resolvedCall.call.valueArguments.associate { arg ->
val argumentContext = argumentContexts[arg]!!
val argumentExpression = KtPsiUtil.deparenthesize(arg.getArgumentExpression())
val lambdaDescriptor = argumentExpression?.let { argumentContext.extractLambda(it) }
val jsExpr = if (lambdaDescriptor?.isSuspendLambda == true) {
val lambdaExpression = (argumentExpression as KtLambdaExpression).functionLiteral
val param = argsToParameters[arg]!!
LiteralFunctionTranslator(argumentContext).translate(lambdaExpression, param.type)
}
else {
Translation.translateAsExpression(arg.getArgumentExpression()!!, argumentContext)
}
val jsExpr = Translation.translateAsExpression(arg.getArgumentExpression()!!, argumentContext)
arg to jsExpr
}
@@ -225,11 +212,6 @@ class CallArgumentTranslator private constructor(
return resolvedArgument.arguments.map { translatedArgs[it]!! }
}
private fun TranslationContext.extractLambda(expression: KtExpression): CallableDescriptor? {
val lambdaExpression = expression as? KtLambdaExpression ?: return null
return BindingUtils.getFunctionDescriptor(bindingContext(), lambdaExpression.functionLiteral)
}
private fun translateVarargArgument(
resolvedArgument: ResolvedValueArgument,
translatedArgs: Map<ValueArgument, JsExpression>,