GROOVY-7997: fix long and BigInteger to BigDecimal conversion in method calls
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/bf259e9a Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/bf259e9a Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/bf259e9a Branch: refs/heads/GROOVY_2_4_X Commit: bf259e9a5c900583f27b3913e403e35a60c8fc5d Parents: 1c58ba3 Author: Jochen Theodorou <[email protected]> Authored: Tue Nov 15 19:53:36 2016 +0100 Committer: Jochen Theodorou <[email protected]> Committed: Tue Nov 15 19:55:48 2016 +0100 ---------------------------------------------------------------------- .../stdclasses/BigDecimalCachedClass.java | 8 +++-- .../groovy/vmplugin/v7/TypeTransformers.java | 32 ++++++++++++++------ src/test/groovy/PrimitiveTypesTest.groovy | 17 ++++++++++- 3 files changed, 44 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/bf259e9a/src/main/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java b/src/main/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java index 2a447c4..e98f6b9 100644 --- a/src/main/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java +++ b/src/main/org/codehaus/groovy/reflection/stdclasses/BigDecimalCachedClass.java @@ -18,9 +18,9 @@ */ package org.codehaus.groovy.reflection.stdclasses; -import org.codehaus.groovy.reflection.ClassInfo; - import java.math.BigDecimal; +import java.math.BigInteger; +import org.codehaus.groovy.reflection.ClassInfo; /** * @author Alex.Tkachman @@ -37,6 +37,10 @@ public class BigDecimalCachedClass extends DoubleCachedClass { public Object coerceArgument(Object argument) { if (argument instanceof BigDecimal) { return argument; + } else if (argument instanceof Long) { + return new BigDecimal((Long) argument); + } else if (argument instanceof BigInteger) { + return new BigDecimal((BigInteger) argument); } if (argument instanceof Number) { http://git-wip-us.apache.org/repos/asf/groovy/blob/bf259e9a/src/main/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java b/src/main/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java index c64abe1..4764f52 100644 --- a/src/main/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java +++ b/src/main/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java @@ -22,7 +22,6 @@ import groovy.lang.Closure; import groovy.lang.GString; import groovy.lang.GroovyObject; import groovy.util.ProxyGenerator; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -34,7 +33,6 @@ import java.math.BigInteger; import java.util.Collections; import java.util.List; import java.util.Map; - import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass; import org.codehaus.groovy.runtime.ConvertedClosure; @@ -49,8 +47,9 @@ public class TypeTransformers { private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); private static final MethodHandle TO_STRING, TO_BYTE, TO_INT, TO_LONG, TO_SHORT, - TO_FLOAT, TO_DOUBLE, TO_BIG_INT, TO_BIG_DEC, AS_ARRAY, - TO_REFLECTIVE_PROXY, TO_GENERATED_PROXY, TO_SAMTRAIT_PROXY; + TO_FLOAT, TO_DOUBLE, TO_BIG_INT, AS_ARRAY, + TO_REFLECTIVE_PROXY, TO_GENERATED_PROXY, TO_SAMTRAIT_PROXY, + DOUBLE_TO_BIG_DEC, DOUBLE_TO_BIG_DEC_WITH_CONVERSION, LONG_TO_BIG_DEC, BIG_INT_TO_BIG_DEC; static { try { TO_STRING = LOOKUP.findVirtual(Object.class, "toString", MethodType.methodType(String.class)); @@ -62,13 +61,18 @@ public class TypeTransformers { TO_DOUBLE = LOOKUP.findVirtual(Number.class, "doubleValue", MethodType.methodType(Double.TYPE)); // BigDecimal conversion is done by using the double value - // if the given number. - MethodHandle tmp = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, Double.TYPE)); - TO_BIG_DEC = MethodHandles.filterReturnValue(TO_DOUBLE, tmp); + DOUBLE_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, Double.TYPE)); + DOUBLE_TO_BIG_DEC_WITH_CONVERSION = MethodHandles.filterReturnValue(TO_DOUBLE, DOUBLE_TO_BIG_DEC); + + // BigDecimal conversion is done by using the double value + LONG_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, Long.TYPE)); + + // BigDecimal conversion is done by using the double value + BIG_INT_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, BigInteger.class)); + // BigInteger conversion is done by using the string representation - // if the given number - tmp = LOOKUP.findConstructor(BigInteger.class, MethodType.methodType(Void.TYPE, String.class)); + MethodHandle tmp = LOOKUP.findConstructor(BigInteger.class, MethodType.methodType(Void.TYPE, String.class)); TO_BIG_INT = MethodHandles.filterReturnValue(TO_STRING, tmp); // generic array to array conversion @@ -220,7 +224,15 @@ public class TypeTransformers { } else if (param == BigInteger.class) { return TO_BIG_INT; } else if (param == BigDecimal.class) { - return TO_BIG_DEC; + if (arg instanceof Double) { + return DOUBLE_TO_BIG_DEC; + } else if (arg instanceof Long) { + return LONG_TO_BIG_DEC; + } else if (arg instanceof BigInteger) { + return BIG_INT_TO_BIG_DEC; + } else { + return DOUBLE_TO_BIG_DEC_WITH_CONVERSION; + } } else if (param == Short.class) { return TO_SHORT; } else { http://git-wip-us.apache.org/repos/asf/groovy/blob/bf259e9a/src/test/groovy/PrimitiveTypesTest.groovy ---------------------------------------------------------------------- diff --git a/src/test/groovy/PrimitiveTypesTest.groovy b/src/test/groovy/PrimitiveTypesTest.groovy index 66aadf7..bbc2f90 100644 --- a/src/test/groovy/PrimitiveTypesTest.groovy +++ b/src/test/groovy/PrimitiveTypesTest.groovy @@ -78,7 +78,22 @@ class PrimitiveTypesTest extends GroovyTestCase { assert getNextShort((Short) 1) == 2 assert 3 == getNextShort((Short) 2) } - + + void testLong2BigDecimal() { + long l = Long.MAX_VALUE + assert l == testMethod(l).longValueExact() + } + + void testBigInteger2BigDecimal() { + BigInteger big = new BigInteger(Long.MAX_VALUE) + assert big.longValueExact() == testMethod(big).longValueExact() + } + + private testMethod(BigDecimal bd) { + return bd; + } + + static void main(args) { new PrimitiveTypesTest().testPrimitiveTypes() }
