JS: support non-local return from secondary constructor
See KT-14549
This commit is contained in:
@@ -1,6 +1,3 @@
|
|||||||
// TODO enable for JS backend too when KT-14549 will be fixed
|
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
|
|
||||||
inline fun run(block: () -> Unit) = block()
|
inline fun run(block: () -> Unit) = block()
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ var JsNameRef.psiElement: PsiElement? by MetadataProperty(default = null)
|
|||||||
|
|
||||||
var JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
var JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
||||||
|
|
||||||
|
var JsFunction.forcedReturnVariable: JsName? by MetadataProperty(default = null)
|
||||||
|
|
||||||
var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false)
|
var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false)
|
||||||
|
|
||||||
var JsInvocation.typeCheck: TypeCheck? by MetadataProperty(default = null)
|
var JsInvocation.typeCheck: TypeCheck? by MetadataProperty(default = null)
|
||||||
|
|||||||
@@ -361,6 +361,22 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
// body of inline function can contain call to lambdas that need to be inlined
|
// body of inline function can contain call to lambdas that need to be inlined
|
||||||
JsStatement inlineableBodyWithLambdasInlined = accept(inlineableBody);
|
JsStatement inlineableBodyWithLambdasInlined = accept(inlineableBody);
|
||||||
assert inlineableBody == inlineableBodyWithLambdasInlined;
|
assert inlineableBody == inlineableBodyWithLambdasInlined;
|
||||||
|
|
||||||
|
// Support non-local return from secondary constructor
|
||||||
|
// Returns from secondary constructors should return `$this` object.
|
||||||
|
JsFunction currentFunction = getCurrentNamedFunction();
|
||||||
|
if (currentFunction != null) {
|
||||||
|
JsName returnVariable = MetadataProperties.getForcedReturnVariable(currentFunction);
|
||||||
|
if (returnVariable != null) {
|
||||||
|
inlineableBody.accept(new RecursiveJsVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitReturn(@NotNull JsReturn x) {
|
||||||
|
x.setExpression(returnVariable.makeRef());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
statementContext.addPrevious(flattenStatement(inlineableBody));
|
statementContext.addPrevious(flattenStatement(inlineableBody));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+1
-7
@@ -21884,13 +21884,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
@TestMetadata("withNonLocalReturn.kt")
|
@TestMetadata("withNonLocalReturn.kt")
|
||||||
public void testWithNonLocalReturn() throws Exception {
|
public void testWithNonLocalReturn() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt");
|
||||||
try {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("withReturn.kt")
|
@TestMetadata("withReturn.kt")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.metadata.forcedReturnVariable
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
||||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.context.*
|
import org.jetbrains.kotlin.js.translate.context.*
|
||||||
@@ -281,6 +282,7 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructorInitializer.parameters += JsParameter(thisName)
|
constructorInitializer.parameters += JsParameter(thisName)
|
||||||
|
constructorInitializer.forcedReturnVariable = thisName
|
||||||
|
|
||||||
// Generate super/this call to insert to beginning of the function
|
// Generate super/this call to insert to beginning of the function
|
||||||
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(context.bindingContext(), constructorDescriptor)
|
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(context.bindingContext(), constructorDescriptor)
|
||||||
|
|||||||
Reference in New Issue
Block a user