JS: add support of custom exceptions inherited from kotlin.Throwable that call super constructor from secondary constructor
This commit is contained in:
@@ -17,5 +17,5 @@ fun box(): String {
|
||||
return "OK"
|
||||
}
|
||||
|
||||
return "fail: MyThrowable wasn't catched."
|
||||
return "fail: MyThrowable wasn't caught."
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
class MyThrowable : Throwable {
|
||||
val x: String
|
||||
|
||||
constructor(x: String, message: String, cause: Throwable? = null) : super(x + message, cause) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
throw MyThrowable("O", "K")
|
||||
}
|
||||
catch (t: MyThrowable) {
|
||||
if (t.cause != null) return "fail t.cause"
|
||||
if (t.message != "OK") return "fail t.message: ${t.message}"
|
||||
if (t.x != "O") return "fail t.x: ${t.x}"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
return "fail: MyThrowable wasn't caught."
|
||||
}
|
||||
+6
@@ -16235,6 +16235,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImplWithSecondaryConstructor.kt")
|
||||
public void testThrowableImplWithSecondaryConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesInsideEnum.kt")
|
||||
public void testValuesInsideEnum() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
|
||||
|
||||
@@ -16235,6 +16235,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImplWithSecondaryConstructor.kt")
|
||||
public void testThrowableImplWithSecondaryConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesInsideEnum.kt")
|
||||
public void testValuesInsideEnum() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
|
||||
|
||||
@@ -16235,6 +16235,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImplWithSecondaryConstructor.kt")
|
||||
public void testThrowableImplWithSecondaryConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesInsideEnum.kt")
|
||||
public void testValuesInsideEnum() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
|
||||
|
||||
@@ -20499,6 +20499,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImplWithSecondaryConstructor.kt")
|
||||
public void testThrowableImplWithSecondaryConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesInsideEnum.kt")
|
||||
public void testValuesInsideEnum() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
|
||||
|
||||
+17
-7
@@ -252,13 +252,23 @@ class ClassTranslator private constructor(
|
||||
val delegationClassDescriptor = (resolvedCall?.resultingDescriptor as? ClassConstructorDescriptor)?.constructedClass
|
||||
|
||||
if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
|
||||
superCallGenerators += {
|
||||
val delegationConstructor = resolvedCall.resultingDescriptor
|
||||
val innerContext = context.innerBlock()
|
||||
val statement = CallTranslator.translate(innerContext, resolvedCall)
|
||||
.toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt()
|
||||
it += innerContext.currentBlock.statements
|
||||
it += statement
|
||||
if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
|
||||
superCallGenerators += {
|
||||
val innerContext = context().innerBlock()
|
||||
ClassInitializerTranslator.emulateSuperCallToNativeError(
|
||||
innerContext, classDescriptor, resolvedCall, thisNameRef.deepCopy())
|
||||
it += innerContext.currentBlock.statements
|
||||
}
|
||||
}
|
||||
else {
|
||||
superCallGenerators += {
|
||||
val delegationConstructor = resolvedCall.resultingDescriptor
|
||||
val innerContext = context.innerBlock()
|
||||
val statement = CallTranslator.translate(innerContext, resolvedCall)
|
||||
.toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt()
|
||||
it += innerContext.currentBlock.statements
|
||||
it += statement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-11
@@ -189,7 +189,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
|
||||
emulateSuperCallToNativeError(superCall);
|
||||
emulateSuperCallToNativeError(context, classDescriptor, superCall, JsLiteral.THIS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,11 +257,17 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
private void emulateSuperCallToNativeError(@NotNull ResolvedCall<FunctionDescriptor> superCall) {
|
||||
public static void emulateSuperCallToNativeError(
|
||||
@NotNull TranslationContext context,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull ResolvedCall<? extends FunctionDescriptor> superCall,
|
||||
@NotNull JsExpression receiver
|
||||
) {
|
||||
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor);
|
||||
JsExpression superClassRef = ReferenceTranslator.translateAsTypeReference(superClass, context);
|
||||
JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), JsLiteral.THIS);
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(superInvocation));
|
||||
JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), receiver.deepCopy());
|
||||
List<JsStatement> statements = context.getCurrentBlock().getStatements();
|
||||
statements.add(JsAstUtils.asSyntheticStatement(superInvocation));
|
||||
|
||||
JsExpression messageArgument = JsLiteral.NULL;
|
||||
JsExpression causeArgument = JsLiteral.NULL;
|
||||
@@ -283,21 +289,19 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
causeArgument = jsValue;
|
||||
}
|
||||
else {
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(jsValue));
|
||||
statements.add(JsAstUtils.asSyntheticStatement(jsValue));
|
||||
}
|
||||
}
|
||||
|
||||
PropertyDescriptor messageProperty = DescriptorUtils.getPropertyByName(
|
||||
classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("message"));
|
||||
JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), JsLiteral.THIS);
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(
|
||||
JsAstUtils.assignment(messageRef, messageArgument)));
|
||||
JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), receiver.deepCopy());
|
||||
statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(messageRef, messageArgument)));
|
||||
|
||||
PropertyDescriptor causeProperty = DescriptorUtils.getPropertyByName(
|
||||
classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("cause"));
|
||||
JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), JsLiteral.THIS);
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(
|
||||
JsAstUtils.assignment(causeRef, causeArgument)));
|
||||
JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), receiver.deepCopy());
|
||||
statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(causeRef, causeArgument)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user