[KT-4124] Refactor super calls and fix calls to Any::equals
This commit is contained in:
@@ -65,4 +65,8 @@ public final class EqualsTest extends AbstractExpressionTest {
|
||||
public void testEqualsBehaviorOnNull() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
|
||||
public void testSuperEquals() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import com.google.dart.compiler.backend.js.ast.JsLiteral
|
||||
import com.google.dart.compiler.backend.js.ast.JsConditional
|
||||
import com.google.dart.compiler.backend.js.ast.JsBlock
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
|
||||
import com.google.dart.compiler.backend.js.ast.JsConditional
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||
import com.google.dart.compiler.backend.js.ast.JsLiteral
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
interface CallInfo {
|
||||
val context: TranslationContext
|
||||
@@ -61,33 +55,6 @@ class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null) :
|
||||
|
||||
class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : AbstractCallInfo(), CallInfo by callInfo
|
||||
|
||||
val CallInfo.superCallReceiver : JsExpression?
|
||||
get() {
|
||||
val receiver = this.resolvedCall.dispatchReceiver
|
||||
return when (receiver) {
|
||||
is ExpressionReceiver -> {
|
||||
val expr = receiver.expression
|
||||
when (expr) {
|
||||
is KtSuperExpression -> {
|
||||
val superDescriptor = context.getSuperTarget(expr);
|
||||
context.getDispatchReceiver(JsDescriptorUtils.getReceiverParameterForDeclaration(superDescriptor))
|
||||
}
|
||||
else -> {
|
||||
Translation.translateAsExpression(receiver.expression, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
is ThisClassReceiver -> {
|
||||
JsLiteral.THIS
|
||||
}
|
||||
is ExtensionReceiver -> {
|
||||
JsLiteral.THIS
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* no receivers - extensionOrDispatchReceiver = null, extensionReceiver = null
|
||||
@@ -101,10 +68,6 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescri
|
||||
return createCallInfo(resolvedCall, ExplicitReceivers(extensionOrDispatchReceiver))
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, extensionOrDispatchReceiver: JsExpression?): FunctionCallInfo {
|
||||
return getCallInfo(resolvedCall, ExplicitReceivers(extensionOrDispatchReceiver));
|
||||
}
|
||||
|
||||
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, explicitReceivers: ExplicitReceivers): FunctionCallInfo {
|
||||
val argsBlock = JsBlock()
|
||||
|
||||
+15
-10
@@ -16,18 +16,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import com.google.dart.compiler.backend.js.ast.JsName
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
|
||||
|
||||
val CallInfo.callableDescriptor: CallableDescriptor
|
||||
@@ -35,8 +36,6 @@ val CallInfo.callableDescriptor: CallableDescriptor
|
||||
|
||||
fun CallInfo.isExtension(): Boolean = extensionReceiver != null
|
||||
|
||||
fun CallInfo.isMemberCall(): Boolean = dispatchReceiver != null
|
||||
|
||||
fun CallInfo.isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||
|
||||
fun CallInfo.isSuperInvocation(): Boolean {
|
||||
@@ -44,6 +43,12 @@ fun CallInfo.isSuperInvocation(): Boolean {
|
||||
return dispatchReceiver is ExpressionReceiver && dispatchReceiver.expression is KtSuperExpression
|
||||
}
|
||||
|
||||
val CallInfo.calleeOwner: JsExpression
|
||||
get() {
|
||||
val calleeOwner = resolvedCall.resultingDescriptor.containingDeclaration
|
||||
return ReferenceTranslator.translateAsFQReference(calleeOwner, context)
|
||||
}
|
||||
|
||||
val VariableAccessInfo.variableDescriptor: VariableDescriptor
|
||||
get() = callableDescriptor as VariableDescriptor
|
||||
|
||||
|
||||
+6
-14
@@ -203,21 +203,14 @@ object ConstructorCallCase : FunctionCallCase() {
|
||||
return callInfo.callableDescriptor is ConstructorDescriptor
|
||||
}
|
||||
|
||||
override fun FunctionCallInfo.noReceivers(): JsExpression {
|
||||
return receiver { it }
|
||||
}
|
||||
override fun FunctionCallInfo.noReceivers() = doTranslate { translateArguments }
|
||||
|
||||
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
||||
return receiver {
|
||||
val receiver = superCallReceiver
|
||||
if (receiver != null) (sequenceOf(receiver) + it).toList() else it
|
||||
}
|
||||
}
|
||||
override fun FunctionCallInfo.dispatchReceiver() = doTranslate { argsWithReceiver(dispatchReceiver!!) }
|
||||
|
||||
private inline fun FunctionCallInfo.receiver(argumentTranslator: (List<JsExpression>) -> List<JsExpression>): JsExpression {
|
||||
private inline fun FunctionCallInfo.doTranslate(getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List<JsExpression>): JsExpression {
|
||||
val fqName = context.getQualifiedReference(callableDescriptor)
|
||||
val functionRef = if (isNative()) fqName else context.aliasOrValue(callableDescriptor) { fqName }
|
||||
val arguments = argumentTranslator(argumentsInfo.translateArguments)
|
||||
val arguments = argumentsInfo.getArguments()
|
||||
|
||||
val constructorDescriptor = callableDescriptor as ConstructorDescriptor
|
||||
if (constructorDescriptor.isPrimary || AnnotationsUtils.isNativeObject(constructorDescriptor)) {
|
||||
@@ -236,10 +229,9 @@ object SuperCallCase : FunctionCallCase() {
|
||||
|
||||
override fun FunctionCallInfo.dispatchReceiver(): JsExpression {
|
||||
// TODO: spread operator
|
||||
val prototypeClass = JsNameRef(Namer.getPrototypeName(), dispatchReceiver!!)
|
||||
val prototypeClass = JsNameRef(Namer.getPrototypeName(), calleeOwner)
|
||||
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
||||
val receiver = superCallReceiver ?: JsLiteral.THIS;
|
||||
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(receiver))
|
||||
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(dispatchReceiver!!))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-11
@@ -17,14 +17,13 @@
|
||||
package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||
import com.google.dart.compiler.backend.js.ast.JsLiteral
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
||||
import java.util.*
|
||||
|
||||
|
||||
object NativeVariableAccessCase : VariableAccessCase() {
|
||||
@@ -110,15 +109,11 @@ object DelegatePropertyAccessIntrinsic : DelegateIntrinsic<VariableAccessInfo> {
|
||||
object SuperPropertyAccessCase : VariableAccessCase() {
|
||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||
val variableName = context.program().getStringLiteral(this.variableName.ident)
|
||||
val jsReceiver = superCallReceiver
|
||||
var propertyOwner = when (jsReceiver) {
|
||||
null -> JsLiteral.THIS
|
||||
else -> jsReceiver
|
||||
}
|
||||
|
||||
return if (isGetAccess())
|
||||
JsInvocation(context.namer().callGetProperty, propertyOwner, dispatchReceiver!!, variableName)
|
||||
JsInvocation(context.namer().callGetProperty, dispatchReceiver!!, calleeOwner, variableName)
|
||||
else
|
||||
JsInvocation(context.namer().callSetProperty, propertyOwner, dispatchReceiver!!, variableName, value!!)
|
||||
JsInvocation(context.namer().callSetProperty, dispatchReceiver!!, calleeOwner, variableName, value!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-15
@@ -27,8 +27,6 @@ import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
@@ -38,7 +36,6 @@ import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.js.translate.context.UsageTrackerKt.getNameForCapturedDescriptor;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForElement;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
|
||||
/**
|
||||
* All the info about the state of the translation process.
|
||||
@@ -433,16 +430,4 @@ public class TranslationContext {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DeclarationDescriptor getSuperTarget(KtSuperExpression expression) {
|
||||
PsiElement labelPsi = bindingContext().get(LABEL_TARGET, expression.getTargetLabel());
|
||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext().get(DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||
if (labelTarget != null) {
|
||||
return labelTarget;
|
||||
}
|
||||
DeclarationDescriptor descriptor = bindingContext().get(REFERENCE_TARGET, expression.getInstanceReference());
|
||||
assert descriptor != null : "Missing declaration descriptor: " + PsiUtilsKt.getTextWithLocation(expression);
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
+21
-8
@@ -18,13 +18,11 @@ package org.jetbrains.kotlin.js.translate.expression;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||
@@ -40,6 +38,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
@@ -56,13 +55,15 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor;
|
||||
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
|
||||
import static org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator.translateAsFQReference;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.*;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.newVar;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.LABEL_TARGET;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
|
||||
public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@@ -454,9 +455,9 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitSuperExpression(@NotNull KtSuperExpression expression, @NotNull TranslationContext context) {
|
||||
DeclarationDescriptor superClassDescriptor = context.bindingContext().get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||
assert superClassDescriptor != null: message(expression);
|
||||
return translateAsFQReference(superClassDescriptor, context);
|
||||
DeclarationDescriptor superTarget = getSuperTarget(context, expression);
|
||||
ReceiverParameterDescriptor receiver = getReceiverParameterForDeclaration(superTarget);
|
||||
return context.getDispatchReceiver(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -522,4 +523,16 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
|
||||
return super.visitAnnotatedExpression(expression, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static DeclarationDescriptor getSuperTarget(TranslationContext context, KtSuperExpression expression) {
|
||||
BindingContext bindingContext = context.bindingContext();
|
||||
PsiElement labelPsi = bindingContext.get(LABEL_TARGET, expression.getTargetLabel());
|
||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||
if (labelTarget != null) return labelTarget;
|
||||
|
||||
DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference());
|
||||
assert descriptor != null : "Missing declaration descriptor: " + PsiUtilsKt.getTextWithLocation(expression);
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class KotlinFunctionIntrinsic extends FunctionIntrinsic {
|
||||
public class KotlinFunctionIntrinsic extends FunctionIntrinsic {
|
||||
@NotNull
|
||||
private final JsNameRef function;
|
||||
|
||||
|
||||
+26
-4
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNew;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||
@@ -27,10 +30,12 @@ import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
|
||||
import org.jetbrains.kotlin.js.patterns.NamePredicate;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo;
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfoExtensionsKt;
|
||||
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.AnnotationsUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression;
|
||||
@@ -50,13 +55,30 @@ import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getStableMan
|
||||
|
||||
public final class TopLevelFIF extends CompositeFIF {
|
||||
public static final DescriptorPredicate EQUALS_IN_ANY = pattern("kotlin", "Any", "equals");
|
||||
@NotNull
|
||||
private static final KotlinFunctionIntrinsic KOTLIN_ANY_EQUALS = new KotlinFunctionIntrinsic("equals") {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@NotNull CallInfo callInfo, @NotNull List<JsExpression> arguments, @NotNull TranslationContext context
|
||||
) {
|
||||
if (CallInfoExtensionsKt.isSuperInvocation(callInfo)) {
|
||||
JsExpression dispatchReceiver = callInfo.getDispatchReceiver();
|
||||
assert arguments.size() == 1 && dispatchReceiver != null;
|
||||
return JsAstUtils.equality(dispatchReceiver, arguments.get(0));
|
||||
}
|
||||
|
||||
return super.apply(callInfo, arguments, context);
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public static final KotlinFunctionIntrinsic KOTLIN_EQUALS = new KotlinFunctionIntrinsic("equals");
|
||||
|
||||
@NotNull
|
||||
public static final DescriptorPredicate HASH_CODE_IN_ANY = pattern("kotlin", "Any", "hashCode");
|
||||
private static final DescriptorPredicate HASH_CODE_IN_ANY = pattern("kotlin", "Any", "hashCode");
|
||||
@NotNull
|
||||
public static final KotlinFunctionIntrinsic KOTLIN_HASH_CODE = new KotlinFunctionIntrinsic("hashCode");
|
||||
private static final KotlinFunctionIntrinsic KOTLIN_HASH_CODE = new KotlinFunctionIntrinsic("hashCode");
|
||||
|
||||
@NotNull
|
||||
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsic() {
|
||||
@@ -127,7 +149,7 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
public static final FunctionIntrinsicFactory INSTANCE = new TopLevelFIF();
|
||||
|
||||
private TopLevelFIF() {
|
||||
add(EQUALS_IN_ANY, KOTLIN_EQUALS);
|
||||
add(EQUALS_IN_ANY, KOTLIN_ANY_EQUALS);
|
||||
add(pattern("kotlin", "toString").isExtensionOf(FQ_NAMES.any.asString()), TO_STRING);
|
||||
add(pattern("kotlin", "equals").isExtensionOf(FQ_NAMES.any.asString()), KOTLIN_EQUALS);
|
||||
add(HASH_CODE_IN_ANY, KOTLIN_HASH_CODE);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package kotlin
|
||||
// This file should be excluded from tests using StdLib, as these methods conflict with corresponding methods from kotlin.test
|
||||
// see StdLibTestBase.removeAdHocAssertions
|
||||
|
||||
fun fail(message: String? = null): Nothing = throw Exception(message)
|
||||
fun fail(message: String? = null): Nothing = js("throw new Error(message)")
|
||||
|
||||
fun <T> assertEquals(expected: T, actual: T, message: String? = null) {
|
||||
if (expected != actual) {
|
||||
|
||||
+4
-3
@@ -1,10 +1,11 @@
|
||||
package foo
|
||||
|
||||
object f {
|
||||
var equalsCalled = false
|
||||
var equalsCalled = 0
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
equalsCalled = true
|
||||
equalsCalled++
|
||||
if (equalsCalled > 1) return false
|
||||
return super.equals(other)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +41,7 @@ fun box(): String {
|
||||
|
||||
val ff: dynamic = f
|
||||
testFalse { ff.equals(v) }
|
||||
assertTrue(f.equalsCalled, "f.equalsCalled")
|
||||
assertEquals(1, f.equalsCalled)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package foo
|
||||
|
||||
open class A {
|
||||
var log = ""
|
||||
|
||||
var called = false
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (called) fail("recursion detected")
|
||||
|
||||
log += "A.equals;"
|
||||
|
||||
called = true
|
||||
val result = super.equals(other)
|
||||
called = false
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
log += "B.equals;"
|
||||
if (other == null) return false
|
||||
return super.equals(other)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
testFalse { a == A() }
|
||||
assertEquals("A.equals;", a.log)
|
||||
|
||||
val b1 = B()
|
||||
testTrue { b1 == b1 }
|
||||
assertEquals("B.equals;A.equals;", b1.log)
|
||||
|
||||
val b2 = B()
|
||||
testFalse { b2 == B() }
|
||||
assertEquals("B.equals;A.equals;", b2.log)
|
||||
|
||||
val b3 = B()
|
||||
testFalse { b3 == null }
|
||||
assertEquals("", b3.log)
|
||||
|
||||
val b4 = B()
|
||||
testFalse { b4.equals(null) }
|
||||
assertEquals("B.equals;", b4.log)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user