This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit cca4515dc11ab13a8225f010cc7bc83a403b4e53
Author: Esko Toivonen <[email protected]>
AuthorDate: Wed Apr 7 17:48:08 2021 +0300

    GROOVY-9649: Make createRange create EmptyRanges when from != to
    
    Ranges like 0<..<1 should be EmptyRanges. One complicating fact is that
    ranges like 0<..<-1 can be used for list indexing, thus only ranges
    where from and to share the same sign (zeros and positives are
    considered equal) and their difference is one are treated as EmptyRanges.
---
 .../groovy/runtime/ScriptBytecodeAdapter.java      | 47 ++++++++++++++--------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java 
b/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
index 5161f65..fdd593d 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java
@@ -636,38 +636,53 @@ public class ScriptBytecodeAdapter {
     }
 
     public static List createRange(Object from, Object to, boolean 
exclusiveLeft, boolean exclusiveRight) throws Throwable {
+        if (exclusiveLeft && exclusiveRight) {
+            if (compareEqual(from, to)) {
+                return new EmptyRange((Comparable) from);
+            }
+            Object tmpFrom;
+            if (compareLessThan(from, to)) {
+                tmpFrom = invokeMethod0(ScriptBytecodeAdapter.class, from, 
"next");
+            } else {
+                tmpFrom = invokeMethod0(ScriptBytecodeAdapter.class, from, 
"previous");
+            }
+            // Create an empty range if the difference between from and to is 
one and they have the same sign. This
+            // means that range syntaxes like 5<..<6 will result in an empty 
range, but 0<..<-1 won't, since the latter
+            // is used in list indexing where negative indices count from the 
end towards the beginning. Note that
+            // positive numbers and zeros are considered to have the same sign 
to make ranges like 0<..<1 be EmptyRanges
+            int fromComp = compareTo(from, 0);
+            int toComp = compareTo(to, 0);
+            boolean sameSign = (fromComp >= 0 && toComp >= 0) || (fromComp < 0 
&& toComp < 0);
+            if (compareEqual(tmpFrom, to) && sameSign) {
+                return new EmptyRange((Comparable) from);
+            }
+        }
+        if ((exclusiveLeft || exclusiveRight) && compareEqual(from, to)) {
+            return new EmptyRange((Comparable) from);
+        }
         if (from instanceof Integer && to instanceof Integer) {
             int ifrom = (Integer) from;
             int ito = (Integer) to;
             if ((!exclusiveLeft && !exclusiveRight) || ifrom != ito) {
-                // Currently, empty ranges where from != to and the range is 
full exclusive (e.g. 0<..<-1) are
-                // constructed as IntRanges. This is because these ranges can 
still be used to index into lists.
+                // Currently, empty ranges where from != to, the range is full 
exclusive (e.g. 0<..<-1) and from and to
+                // have a different sign are constructed as IntRanges. This is 
because these ranges can still be used to
+                // index into lists.
                 return new IntRange(!exclusiveLeft, !exclusiveRight, ifrom, 
ito);
-            } // else fall through for EmptyRange
-        }
-        if ((exclusiveLeft || exclusiveRight) && compareEqual(from, to)) {
-            return new EmptyRange((Comparable) from);
+            }
         }
         if (from instanceof Number && to instanceof Number) {
             return new NumberRange(comparableNumber((Number) from), 
comparableNumber((Number) to), !exclusiveLeft, !exclusiveRight);
         }
-        Boolean greater = null;
+        // ObjectRange does not include information about inclusivity, so we 
need to consider it here
         if (exclusiveRight) {
-            greater = compareGreaterThan(from, to);
-            if (greater) {
+            if (compareGreaterThan(from, to)) {
                 to = invokeMethod0(ScriptBytecodeAdapter.class, to, "next");
             } else {
                 to = invokeMethod0(ScriptBytecodeAdapter.class, to, 
"previous");
             }
         }
         if (exclusiveLeft) {
-            if (greater == null) {
-                greater = compareGreaterThan(from, to);
-            }
-            if (compareEqual(from, to)) {
-                return new EmptyRange((Comparable) from);
-            }
-            if (greater) {
+            if (compareGreaterThan(from, to)) {
                 from = invokeMethod0(ScriptBytecodeAdapter.class, from, 
"previous");
             } else {
                 from = invokeMethod0(ScriptBytecodeAdapter.class, from, 
"next");

Reply via email to