From dde50a34db9c431899e1aa0f43e67764ac09859c Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 25 May 2017 16:48:08 +0300 Subject: [PATCH] Fix comparison of boolean values in JS BE See KT-16984 --- .../operatorConventions/compareTo/boolean.kt | 3 --- .../kotlin/util/OperatorNameConventions.kt | 2 +- js/js.libraries/src/js/misc.js | 8 +++--- .../js/test/semantics/BoxJsTestGenerated.java | 6 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 8 +----- .../intrinsic/operation/CompareToBOIF.kt | 5 ++-- .../operation/binaryOperationIntrinsics.kt | 2 +- .../expression/compareTo/booleanCompareTo.kt | 26 +++++++++++++++++++ 8 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 js/js.translator/testData/box/expression/compareTo/booleanCompareTo.kt diff --git a/compiler/testData/codegen/box/operatorConventions/compareTo/boolean.kt b/compiler/testData/codegen/box/operatorConventions/compareTo/boolean.kt index a8a367c3354..833e11a733a 100644 --- a/compiler/testData/codegen/box/operatorConventions/compareTo/boolean.kt +++ b/compiler/testData/codegen/box/operatorConventions/compareTo/boolean.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - fun checkLess(x: Boolean, y: Boolean) = when { x >= y -> "Fail $x >= $y" !(x < y) -> "Fail !($x < $y)" diff --git a/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt b/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt index 67a381ee5d5..362a0c99925 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt @@ -69,7 +69,7 @@ object OperatorNameConventions { internal val SIMPLE_UNARY_OPERATION_NAMES = setOf(UNARY_PLUS, UNARY_MINUS, NOT) @JvmField - internal val BINARY_OPERATION_NAMES = setOf(TIMES, PLUS, MINUS, DIV, MOD, REM, RANGE_TO) + val BINARY_OPERATION_NAMES = setOf(TIMES, PLUS, MINUS, DIV, MOD, REM, RANGE_TO) @JvmField internal val ASSIGNMENT_OPERATIONS = setOf(TIMES_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, REM_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN) diff --git a/js/js.libraries/src/js/misc.js b/js/js.libraries/src/js/misc.js index d0045ae19d0..54feff2cef6 100644 --- a/js/js.libraries/src/js/misc.js +++ b/js/js.libraries/src/js/misc.js @@ -17,14 +17,14 @@ Kotlin.compareTo = function (a, b) { var typeA = typeof a; var typeB = typeof a; - if (Kotlin.isChar(a) && typeB == "number") { + if (Kotlin.isChar(a) && typeB === "number") { return Kotlin.primitiveCompareTo(a.charCodeAt(0), b); } - if (typeA == "number" && Kotlin.isChar(b)) { + if (typeA === "number" && Kotlin.isChar(b)) { return Kotlin.primitiveCompareTo(a, b.charCodeAt(0)); } - if (typeA == "number" || typeA == "string") { - return a < b ? -1 : a > b ? 1 : 0; + if (typeA === "number" || typeA === "string" || typeA === "boolean") { + return Kotlin.primitiveCompareTo(a, b); } return a.compareTo_11rb$(b); }; diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index e9b3fc2c12f..9095720de48 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1882,6 +1882,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/expression/compareTo"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("booleanCompareTo.kt") + public void testBooleanCompareTo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/compareTo/booleanCompareTo.kt"); + doTest(fileName); + } + @TestMetadata("customCompareToMethod.kt") public void testCustomCompareToMethod() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/compareTo/customCompareToMethod.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9942707cf96..e82e35ffacc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13222,13 +13222,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("boolean.kt") public void testBoolean() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/operatorConventions/compareTo/boolean.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("comparable.kt") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/CompareToBOIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/CompareToBOIF.kt index 0836ca27d3a..94dde98f16a 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/CompareToBOIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/CompareToBOIF.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.operation.OperatorTable import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken +import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.types.KotlinType @@ -34,7 +35,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions object CompareToBOIF : BinaryOperationIntrinsicFactory { val COMPARE_TO_CHAR = pattern("Int|Short|Byte|Double|Float.compareTo(Char)") val CHAR_COMPARE_TO = pattern("Char.compareTo(Int|Short|Byte|Double|Float)") - val PRIMITIVE_COMPARE_TO = pattern("Int|Short|Byte|Double|Float|Char|String.compareTo") + val PRIMITIVE_COMPARE_TO = pattern("Int|Short|Byte|Double|Float|Char|String|Boolean.compareTo") private object CompareToIntrinsic : AbstractBinaryOperationIntrinsic() { override fun apply(expression: KtBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression { @@ -65,7 +66,7 @@ object CompareToBOIF : BinaryOperationIntrinsicFactory { } } - override fun getSupportTokens() = OperatorConventions.COMPARISON_OPERATIONS + override fun getSupportTokens(): Set = OperatorConventions.COMPARISON_OPERATIONS override fun getIntrinsic(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): BinaryOperationIntrinsic? { if (descriptor.isDynamic()) return CompareToIntrinsic diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/binaryOperationIntrinsics.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/binaryOperationIntrinsics.kt index 478843100ee..e9ecdeffd2b 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/binaryOperationIntrinsics.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/binaryOperationIntrinsics.kt @@ -76,7 +76,7 @@ private data class IntrinsicKey( interface BinaryOperationIntrinsicFactory { - fun getSupportTokens(): ImmutableSet + fun getSupportTokens(): Set fun getIntrinsic(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): BinaryOperationIntrinsic? } diff --git a/js/js.translator/testData/box/expression/compareTo/booleanCompareTo.kt b/js/js.translator/testData/box/expression/compareTo/booleanCompareTo.kt new file mode 100644 index 00000000000..2cdeabeb70a --- /dev/null +++ b/js/js.translator/testData/box/expression/compareTo/booleanCompareTo.kt @@ -0,0 +1,26 @@ +// EXPECTED_REACHABLE_NODES: 489 +fun box(): String { + val r1 = trueFun() > falseFun() + if (!r1) return "fail1" + + if (falseFun() > trueFun()) return "fail2" + + if (trueFun() > trueFun()) return "fail3" + + if (trueFun() < falseFun()) return "fail4" + + val x: Comparable = trueFun() + val y: Comparable = falseFun() + + if (x.compareTo(false) <= 0) return "fail5" + if (y.compareTo(true) >= 0) return "fail6" + if (y.compareTo(false) != 0) return "fail7" + + if ((true).compareTo(false) <= 0) return "fail8" + + return "OK" +} + +fun trueFun() = true + +fun falseFun() = false \ No newline at end of file