From 6354d1bae0e3f6dbb519291b328b74b3200afd8f Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Thu, 5 Jul 2012 15:32:57 +0400 Subject: [PATCH] Custom equals operator (includes little patch to frontend) #KT-2354 fixed --- .../BasicExpressionTypingVisitor.java | 2 +- .../k2js/test/semantics/EqualsTest.java | 2 +- .../operation/BinaryOperationTranslator.java | 26 +++++++++---------- .../k2js/translate/utils/PsiUtils.java | 4 +++ .../equals/cases/customEqualsMethod.kt | 9 ++++--- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 81065acdc19..c91711ef870 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -21,7 +21,6 @@ import com.google.common.collect.Multimap; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; -import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; @@ -958,6 +957,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (resolutionResults.isSuccess()) { FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor(); context.trace.record(REFERENCE_TARGET, operationSign, equals); + context.trace.record(RESOLVED_CALL, operationSign, resolutionResults.getResultingCall()); if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { ensureNonemptyIntersectionOfOperandTypes(expression, context); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/EqualsTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/EqualsTest.java index 67c073bfb89..7c78890e80d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/EqualsTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/EqualsTest.java @@ -22,7 +22,7 @@ public final class EqualsTest extends AbstractExpressionTest { super("equals/"); } - public void TODO_testCustomEqualsMethod() throws Exception { + public void testCustomEqualsMethod() throws Exception { fooBoxTest(); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java index 5389fae9639..c55be86d03a 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java @@ -39,8 +39,8 @@ import static org.jetbrains.k2js.translate.operation.AssignmentTranslator.isAssi import static org.jetbrains.k2js.translate.operation.CompareToTranslator.isCompareToCall; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; -import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isEquals; import static org.jetbrains.k2js.translate.utils.JsAstUtils.not; +import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isEquals; import static org.jetbrains.k2js.translate.utils.PsiUtils.*; import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; @@ -52,13 +52,13 @@ public final class BinaryOperationTranslator extends AbstractTranslator { @NotNull public static JsExpression translate(@NotNull JetBinaryExpression expression, - @NotNull TranslationContext context) { + @NotNull TranslationContext context) { return (new BinaryOperationTranslator(expression, context).translate()); } @NotNull /*package*/ static JsExpression translateAsOverloadedCall(@NotNull JetBinaryExpression expression, - @NotNull TranslationContext context) { + @NotNull TranslationContext context) { return (new BinaryOperationTranslator(expression, context)).translateAsOverloadedBinaryOperation(); } @@ -69,11 +69,11 @@ public final class BinaryOperationTranslator extends AbstractTranslator { private final FunctionDescriptor operationDescriptor; private BinaryOperationTranslator(@NotNull JetBinaryExpression expression, - @NotNull TranslationContext context) { + @NotNull TranslationContext context) { super(context); this.expression = expression; this.operationDescriptor = - getFunctionDescriptorForOperationExpression(bindingContext(), expression); + getFunctionDescriptorForOperationExpression(bindingContext(), expression); } @NotNull @@ -91,9 +91,9 @@ public final class BinaryOperationTranslator extends AbstractTranslator { return CompareToTranslator.translate(expression, context()); } assert operationDescriptor != null : - "Overloadable operations must have not null descriptor"; - if (isEquals(operationDescriptor)) { - return translateAsEqualsCall(); + "Overloadable operations must have not null descriptor"; + if (isEquals(operationDescriptor) && context().intrinsics().isIntrinsic(operationDescriptor)) { + return translateAsEqualsIntrinsic(); } return translateAsOverloadedBinaryOperation(); } @@ -116,7 +116,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator { } @NotNull - private JsExpression translateAsEqualsCall() { + private JsExpression translateAsEqualsIntrinsic() { assert operationDescriptor != null : "Equals operation must resolve to descriptor."; EqualsIntrinsic intrinsic = context().intrinsics().getEqualsIntrinsic(operationDescriptor); intrinsic.setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ)); @@ -137,10 +137,8 @@ public final class BinaryOperationTranslator extends AbstractTranslator { @NotNull private JsExpression translateAsOverloadedBinaryOperation() { CallBuilder callBuilder = setReceiverAndArguments(); - ResolvedCall resolvedCall1 = - getResolvedCall(bindingContext(), expression.getOperationReference()); - JsExpression result = callBuilder.resolvedCall(resolvedCall1) - .type(CallType.NORMAL).translate(); + ResolvedCall resolvedCall = getResolvedCall(bindingContext(), expression.getOperationReference()); + JsExpression result = callBuilder.resolvedCall(resolvedCall).type(CallType.NORMAL).translate(); return mayBeWrapWithNegation(result); } @@ -161,7 +159,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator { @NotNull private JsExpression mayBeWrapWithNegation(@NotNull JsExpression result) { - if (isNotInOperation(expression)) { + if (isNegatedOperation(expression)) { return not(result); } else { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java index e4f08b3a55a..7aeb7b2882d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/PsiUtils.java @@ -93,6 +93,10 @@ public final class PsiUtils { return (binaryExpression.getOperationToken() == JetTokens.NOT_IN); } + public static boolean isNegatedOperation(@NotNull JetBinaryExpression binaryExpression) { + return (binaryExpression.getOperationToken() == JetTokens.EXCLEQ) || isNotInOperation(binaryExpression); + } + private static boolean isInOperation(@NotNull JetBinaryExpression binaryExpression) { return (binaryExpression.getOperationToken() == JetTokens.IN_KEYWORD); } diff --git a/js/js.translator/testFiles/expression/equals/cases/customEqualsMethod.kt b/js/js.translator/testFiles/expression/equals/cases/customEqualsMethod.kt index 70c58bf634f..4dae1afc721 100644 --- a/js/js.translator/testFiles/expression/equals/cases/customEqualsMethod.kt +++ b/js/js.translator/testFiles/expression/equals/cases/customEqualsMethod.kt @@ -1,9 +1,12 @@ package foo class Foo(val name: String) { - public fun equals(that: Foo): Boolean { - return this.name == that.name - } + public fun equals(that: Any?): Boolean { + if (that !is Foo) { + return false + } + return this.name == that.name + } } fun box() : Boolean {