Custom equals operator (includes little patch to frontend)

#KT-2354 fixed
This commit is contained in:
Pavel V. Talanov
2012-07-05 15:32:57 +04:00
parent 88a38d9b5b
commit 6354d1bae0
5 changed files with 24 additions and 19 deletions
@@ -21,7 +21,6 @@ import com.google.common.collect.Multimap;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.JetNodeTypes;
@@ -958,6 +957,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (resolutionResults.isSuccess()) { if (resolutionResults.isSuccess()) {
FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor(); FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
context.trace.record(REFERENCE_TARGET, operationSign, equals); context.trace.record(REFERENCE_TARGET, operationSign, equals);
context.trace.record(RESOLVED_CALL, operationSign, resolutionResults.getResultingCall());
if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) {
ensureNonemptyIntersectionOfOperandTypes(expression, context); ensureNonemptyIntersectionOfOperandTypes(expression, context);
} }
@@ -22,7 +22,7 @@ public final class EqualsTest extends AbstractExpressionTest {
super("equals/"); super("equals/");
} }
public void TODO_testCustomEqualsMethod() throws Exception { public void testCustomEqualsMethod() throws Exception {
fooBoxTest(); fooBoxTest();
} }
@@ -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.operation.CompareToTranslator.isCompareToCall;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; 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.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.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.PsiUtils.*;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; import static org.jetbrains.k2js.translate.utils.TranslationUtils.*;
@@ -52,13 +52,13 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
@NotNull @NotNull
public static JsExpression translate(@NotNull JetBinaryExpression expression, public static JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new BinaryOperationTranslator(expression, context).translate()); return (new BinaryOperationTranslator(expression, context).translate());
} }
@NotNull @NotNull
/*package*/ static JsExpression translateAsOverloadedCall(@NotNull JetBinaryExpression expression, /*package*/ static JsExpression translateAsOverloadedCall(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new BinaryOperationTranslator(expression, context)).translateAsOverloadedBinaryOperation(); return (new BinaryOperationTranslator(expression, context)).translateAsOverloadedBinaryOperation();
} }
@@ -69,11 +69,11 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
private final FunctionDescriptor operationDescriptor; private final FunctionDescriptor operationDescriptor;
private BinaryOperationTranslator(@NotNull JetBinaryExpression expression, private BinaryOperationTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
super(context); super(context);
this.expression = expression; this.expression = expression;
this.operationDescriptor = this.operationDescriptor =
getFunctionDescriptorForOperationExpression(bindingContext(), expression); getFunctionDescriptorForOperationExpression(bindingContext(), expression);
} }
@NotNull @NotNull
@@ -91,9 +91,9 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
return CompareToTranslator.translate(expression, context()); return CompareToTranslator.translate(expression, context());
} }
assert operationDescriptor != null : assert operationDescriptor != null :
"Overloadable operations must have not null descriptor"; "Overloadable operations must have not null descriptor";
if (isEquals(operationDescriptor)) { if (isEquals(operationDescriptor) && context().intrinsics().isIntrinsic(operationDescriptor)) {
return translateAsEqualsCall(); return translateAsEqualsIntrinsic();
} }
return translateAsOverloadedBinaryOperation(); return translateAsOverloadedBinaryOperation();
} }
@@ -116,7 +116,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
private JsExpression translateAsEqualsCall() { private JsExpression translateAsEqualsIntrinsic() {
assert operationDescriptor != null : "Equals operation must resolve to descriptor."; assert operationDescriptor != null : "Equals operation must resolve to descriptor.";
EqualsIntrinsic intrinsic = context().intrinsics().getEqualsIntrinsic(operationDescriptor); EqualsIntrinsic intrinsic = context().intrinsics().getEqualsIntrinsic(operationDescriptor);
intrinsic.setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ)); intrinsic.setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ));
@@ -137,10 +137,8 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression translateAsOverloadedBinaryOperation() { private JsExpression translateAsOverloadedBinaryOperation() {
CallBuilder callBuilder = setReceiverAndArguments(); CallBuilder callBuilder = setReceiverAndArguments();
ResolvedCall<?> resolvedCall1 = ResolvedCall<?> resolvedCall = getResolvedCall(bindingContext(), expression.getOperationReference());
getResolvedCall(bindingContext(), expression.getOperationReference()); JsExpression result = callBuilder.resolvedCall(resolvedCall).type(CallType.NORMAL).translate();
JsExpression result = callBuilder.resolvedCall(resolvedCall1)
.type(CallType.NORMAL).translate();
return mayBeWrapWithNegation(result); return mayBeWrapWithNegation(result);
} }
@@ -161,7 +159,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression mayBeWrapWithNegation(@NotNull JsExpression result) { private JsExpression mayBeWrapWithNegation(@NotNull JsExpression result) {
if (isNotInOperation(expression)) { if (isNegatedOperation(expression)) {
return not(result); return not(result);
} }
else { else {
@@ -93,6 +93,10 @@ public final class PsiUtils {
return (binaryExpression.getOperationToken() == JetTokens.NOT_IN); 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) { private static boolean isInOperation(@NotNull JetBinaryExpression binaryExpression) {
return (binaryExpression.getOperationToken() == JetTokens.IN_KEYWORD); return (binaryExpression.getOperationToken() == JetTokens.IN_KEYWORD);
} }
@@ -1,9 +1,12 @@
package foo package foo
class Foo(val name: String) { class Foo(val name: String) {
public fun equals(that: Foo): Boolean { public fun equals(that: Any?): Boolean {
return this.name == that.name if (that !is Foo) {
} return false
}
return this.name == that.name
}
} }
fun box() : Boolean { fun box() : Boolean {