JS: add support of custom exceptions inherited from kotlin.Throwable that call super constructor from secondary constructor

This commit is contained in:
Alexey Andreev
2016-12-29 14:51:47 +03:00
parent f34093db9f
commit 6f4d8decc7
8 changed files with 78 additions and 19 deletions
@@ -17,5 +17,5 @@ fun box(): String {
return "OK" return "OK"
} }
return "fail: MyThrowable wasn't catched." return "fail: MyThrowable wasn't caught."
} }
@@ -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."
}
@@ -16235,6 +16235,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName); 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") @TestMetadata("valuesInsideEnum.kt")
public void testValuesInsideEnum() throws Exception { public void testValuesInsideEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
@@ -16235,6 +16235,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName); 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") @TestMetadata("valuesInsideEnum.kt")
public void testValuesInsideEnum() throws Exception { public void testValuesInsideEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
@@ -16235,6 +16235,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
doTest(fileName); 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") @TestMetadata("valuesInsideEnum.kt")
public void testValuesInsideEnum() throws Exception { public void testValuesInsideEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
@@ -20499,6 +20499,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName); 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") @TestMetadata("valuesInsideEnum.kt")
public void testValuesInsideEnum() throws Exception { public void testValuesInsideEnum() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt");
@@ -252,13 +252,23 @@ class ClassTranslator private constructor(
val delegationClassDescriptor = (resolvedCall?.resultingDescriptor as? ClassConstructorDescriptor)?.constructedClass val delegationClassDescriptor = (resolvedCall?.resultingDescriptor as? ClassConstructorDescriptor)?.constructedClass
if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) { if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
superCallGenerators += { if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
val delegationConstructor = resolvedCall.resultingDescriptor superCallGenerators += {
val innerContext = context.innerBlock() val innerContext = context().innerBlock()
val statement = CallTranslator.translate(innerContext, resolvedCall) ClassInitializerTranslator.emulateSuperCallToNativeError(
.toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt() innerContext, classDescriptor, resolvedCall, thisNameRef.deepCopy())
it += innerContext.currentBlock.statements it += innerContext.currentBlock.statements
it += statement }
}
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
}
} }
} }
@@ -189,7 +189,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
} }
if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) { if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
emulateSuperCallToNativeError(superCall); emulateSuperCallToNativeError(context, classDescriptor, superCall, JsLiteral.THIS);
return; 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); ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor);
JsExpression superClassRef = ReferenceTranslator.translateAsTypeReference(superClass, context); JsExpression superClassRef = ReferenceTranslator.translateAsTypeReference(superClass, context);
JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), JsLiteral.THIS); JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), receiver.deepCopy());
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(superInvocation)); List<JsStatement> statements = context.getCurrentBlock().getStatements();
statements.add(JsAstUtils.asSyntheticStatement(superInvocation));
JsExpression messageArgument = JsLiteral.NULL; JsExpression messageArgument = JsLiteral.NULL;
JsExpression causeArgument = JsLiteral.NULL; JsExpression causeArgument = JsLiteral.NULL;
@@ -283,21 +289,19 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
causeArgument = jsValue; causeArgument = jsValue;
} }
else { else {
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(jsValue)); statements.add(JsAstUtils.asSyntheticStatement(jsValue));
} }
} }
PropertyDescriptor messageProperty = DescriptorUtils.getPropertyByName( PropertyDescriptor messageProperty = DescriptorUtils.getPropertyByName(
classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("message")); classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("message"));
JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), JsLiteral.THIS); JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), receiver.deepCopy());
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement( statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(messageRef, messageArgument)));
JsAstUtils.assignment(messageRef, messageArgument)));
PropertyDescriptor causeProperty = DescriptorUtils.getPropertyByName( PropertyDescriptor causeProperty = DescriptorUtils.getPropertyByName(
classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("cause")); classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("cause"));
JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), JsLiteral.THIS); JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), receiver.deepCopy());
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement( statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(causeRef, causeArgument)));
JsAstUtils.assignment(causeRef, causeArgument)));
} }
@NotNull @NotNull