JS backend: fix KT-5772 wrong code generated when <,<=,>,>= are used with explicit Comparable type
#KT-5772 Fixed
This commit is contained in:
@@ -31,11 +31,6 @@ public trait Runnable {
|
||||
public open fun run() : Unit;
|
||||
}
|
||||
|
||||
library
|
||||
public trait Comparable<T> {
|
||||
public fun compareTo(that: T): Int
|
||||
}
|
||||
|
||||
library
|
||||
public trait Appendable {
|
||||
public open fun append(csq: CharSequence?): Appendable
|
||||
|
||||
@@ -101,6 +101,8 @@ public final class StandardClasses {
|
||||
.methods("iterator", "contains").properties("start", "end", "increment");
|
||||
|
||||
standardClasses.declare().forFQ("kotlin.Enum").kotlinClass("Enum");
|
||||
|
||||
standardClasses.declare().forFQ("kotlin.Comparable").kotlinClass("Comparable");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
||||
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getTypeByReference;
|
||||
@@ -92,6 +93,9 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
if (NamePredicate.STRING.apply(typeName)) {
|
||||
jsSTypeName = "string";
|
||||
}
|
||||
else if (NamePredicate.NUMBER.apply(typeName)) {
|
||||
return JsAstUtils.isNumber(expressionToMatch);
|
||||
}
|
||||
else if (NamePredicate.PRIMITIVE_NUMBERS.apply(typeName)) {
|
||||
jsSTypeName = "number";
|
||||
}
|
||||
|
||||
+26
-5
@@ -34,11 +34,12 @@ import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredi
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
||||
import org.jetbrains.k2js.translate.operation.OperatorTable;
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setArguments;
|
||||
|
||||
public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
|
||||
INSTANCE;
|
||||
@@ -76,7 +77,7 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static final FunctionIntrinsic NUMBER_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
|
||||
private static final FunctionIntrinsic BUILTINS_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@@ -90,6 +91,21 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static final FunctionIntrinsic PRIMITIVE_NUMBER_COMPARE_TO_INTRINSIC = new FunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@Nullable JsExpression receiver,
|
||||
@NotNull List<JsExpression> arguments,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
assert receiver != null;
|
||||
assert arguments.size() == 1;
|
||||
return JsAstUtils.primitiveCompareTo(receiver, arguments.get(0));
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static final NamePredicate BINARY_OPERATIONS = new NamePredicate(OperatorConventions.BINARY_OPERATION_NAMES.values());
|
||||
private static final DescriptorPredicate PRIMITIVE_NUMBERS_BINARY_OPERATIONS = pattern(NamePredicate.PRIMITIVE_NUMBERS, BINARY_OPERATIONS);
|
||||
@@ -115,13 +131,18 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
|
||||
@Nullable
|
||||
@Override
|
||||
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
|
||||
if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) {
|
||||
return PRIMITIVE_NUMBER_COMPARE_TO_INTRINSIC;
|
||||
}
|
||||
|
||||
if (JsDescriptorUtils.isBuiltin(descriptor) && descriptor.getName().equals(OperatorConventions.COMPARE_TO)) {
|
||||
return BUILTINS_COMPARE_TO_INTRINSIC;
|
||||
}
|
||||
|
||||
if (!PREDICATE.apply(descriptor)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) {
|
||||
return NUMBER_COMPARE_TO_INTRINSIC;
|
||||
}
|
||||
|
||||
if (pattern("Int|Short|Byte.div").apply(descriptor)) {
|
||||
JetType resultType = descriptor.getReturnType();
|
||||
|
||||
+3
@@ -45,6 +45,9 @@ public final class NamePredicate implements Predicate<Name> {
|
||||
@NotNull
|
||||
public static final NamePredicate STRING = new NamePredicate("String");
|
||||
|
||||
@NotNull
|
||||
public static final NamePredicate NUMBER = new NamePredicate("Number");
|
||||
|
||||
@NotNull
|
||||
private final Set<Name> validNames = Sets.newHashSet();
|
||||
|
||||
|
||||
+24
-9
@@ -16,18 +16,18 @@
|
||||
|
||||
package org.jetbrains.k2js.translate.intrinsic.operation
|
||||
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext
|
||||
import org.jetbrains.k2js.translate.operation.OperatorTable
|
||||
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
|
||||
|
||||
import org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lexer.JetToken
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext
|
||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern
|
||||
import org.jetbrains.k2js.translate.operation.OperatorTable
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils
|
||||
import org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken
|
||||
|
||||
|
||||
object CompareToBOIF : BinaryOperationIntrinsicFactory {
|
||||
@@ -39,9 +39,24 @@ object CompareToBOIF : BinaryOperationIntrinsicFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private object CompareToFunctionIntrinsic : AbstractBinaryOperationIntrinsic() {
|
||||
override fun apply(expression: JetBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression {
|
||||
val operator = OperatorTable.getBinaryOperator(getOperationToken(expression))
|
||||
val compareTo = JsAstUtils.compareTo(left, right)
|
||||
return JsBinaryOperation(operator, compareTo, context.program().getNumberLiteral(0))
|
||||
}
|
||||
}
|
||||
|
||||
override public fun getSupportTokens(): ImmutableSet<JetToken> = OperatorConventions.COMPARISON_OPERATIONS
|
||||
|
||||
override public fun getIntrinsic(descriptor: FunctionDescriptor): BinaryOperationIntrinsic? {
|
||||
return if (JsDescriptorUtils.isBuiltin(descriptor)) CompareToIntrinsic else null
|
||||
if (JsDescriptorUtils.isBuiltin(descriptor))
|
||||
when {
|
||||
pattern("Int|Short|Byte|Double|Float|Char|String|Long.compareTo").apply(descriptor) ->
|
||||
return CompareToIntrinsic
|
||||
else ->
|
||||
return CompareToFunctionIntrinsic
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,16 @@ public final class JsAstUtils {
|
||||
return new JsInvocation(new JsNameRef(OperatorConventions.COMPARE_TO.getIdentifier(), Namer.KOTLIN_OBJECT_REF), left, right);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression primitiveCompareTo(@NotNull JsExpression left, @NotNull JsExpression right) {
|
||||
return new JsInvocation(new JsNameRef("primitiveCompareTo", Namer.KOTLIN_OBJECT_REF), left, right);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsExpression isNumber(@NotNull JsExpression expression) {
|
||||
return new JsInvocation(new JsNameRef("isNumber", Namer.KOTLIN_OBJECT_REF), expression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsPrefixOperation negated(@NotNull JsExpression expression) {
|
||||
return new JsPrefixOperation(JsUnaryOperator.NOT, expression);
|
||||
|
||||
@@ -86,9 +86,21 @@
|
||||
};
|
||||
|
||||
Kotlin.compareTo = function(a, b) {
|
||||
var type = typeof a;
|
||||
if (type == "number" || type == "string") {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
return a.compareTo_za3rmp$(b);
|
||||
};
|
||||
|
||||
Kotlin.primitiveCompareTo = function(a, b) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
};
|
||||
|
||||
Kotlin.isNumber = function (a) {
|
||||
return typeof a == "number";
|
||||
};
|
||||
|
||||
Kotlin.toShort = function(a) {
|
||||
return (a & 0xFFFF) << 16 >> 16;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user