From 6aaccae6a9e87bd4bce0eadef836ba48d5db3346 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Mon, 1 Jun 2015 22:09:35 +0300 Subject: [PATCH] JS backend: compare enum entries strictly #KT-7840 fixed --- .../kotlin/js/test/semantics/EnumTest.java | 4 ++ .../intrinsic/operation/EqualsBOIF.kt | 40 +++++++++++++------ .../testData/enum/cases/equals.kt | 20 ++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 js/js.translator/testData/enum/cases/equals.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/EnumTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/EnumTest.java index 7cdb3f2a630..6cb150d8a02 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/EnumTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/EnumTest.java @@ -54,4 +54,8 @@ public class EnumTest extends SingleFileTranslationTest { public void testNativeEnum() throws Exception { checkFooBoxIsOk(); } + + public void testEquals() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt index f7022702e0d..a1bf4a5b568 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt @@ -16,7 +16,10 @@ package org.jetbrains.kotlin.js.translate.intrinsic.operation -import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.JsBinaryOperation +import com.google.dart.compiler.backend.js.ast.JsBinaryOperator +import com.google.dart.compiler.backend.js.ast.JsExpression +import com.google.dart.compiler.backend.js.ast.JsLiteral import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.patterns.NamePredicate import org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern @@ -26,15 +29,13 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken import org.jetbrains.kotlin.js.translate.utils.TranslationUtils -import org.jetbrains.kotlin.lexer.JetToken import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.JetBinaryExpression +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.isDynamic - import java.util.Arrays -import com.google.common.collect.ImmutableSet object EqualsBOIF : BinaryOperationIntrinsicFactory { @@ -42,15 +43,14 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory { private object LONG_EQUALS_ANY_INTRINSIC : AbstractBinaryOperationIntrinsic() { override fun apply(expression: JetBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression { - val isNegated = getOperationToken(expression) == JetTokens.EXCLEQ val invokeEquals = JsAstUtils.equalsForObject(left, right) - return if (isNegated) JsAstUtils.not(invokeEquals) else invokeEquals + return if (expression.isNegated()) JsAstUtils.not(invokeEquals) else invokeEquals } } private object EqualsIntrinsic : AbstractBinaryOperationIntrinsic() { override fun apply(expression: JetBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression { - val isNegated = getOperationToken(expression) == JetTokens.EXCLEQ + val isNegated = expression.isNegated() if (right == JsLiteral.NULL || left == JsLiteral.NULL) { return TranslationUtils.nullCheck(if (right == JsLiteral.NULL) left else right, isNegated) } @@ -81,12 +81,26 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory { } } + object EnumEqualsIntrinsic : AbstractBinaryOperationIntrinsic() { + override fun apply(expression: JetBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsBinaryOperation { + val operator = if (expression.isNegated()) JsBinaryOperator.REF_NEQ else JsBinaryOperator.REF_EQ + return JsBinaryOperation(operator, left, right) + } + } + override public fun getSupportTokens() = OperatorConventions.EQUALS_OPERATIONS - override public fun getIntrinsic(descriptor: FunctionDescriptor): BinaryOperationIntrinsic? { - if (JsDescriptorUtils.isBuiltin(descriptor) || TopLevelFIF.EQUALS_IN_ANY.apply(descriptor)) { - return if (LONG_EQUALS_ANY.apply(descriptor)) LONG_EQUALS_ANY_INTRINSIC else EqualsIntrinsic - } - return null - } + override public fun getIntrinsic(descriptor: FunctionDescriptor): BinaryOperationIntrinsic? = + when { + (LONG_EQUALS_ANY.apply(descriptor)) -> LONG_EQUALS_ANY_INTRINSIC + + DescriptorUtils.isEnumClass(descriptor.getContainingDeclaration()) -> EnumEqualsIntrinsic + + JsDescriptorUtils.isBuiltin(descriptor) || + TopLevelFIF.EQUALS_IN_ANY.apply(descriptor) -> EqualsIntrinsic + + else -> null + } + + private fun JetBinaryExpression.isNegated() = getOperationToken(this) == JetTokens.EXCLEQ } diff --git a/js/js.translator/testData/enum/cases/equals.kt b/js/js.translator/testData/enum/cases/equals.kt new file mode 100644 index 00000000000..0a60668e363 --- /dev/null +++ b/js/js.translator/testData/enum/cases/equals.kt @@ -0,0 +1,20 @@ +package foo + +enum class Foo { + A, + B +} + +fun box(): String { + testFalse { Foo.A == Foo.B } + testTrue { Foo.A != Foo.B } + testTrue { Foo.A == Foo.A } + testFalse { Foo.A != Foo.A } + + testFalse { Foo.A == null } + testTrue { Foo.A != null } + testFalse { null == Foo.A } + testTrue { null != Foo.A } + + return "OK" +}