Kaynağa Gözat

[jvm] fixed Reflect.compare for different number types (closes #10350)

Aleksandr Kuzmenko 4 yıl önce
ebeveyn
işleme
f0ea91efa7

+ 1 - 0
extra/CHANGES.txt

@@ -11,6 +11,7 @@
 	php : fixed type of `php.db.PDO.ATTR_DRIVER_NAME` (#10319)
 	eval : fixed signature of `eval.luv.Tcp.noDelay` method
 	lua : fixed `string.length` when `string` has type of a type parameter constrained to `String` (#10343)
+	jvm : fixed `Reflect.compare()` for different number types (#10350)
 
 2021-07-01 4.2.3:
 

+ 30 - 2
std/jvm/_std/Reflect.hx

@@ -22,6 +22,15 @@
 
 import jvm.Jvm;
 
+import java.lang.Number;
+import java.lang.Long.LongClass;
+import java.lang.Double.DoubleClass;
+import java.lang.Float.FloatClass;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+using jvm.NativeTools.NativeClassTools;
+
 @:coreApi
 class Reflect {
 	public static function hasField(o:Dynamic, field:String):Bool {
@@ -100,8 +109,27 @@ class Reflect {
 		if (b == null) {
 			return 1;
 		}
-		if (Jvm.instanceof(a, java.lang.Number) && Jvm.instanceof(b, java.lang.Number)) {
-			return java.lang.Long.compare((cast a : java.lang.Number).longValue(), (cast b : java.lang.Number).longValue());
+		if (Jvm.instanceof(a, Number) && Jvm.instanceof(b, Number)) {
+			var a = (cast a:Number);
+			var b = (cast b:Number);
+			inline function isBig(v:Number)
+				return Jvm.instanceof(v, BigDecimal) || Jvm.instanceof(v, BigInteger);
+			inline function cmpLongTo(long:Number, another:Number) {
+				if(Jvm.instanceof(another, DoubleClass)) {
+					return new BigDecimal(long.longValue()).compareTo(new BigDecimal(another.doubleValue()));
+				} else if(Jvm.instanceof(another, FloatClass)) {
+					return new BigDecimal(long.longValue()).compareTo(new BigDecimal(another.floatValue()));
+				} else {
+					return LongClass.compare(long.longValue(), another.longValue());
+				}
+			}
+			if(isBig(a) || isBig(b))
+				return new BigDecimal((cast a:java.lang.Object).toString()).compareTo((cast a:java.lang.Object).toString());
+			if(Jvm.instanceof(a, LongClass))
+				return cmpLongTo(a, b);
+			if(Jvm.instanceof(b, LongClass))
+				return -1 * cmpLongTo(b, a);
+			return DoubleClass.compare(a.doubleValue(), b.doubleValue());
 		}
 		if (Jvm.instanceof(a, java.NativeString)) {
 			if (!Jvm.instanceof(b, java.NativeString)) {

+ 8 - 0
tests/unit/src/unit/issues/Issue10350.hx

@@ -0,0 +1,8 @@
+package unit.issues;
+
+class Issue10350 extends Test {
+	function test() {
+		t(Reflect.compare(0.1, 0.2) < 0);
+		t(Reflect.compare(0.2, 0.1) > 0);
+	}
+}