You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/08/19 03:37:29 UTC

[groovy] branch GROOVY_4_0_X updated (901373310f -> c5121849bc)

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

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


    from 901373310f GROOVY-7247: STC: support spread-map expression
     new bd45d5b860 GROOVY-10710: operator == is slow when comparing primitive arrays and lists (port to 4_0_X)
     new 923238f731 GROOVY-10713 Document ClassCodeExpressionTransformer limitation when dealing with Closure.
     new c5121849bc GROOVY-10710: operator == is slow when comparing primitive arrays and lists

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../groovy/ast/ClassCodeExpressionTransformer.java |  21 +++
 .../groovy/runtime/DefaultGroovyMethods.java       |  16 +-
 .../typehandling/DefaultTypeTransformation.java    | 181 ++++++++++++++++++++-
 .../DefaultTypeTransformationTest.groovy           |  22 +++
 4 files changed, 230 insertions(+), 10 deletions(-)


[groovy] 03/03: GROOVY-10710: operator == is slow when comparing primitive arrays and lists

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c5121849bcbaea314006c3b387aa16d451643617
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Aug 16 22:03:47 2022 +1000

    GROOVY-10710: operator == is slow when comparing primitive arrays and lists
---
 .../groovy/ast/ClassCodeExpressionTransformer.java | 28 ++++++++++------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
