JS: make kotlin.Throwable = Error. See KT-15312
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
fun box(): String {
|
||||
var t = Throwable("O", Throwable("K"))
|
||||
if (t.message != "O" || t.cause?.message != "K") return "fail1"
|
||||
|
||||
t = Throwable(Throwable("OK"))
|
||||
if (t.message != null || t.cause?.message != "OK") return "fail2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public final class ThrowableCauseKt {
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+6
@@ -16223,6 +16223,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableCause.kt")
|
||||
public void testThrowableCause() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableCause.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImpl.kt")
|
||||
public void testThrowableImpl() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt");
|
||||
|
||||
@@ -16223,6 +16223,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableCause.kt")
|
||||
public void testThrowableCause() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableCause.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImpl.kt")
|
||||
public void testThrowableImpl() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt");
|
||||
|
||||
@@ -16223,6 +16223,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableCause.kt")
|
||||
public void testThrowableCause() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableCause.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImpl.kt")
|
||||
public void testThrowableImpl() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt");
|
||||
|
||||
@@ -601,6 +601,19 @@ public class DescriptorUtils {
|
||||
throw new IllegalStateException("Function not found");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PropertyDescriptor getPropertyByName(@NotNull MemberScope scope, @NotNull Name name) {
|
||||
Collection<DeclarationDescriptor> callables = scope.getContributedDescriptors(
|
||||
DescriptorKindFilter.CALLABLES, MemberScope.Companion.getALL_NAME_FILTER());
|
||||
for (DeclarationDescriptor d : callables) {
|
||||
if (d instanceof PropertyDescriptor && name.equals(d.getOriginal().getName())) {
|
||||
return (PropertyDescriptor) d;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Property not found");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CallableMemberDescriptor getDirectMember(@NotNull CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof PropertyAccessorDescriptor
|
||||
|
||||
@@ -25,10 +25,10 @@ public abstract class JsExpression extends SourceInfoAwareJsNode {
|
||||
return new JsExpressionStatement(this);
|
||||
}
|
||||
|
||||
protected abstract static class JsExpressionHasArguments extends JsExpression implements HasArguments {
|
||||
public abstract static class JsExpressionHasArguments extends JsExpression implements HasArguments {
|
||||
protected final List<JsExpression> arguments;
|
||||
|
||||
public JsExpressionHasArguments(List<JsExpression> arguments) {
|
||||
protected JsExpressionHasArguments(List<JsExpression> arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.js.internal.JsError
|
||||
|
||||
/**
|
||||
* The base class for all errors and exceptions. Only instances of this class can be thrown or caught.
|
||||
*
|
||||
* @param message the detail message string.
|
||||
* @param cause the cause of this throwable.
|
||||
*/
|
||||
public open class Throwable(open val message: String?, open val cause: Throwable?) : JsError(message) {
|
||||
constructor(message: String?) : this(message, null)
|
||||
|
||||
constructor(cause: Throwable?) : this(cause?.toString(), cause)
|
||||
|
||||
constructor() : this(null, null)
|
||||
|
||||
init {
|
||||
var e = JsError(message)
|
||||
copyOwnProperties(e, this)
|
||||
val t: dynamic = this
|
||||
t.name = t.constructor.name
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyOwnProperties(from: dynamic, to: dynamic) {
|
||||
val names: Array<String> = js("Object").getOwnPropertyNames(from);
|
||||
for (name in names) {
|
||||
to[name] = from[name];
|
||||
}
|
||||
}
|
||||
@@ -46,4 +46,22 @@ fun subSequence(c: CharSequence, startIndex: Int, endIndex: Int): CharSequence {
|
||||
else {
|
||||
return c.asDynamic().`subSequence_vux9f0$`(startIndex, endIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("captureStack")
|
||||
internal fun captureStack(baseClass: JsClass<in Throwable>, instance: Throwable) {
|
||||
if (js("Error").captureStackTrace) {
|
||||
js("Error").captureStackTrace(instance, instance::class.js);
|
||||
}
|
||||
else {
|
||||
instance.asDynamic().stack = js("new Error()").stack;
|
||||
}
|
||||
}
|
||||
|
||||
@JsName("newThrowable")
|
||||
internal fun newThrowable(message: String?, cause: Throwable?): Throwable {
|
||||
val throwable = js("new Error()")
|
||||
throwable.message = message
|
||||
throwable.cause = cause
|
||||
return throwable
|
||||
}
|
||||
@@ -20487,6 +20487,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableCause.kt")
|
||||
public void testThrowableCause() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableCause.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwableImpl.kt")
|
||||
public void testThrowableImpl() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt");
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -248,6 +249,9 @@ public final class StaticContext {
|
||||
if (KotlinBuiltIns.isAny(classDescriptor)) {
|
||||
return pureFqn("Object", null);
|
||||
}
|
||||
else if (TypeUtilsKt.isThrowable(classDescriptor.getDefaultType())) {
|
||||
return pureFqn("Error", null);
|
||||
}
|
||||
}
|
||||
|
||||
SuggestedName suggested = nameSuggestion.suggest(descriptor);
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters
|
||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
||||
@@ -87,6 +88,7 @@ class ClassTranslator private constructor(
|
||||
translatePropertiesAsConstructorParameters(nonConstructorContext)
|
||||
val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext, enumInitFunction)
|
||||
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
||||
mayBeAddThrowableProperties(context)
|
||||
constructorFunction.body.statements += bodyVisitor.initializerStatements
|
||||
delegationTranslator.generateDelegated()
|
||||
|
||||
@@ -455,6 +457,23 @@ class ClassTranslator private constructor(
|
||||
EnumTranslator(context(), descriptor, entries).generateStandardMethods()
|
||||
}
|
||||
|
||||
private fun mayBeAddThrowableProperties(context: TranslationContext) {
|
||||
if (!TranslationUtils.isImmediateSubtypeOfError(descriptor)) return
|
||||
|
||||
val properties = listOf("message", "cause")
|
||||
.map { Name.identifier(it) }
|
||||
.map { DescriptorUtils.getPropertyByName(descriptor.unsubstitutedMemberScope, it) }
|
||||
.filter { !it.kind.isReal }
|
||||
for (property in properties) {
|
||||
val propertyTranslator = DefaultPropertyTranslator(property, context, JsLiteral.NULL)
|
||||
val literal = JsObjectLiteral(true)
|
||||
val getterFunction = context.getFunctionObject(property.getter!!)
|
||||
propertyTranslator.generateDefaultGetterFunction(property.getter!!, getterFunction)
|
||||
literal.propertyInitializers += JsPropertyInitializer(context.program().getStringLiteral("get"), getterFunction)
|
||||
context.addAccessorsToPrototype(descriptor, property, literal)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generatedBridgeMethods() {
|
||||
if (isAnnotation()) return
|
||||
|
||||
|
||||
+79
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.translate.initializer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
@@ -26,21 +27,28 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.context.UsageTracker;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.DelegationTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtParameter;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -63,6 +71,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private final ClassDescriptor classDescriptor;
|
||||
|
||||
private final ConstructorDescriptor primaryConstructor;
|
||||
|
||||
private int ordinal;
|
||||
|
||||
public ClassInitializerTranslator(
|
||||
@@ -75,6 +85,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
this.initFunction = initFunction;
|
||||
this.context = context.contextWithScope(initFunction);
|
||||
classDescriptor = BindingUtils.getClassDescriptor(bindingContext(), classDeclaration);
|
||||
primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
}
|
||||
|
||||
public void setOrdinal(int ordinal) {
|
||||
@@ -89,7 +100,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
|
||||
public void generateInitializeMethod(DelegationTranslator delegationTranslator) {
|
||||
addOuterClassReference(classDescriptor);
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
|
||||
if (primaryConstructor != null) {
|
||||
initFunction.getBody().getStatements().addAll(setDefaultValueForArguments(primaryConstructor, context()));
|
||||
@@ -106,6 +116,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
addThrowableCall();
|
||||
|
||||
delegationTranslator.addInitCode(initFunction.getBody().getStatements());
|
||||
new InitializerVisitor().traverseContainer(classDeclaration, context().innerBlock(initFunction.getBody()));
|
||||
}
|
||||
@@ -168,6 +180,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
}
|
||||
else if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
||||
|
||||
if (superCall == null) {
|
||||
if (DescriptorUtils.isEnumEntry(classDescriptor)) {
|
||||
addCallToSuperMethod(getAdditionalArgumentsForEnumConstructor(), initializer);
|
||||
@@ -175,6 +188,11 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
|
||||
emulateSuperCallToNativeError(superCall);
|
||||
return;
|
||||
}
|
||||
|
||||
if (classDeclaration instanceof KtEnumEntry) {
|
||||
JsExpression expression = CallTranslator.translate(context(), superCall, null);
|
||||
|
||||
@@ -239,6 +257,49 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
private void emulateSuperCallToNativeError(@NotNull ResolvedCall<FunctionDescriptor> superCall) {
|
||||
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 messageArgument = JsLiteral.NULL;
|
||||
JsExpression causeArgument = JsLiteral.NULL;
|
||||
for (ValueParameterDescriptor param : superCall.getResultingDescriptor().getValueParameters()) {
|
||||
ResolvedValueArgument argument = superCall.getValueArguments().get(param);
|
||||
if (!(argument instanceof ExpressionValueArgument)) continue;
|
||||
|
||||
ExpressionValueArgument exprArgument = (ExpressionValueArgument) argument;
|
||||
assert exprArgument.getValueArgument() != null;
|
||||
|
||||
KtExpression value = exprArgument.getValueArgument().getArgumentExpression();
|
||||
assert value != null;
|
||||
JsExpression jsValue = Translation.translateAsExpression(value, context);
|
||||
|
||||
if (KotlinBuiltIns.isStringOrNullableString(param.getType())) {
|
||||
messageArgument = jsValue;
|
||||
}
|
||||
else if (TypeUtilsKt.isConstructedFromClassWithGivenFqName(param.getType(), KotlinBuiltIns.FQ_NAMES.throwable)) {
|
||||
causeArgument = jsValue;
|
||||
}
|
||||
else {
|
||||
initFunction.getBody().getStatements().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)));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<JsExpression> getAdditionalArgumentsForEnumConstructor() {
|
||||
List<JsExpression> additionalArguments = new ArrayList<JsExpression>();
|
||||
@@ -302,4 +363,21 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
initFunction.getBody().getStatements().add(
|
||||
InitializerUtils.generateInitializerForProperty(context(), propertyDescriptor, initialValue));
|
||||
}
|
||||
|
||||
private void addThrowableCall() {
|
||||
if (!TranslationUtils.isExceptionClass(classDescriptor)) return;
|
||||
|
||||
if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) {
|
||||
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor);
|
||||
JsExpression invocation = new JsInvocation(
|
||||
pureFqn("captureStack", Namer.kotlinObject()),
|
||||
ReferenceTranslator.translateAsTypeReference(superClass, context()),
|
||||
JsLiteral.THIS);
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(invocation));
|
||||
}
|
||||
|
||||
JsExpression nameLiteral = context.program().getStringLiteral(context.getInnerNameForDescriptor(classDescriptor).getIdent());
|
||||
JsExpression nameAssignment = JsAstUtils.assignment(pureFqn("name", JsLiteral.THIS), nameLiteral);
|
||||
initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(nameAssignment));
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -46,6 +46,8 @@ public final class FunctionIntrinsics {
|
||||
register(ArrayFIF.INSTANCE);
|
||||
register(TopLevelFIF.INSTANCE);
|
||||
register(NumberAndCharConversionFIF.INSTANCE);
|
||||
register(ThrowableConstructorIntrinsicFactory.INSTANCE);
|
||||
register(ExceptionPropertyIntrinsicFactory.INSTANCE);
|
||||
}
|
||||
|
||||
private void register(@NotNull FunctionIntrinsicFactory instance) {
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.SuperCallReceiverValue
|
||||
import org.jetbrains.kotlin.types.typeUtil.isThrowable
|
||||
|
||||
object ExceptionPropertyIntrinsicFactory : FunctionIntrinsicFactory {
|
||||
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
|
||||
if (descriptor !is PropertyGetterDescriptor) return null
|
||||
val classDescriptor = descriptor.correspondingProperty.containingDeclaration as? ClassDescriptor ?: return null
|
||||
if (!classDescriptor.defaultType.isThrowable()) return null
|
||||
|
||||
return Intrinsic
|
||||
}
|
||||
|
||||
object Intrinsic : FunctionIntrinsic() {
|
||||
override fun apply(callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
|
||||
val property = callInfo.resolvedCall.resultingDescriptor as PropertyDescriptor
|
||||
if (callInfo.resolvedCall.call.explicitReceiver !is SuperCallReceiverValue) {
|
||||
val name = context.getNameForDescriptor(property)
|
||||
return JsNameRef(name, callInfo.dispatchReceiver!!)
|
||||
}
|
||||
|
||||
val currentClassProperty = context.classDescriptor!!.unsubstitutedMemberScope
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.first { it.overriddenDescriptors.any { it == property } }
|
||||
val fieldRef = JsAstUtils.pureFqn(context.getNameForBackingField(currentClassProperty), callInfo.dispatchReceiver!!)
|
||||
return fieldRef
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsInvocation
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsLiteral
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.typeUtil.isThrowable
|
||||
|
||||
object ThrowableConstructorIntrinsicFactory : FunctionIntrinsicFactory {
|
||||
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
|
||||
if (descriptor !is ConstructorDescriptor) return null
|
||||
if (!descriptor.constructedClass.defaultType.isThrowable()) return null
|
||||
|
||||
return Intrinsic
|
||||
}
|
||||
|
||||
object Intrinsic : FunctionIntrinsic() {
|
||||
override fun apply(callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
|
||||
val constructor = callInfo.resolvedCall.resultingDescriptor
|
||||
val argumentsToPass = arguments.toMutableList()
|
||||
val hasCauseParameter = constructor.valueParameters.any {
|
||||
it.type.constructor.declarationDescriptor?.fqNameSafe == KotlinBuiltIns.FQ_NAMES.throwable
|
||||
}
|
||||
|
||||
if (constructor.valueParameters.size == 1 && hasCauseParameter) {
|
||||
argumentsToPass.add(0, JsLiteral.NULL)
|
||||
}
|
||||
|
||||
return JsInvocation(JsAstUtils.pureFqn("newThrowable", Namer.kotlinObject()), argumentsToPass)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.FindClassInModuleKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -399,4 +400,15 @@ public final class TranslationUtils {
|
||||
ModalityKt.isOverridable(descriptor);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isImmediateSubtypeOfError(@NotNull ClassDescriptor descriptor) {
|
||||
if (!isExceptionClass(descriptor)) return false;
|
||||
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(descriptor);
|
||||
return TypeUtilsKt.isThrowable(superClass.getDefaultType()) || AnnotationsUtils.isNativeObject(superClass);
|
||||
}
|
||||
|
||||
public static boolean isExceptionClass(@NotNull ClassDescriptor descriptor) {
|
||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||
return TypeUtilsKt.isSubtypeOf(descriptor.getDefaultType(), module.getBuiltIns().getThrowable().getDefaultType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ fun check(e: Throwable, expectedString: String) {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
check(Throwable(), "Throwable: null")
|
||||
check(Throwable("ccc"), "Throwable: ccc")
|
||||
check(Exception(), "Exception: null")
|
||||
check(Exception("bbb"), "Exception: bbb")
|
||||
check(MyException(), "MyException: null")
|
||||
|
||||
Reference in New Issue
Block a user