Explicit equals method for primitives and correct global equals method.

Includes cosmetics.
#KT-2372 Fixed
This commit is contained in:
Pavel V. Talanov
2012-07-18 17:15:27 +04:00
parent e0651de9ed
commit b45c14b0ab
9 changed files with 52 additions and 28 deletions
@@ -22,7 +22,7 @@ public final class EqualsTest extends AbstractExpressionTest {
super("equals/");
}
public void TODO_testCustomEqualsMethodOnAny() throws Exception {
public void testCustomEqualsMethodOnAny() throws Exception {
fooBoxTest();
}
@@ -34,6 +34,10 @@ public final class EqualsTest extends AbstractExpressionTest {
fooBoxTest();
}
public void testExplicitEqualsMethodForPrimitives() throws Exception {
fooBoxTest();
}
public void testStringsEqual() throws Exception {
fooBoxTest();
}
@@ -19,7 +19,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.factories;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInFunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
@@ -27,16 +27,16 @@ import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternB
* @author Pavel Talanov
*/
public final class TopLevelFIF extends CompositeFIF {
@NotNull
private static final DescriptorPredicate EXT_TO_STRING = pattern("toString");
public static final CallStandardMethodIntrinsic EQUALS = new CallStandardMethodIntrinsic("Kotlin.equals", true, 1);
@NotNull
public static final FunctionIntrinsicFactory INSTANCE = new TopLevelFIF();
private TopLevelFIF() {
add(EXT_TO_STRING, new BuiltInFunctionIntrinsic("toString"));
//TODO: add intrinsic for calling equals explicitly
add(pattern("toString"), new BuiltInFunctionIntrinsic("toString"));
add(pattern("equals"), EQUALS);
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
add(pattern("arrayOfNulls"), new CallStandardMethodIntrinsic("Kotlin.nullArray", false, 1));
}
}
@@ -32,7 +32,7 @@ import java.util.List;
public final class NamePredicate implements Predicate<Name> {
@NotNull
public static final NamePredicate PRIMITIVE_NUMBERS = new NamePredicate("Int", "Double", "Float", "Long", "Short");
public static final NamePredicate PRIMITIVE_NUMBERS = new NamePredicate("Int", "Double", "Float", "Long", "Short", "Byte");
@NotNull
private final List<Name> validNames = Lists.newArrayList();
@@ -28,6 +28,7 @@ public interface BinaryOperationIntrinsic {
boolean isApplicable(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context);
@NotNull
JsExpression apply(@NotNull JetBinaryExpression expression, @NotNull JsExpression left,
@NotNull JsExpression right, @NotNull TranslationContext context);
}
@@ -44,6 +44,7 @@ public final class CompareToInstrinsic implements BinaryOperationIntrinsic {
return JsDescriptorUtils.isStandardDeclaration(functionDescriptor);
}
@NotNull
@Override
public JsExpression apply(@NotNull JetBinaryExpression expression,
@NotNull JsExpression left,
@@ -23,19 +23,20 @@ import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.factories.TopLevelFIF;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import java.util.Arrays;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.equality;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.inequality;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNullLiteral;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.nullCheck;
/**
* @author Pavel Talanov
*/
public final class EqualsIntrinsic implements BinaryOperationIntrinsic {
@Override
public boolean isApplicable(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
if (!OperatorConventions.EQUALS_OPERATIONS.contains(getOperationToken(expression))) {
@@ -47,22 +48,13 @@ public final class EqualsIntrinsic implements BinaryOperationIntrinsic {
}
@Override
@NotNull
public JsExpression apply(@NotNull JetBinaryExpression expression,
@NotNull JsExpression left,
@NotNull JsExpression right,
@NotNull TranslationContext context) {
boolean isNegated = getOperationToken(expression).equals(JetTokens.EXCLEQ);
if (isNullLiteral(context, right)) {
return nullCheck(context, left, !isNegated);
}
if (isNullLiteral(context, left)) {
return nullCheck(context, right, !isNegated);
}
if (isNegated) {
return inequality(left, right);
}
else {
return equality(left, right);
}
JsExpression result = TopLevelFIF.EQUALS.apply(left, Arrays.asList(right), context);
return isNegated ? JsAstUtils.negated(result) : result;
}
}
@@ -9,8 +9,8 @@ class Foo(val name: String) {
}
}
fun callEqualsMethod(v1: Foo, v2: Foo): Boolean {
return v1.equals(v2)
class Bar() {
}
fun box() : Boolean {
@@ -18,7 +18,11 @@ fun box() : Boolean {
val b = Foo("abc")
val c = Foo("def")
if (!callEqualsMethod(a, b)) return false
if (callEqualsMethod(a, c)) return false
if (!(a equals b)) return false
if (a equals c) return false
if (Bar() equals Bar()) return false
val g = Bar()
if (!(g equals g)) return false
if (g equals Bar()) return false
return true
}
@@ -0,0 +1,21 @@
package foo
fun box() : Boolean {
val a = 2
if (!(a equals a)) return false
if (!(a equals 2)) return false
if (!(a equals 2.0)) return false
val c = "a"
if (!("a" equals c)) return false
if (!(null equals null)) return false
val d = 5.6
if (!(d.toShort() equals 5.toShort())) return false
if (!(d.toByte() equals 5.toByte())) return false
if (!(d.toFloat() equals 5.6.toFloat())) return false
if (!(d.toInt() equals 5)) return false
if (true equals false) return false
val n: Number = 3
if (!(n equals 3.3.toInt())) return false
return true
}
+1
View File
@@ -23,6 +23,7 @@ var kotlin = {set:function (receiver, key, value) {
"use strict";
Kotlin.equals = function (obj1, obj2) {
if ((obj1 === null)|| (obj1 === undefined)) return obj2 === null;
if (typeof obj1 == "object") {
if (obj1.equals !== undefined) {
return obj1.equals(obj2);