index 7f04f80bda..5df1c81b4e 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
@@ -43,26 +43,24 @@ import java.util.Map;
 public abstract class ClassCodeExpressionTransformer extends ClassCodeVisitorSupport implements ExpressionTransformer {
 
     /**
-     * <strong>GOTCHA</strong>: This method does not visit Expressions within Closures, for historical
-     * reason.  If you want those Expressions to be visited, you can do this:
+     * <strong>NOTE</strong>: This method does not visit Expressions within Closures,
+     * for performance and historical reasons.
+     * If you want those Expressions to be visited, you can do this:
      * <pre>
      * {@code
      * public class YourTransformer extends ClassCodeExpressionTransformer {
-     *  ...
+     *   ...
      *
-     *  @Override
-     *  public Expression transform(final Expression expr) {
-     *    if (expr instanceof ClosureExpression) {
-     *      expr.visit(this);
+     *   @Override
+     *   public Expression transform(final Expression expr) {
+     *     if (expr instanceof ClosureExpression) {
+     *       expr.visit(this);
      *
-     *      return expr;
-     *    }
-     *
-     *    // ... your custom instanceof + expression transformation
-     *    // ...
-     *  }
-     * }
-     * }
+     *       return expr;
+     *     }
+     *     // ...
+     *   }
+     * }}
      * </pre>
      */
     @Override


[groovy] 02/03: GROOVY-10713 Document ClassCodeExpressionTransformer limitation when dealing with Closure.

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 923238f7313f950922babb870ba7f70a882c796d
Author: Yih Tsern <si...@yahoo.com>
AuthorDate: Fri Aug 12 01:34:54 2022 +0800

    GROOVY-10713 Document ClassCodeExpressionTransformer limitation when dealing with Closure.
---
 .../groovy/ast/ClassCodeExpressionTransformer.java | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
index 4e17a10384..7f04f80bda 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
@@ -42,6 +42,29 @@ import java.util.Map;
  */
 public abstract class ClassCodeExpressionTransformer extends ClassCodeVisitorSupport implements ExpressionTransformer {
 
+    /**
+     * <strong>GOTCHA</strong>: This method does not visit Expressions within Closures, for historical
+     * reason.  If you want those Expressions to be visited, you can do this:
+     * <pre>
+     * {@code
+     * public class YourTransformer extends ClassCodeExpressionTransformer {
+     *  ...
+     *
+     *  @Override
+     *  public Expression transform(final Expression expr) {
+     *    if (expr instanceof ClosureExpression) {
+     *      expr.visit(this);
+     *
+     *      return expr;
+     *    }
+     *
+     *    // ... your custom instanceof + expression transformation
+     *    // ...
+     *  }
+     * }
+     * }
+     * </pre>
+     */
     @Override
     public Expression transform(Expression expr) {
         if (expr == null) return null;


[groovy] 01/03: GROOVY-10710: operator == is slow when comparing primitive arrays and lists (port to 4_0_X)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit bd45d5b86033b38c427df6a14646884f1760d674
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sun Aug 14 23:10:08 2022 +1000

    GROOVY-10710: operator == is slow when comparing primitive arrays and lists (port to 4_0_X)
---
 .../groovy/runtime/DefaultGroovyMethods.java       |  16 +-
 .../typehandling/DefaultTypeTransformation.java    | 181 ++++++++++++++++++++-
 .../DefaultTypeTransformationTest.groovy           |  22 +++
 3 files changed, 209 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 9402610ac8..c5e9b65a92 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -14975,7 +14975,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Byte> toSet(byte[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -14988,7 +14988,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Boolean> toSet(boolean[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15001,7 +15001,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Character> toSet(char[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15014,7 +15014,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Short> toSet(short[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15027,7 +15027,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Integer> toSet(int[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15040,7 +15040,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Long> toSet(long[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15053,7 +15053,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Float> toSet(float[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
@@ -15066,7 +15066,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      */
     @SuppressWarnings("unchecked")
     public static Set<Double> toSet(double[] array) {
-        return toSet(DefaultTypeTransformation.primitiveArrayToList(array));
+        return toSet(DefaultTypeTransformation.primitiveArrayToUnmodifiableList(array));
     }
 
     /**
diff --git a/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java b/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
index ac816bdf57..e19400fc31 100644
--- a/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
+++ b/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java
@@ -46,8 +46,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.Supplier;
@@ -559,6 +561,181 @@ public class DefaultTypeTransformation {
         return list;
     }
 
+    /**
+     * Allows conversion of arrays into an immutable List view
+     *
+     * @param array an array
+     * @return a List view of the array
+     */
+    public static List primitiveArrayToUnmodifiableList(Object array) {
+        return new ArrayToUnmodifiableListAdapter(array);
+    }
+
+    static class ArrayToUnmodifiableListAdapter implements List {
+        private Object delegate;
+
+        public ArrayToUnmodifiableListAdapter(Object delegate) {
+            Objects.requireNonNull(delegate);
+            this.delegate = delegate;
+        }
+
+        @Override
+        public int size() {
+            return Array.getLength(delegate);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return size() == 0;
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            for (Object next : this) {
+                if (next.equals(o)) return true;
+            }
+            return false;
+        }
+
+        private class Itr implements Iterator {
+            private int idx = 0;
+
+            @Override
+            public boolean hasNext() {
+                return idx < size();
+            }
+
+            @Override
+            public Object next() {
+                return get(idx++);
+            }
+        }
+
+        @Override
+        public Iterator iterator() {
+            return new Itr();
+        }
+
+        @Override
+        public Object get(int index) {
+            Object item = Array.get(delegate, index);
+            if (item != null && item.getClass().isArray() && item.getClass().getComponentType().isPrimitive()) {
+                item = primitiveArrayToUnmodifiableList(item);
+            }
+            return item;
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            int idx = 0;
+            boolean found = false;
+            while (!found && idx < size()) {
+                found = get(idx).equals(o);
+                if (!found) idx++;
+            }
+            return found ? idx : -1;
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            int idx = size() - 1;
+            boolean found = false;
+            while (!found && idx >= 0) {
+                found = get(idx).equals(o);
+                if (!found) idx--;
+            }
+            return found ? idx : -1;
+        }
+
+        @Override
+        public boolean containsAll(Collection coll) {
+            for (Object next : coll) {
+                if (!contains(next)) return false;
+            }
+            return true;
+        }
+
+        @Override
+        public ListIterator listIterator() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ListIterator listIterator(int index) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public List subList(int fromIndex, int toIndex) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object[] toArray() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object[] toArray(Object[] a) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object set(int index, Object element) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void add(int index, Object element) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object remove(int index) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean addAll(int index, Collection c) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean add(Object o) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean addAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean removeAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean retainAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean removeIf(Predicate filter) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
     public static Object[] primitiveArrayBox(Object array) {
         int size = Array.getLength(array);
         Object[] ret = (Object[]) Array.newInstance(ReflectionCache.autoboxType(array.getClass().getComponentType()), size);
@@ -661,10 +838,10 @@ public class DefaultTypeTransformation {
             return compareArrayEqual(left, right);
         }
         if (leftClass.isArray() && leftClass.getComponentType().isPrimitive()) {
-            left = primitiveArrayToList(left);
+            left = primitiveArrayToUnmodifiableList(left);
         }
         if (rightClass.isArray() && rightClass.getComponentType().isPrimitive()) {
-            right = primitiveArrayToList(right);
+            right = primitiveArrayToUnmodifiableList(right);
         }
         if (left instanceof Object[] && right instanceof List) {
             return DefaultGroovyMethods.equals((Object[]) left, (List) right);
diff --git a/src/test/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformationTest.groovy b/src/test/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformationTest.groovy
index 5054fb57a3..a889287f71 100644
--- a/src/test/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformationTest.groovy
@@ -234,6 +234,28 @@ final class DefaultTypeTransformationTest {
         assert      G == N
     }
 
+    @Test
+    void testPrimitiveArrayToUnmodifiableList() {
+        int[] nums = [1, 3, 3, 5]
+        def numList = DefaultTypeTransformation.primitiveArrayToUnmodifiableList(nums)
+        assert numList.get(1) == 3
+        assert numList.contains(1)
+        assert numList.contains(3)
+        assert numList.contains(5)
+        assert !numList.contains(2)
+        assert numList.indexOf(1) == 0
+        assert numList.indexOf(3) == 1
+        assert numList.indexOf(5) == 3
+        assert numList.indexOf(2) == -1
+        assert numList.lastIndexOf(2) == -1
+        assert numList.lastIndexOf(3) == 2
+        assert numList.containsAll([5,3,1])
+        assert !numList.containsAll([5,3,2])
+        assert !numList.containsAll([4,3,1])
+        assert !numList.isEmpty()
+        assert numList.size() == 4
+    }
+
     //--------------------------------------------------------------------------
 
     private static void checkCompareToSymmetricSmallerThan(a, b) {