Explicit equals method for primitives and correct global equals method.
Includes cosmetics. #KT-2372 Fixed
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
+6
-6
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-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();
|
||||
|
||||
+1
@@ -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);
|
||||
}
|
||||
|
||||
+1
@@ -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,
|
||||
|
||||
+8
-16
@@ -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
|
||||
}
|
||||
+21
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user