You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2023/02/09 19:35:22 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-10319, GROOVY-10733: array clone

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

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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 509d224eb3 GROOVY-10319, GROOVY-10733: array clone
509d224eb3 is described below

commit 509d224eb38094b9fbf0381e1b6d94ad095021ef
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 9 13:27:18 2023 -0600

    GROOVY-10319, GROOVY-10733: array clone
    
    3_0_X backport
---
 .travis.yml                                        | 10 ++++-----
 .../org/codehaus/groovy/vmplugin/v8/Selector.java  | 16 ++++++++------
 .../stc/ArraysAndCollectionsSTCTest.groovy         |  3 +++
 .../groovy/transform/ImmutableTransformTest.groovy | 25 +++++++++++-----------
 4 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index f2a4448b2b..50044344c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,9 +25,9 @@ install:
 
 matrix:
   include:
-    - env: BC='legacy' FEATURE='17' TARGET_JAVA_HOME="/home/travis/openjdk$FEATURE" LICENSE='GPL'
+    - env: BC='legacy' FEATURE='17' TARGET_JAVA_HOME="$HOME/openjdk$FEATURE" LICENSE='GPL'
       jdk: openjdk11
-    - env: BC='legacy' FEATURE='16' TARGET_JAVA_HOME="/home/travis/openjdk$FEATURE" LICENSE='GPL'
+    - env: BC='legacy' FEATURE='16' TARGET_JAVA_HOME="$HOME/openjdk$FEATURE" LICENSE='GPL'
       jdk: openjdk11
     - env: BC='legacy'
       jdk: openjdk15
@@ -36,9 +36,9 @@ matrix:
     - env: BC='legacy'
       jdk: oraclejdk8
 
-    - env: BC='indy' FEATURE='17' TARGET_JAVA_HOME="/home/travis/openjdk$FEATURE" LICENSE='GPL'
+    - env: BC='indy' FEATURE='17' TARGET_JAVA_HOME="$HOME/openjdk$FEATURE" LICENSE='GPL'
       jdk: openjdk11
-    - env: BC='indy' FEATURE='16' TARGET_JAVA_HOME="/home/travis/openjdk$FEATURE" LICENSE='GPL'
+    - env: BC='indy' FEATURE='16' TARGET_JAVA_HOME="$HOME/openjdk$FEATURE" LICENSE='GPL'
       jdk: openjdk11
     - env: BC='indy'
       jdk: openjdk15
@@ -56,7 +56,7 @@ before_script:
 script:
   - ./gradlew -version
   - if [ "$TARGET_JAVA_HOME" != "" ]; then wget https://github.com/sormuras/bach/raw/master/install-jdk.sh -P /tmp/ && chmod 755 /tmp/install-jdk.sh; fi
-  - if [ "$TARGET_JAVA_HOME" != "" ]; then /tmp/install-jdk.sh --target "$TARGET_JAVA_HOME" --workspace "/home/travis/.cache/install-jdk" --feature "$FEATURE" --license "$LICENSE" --cacerts; fi
+  - if [ "$TARGET_JAVA_HOME" != "" ]; then /tmp/install-jdk.sh --target "$TARGET_JAVA_HOME" --workspace "$HOME/.cache/install-jdk" --feature "$FEATURE" --license "$LICENSE" --cacerts; fi
   - if [ "$BC" == "legacy" ]; then travis_wait 60 ./gradlew test -Ptarget.java.home=$TARGET_JAVA_HOME; elif [ "$BC" == "sonar" ]; then travis_wait 60 ./gradlew sonarqube -Dsonar.login=$SONAR_LOGIN -Pcoverage=true -x testWithIndy; else travis_wait 60 ./gradlew testWithIndy -Ptarget.java.home=$TARGET_JAVA_HOME; fi
 
 # As recommended in:
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index 41c2a3aaa0..d18abd31f8 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -639,19 +639,23 @@ public abstract class Selector {
                 cm = (CachedMethod) vmplugin.transformMetaMethod(mc, cm, sender);
                 isVargs = cm.isVargsMethod();
                 Method m = cm.getCachedMethod();
-                if (m.getParameterCount() == 1 && m.getName().equals("forName") && m.getDeclaringClass() == Class.class) {
-                    handle = MethodHandles.insertArguments(CLASS_FOR_NAME, 1, Boolean.TRUE, sender.getClassLoader());
-                } else {
-                    try {
+                try {
+                    String  methodName = m.getName();
+                    int parameterCount = m.getParameterCount();
+                    if (parameterCount == 0 && methodName.equals("clone") && m.getDeclaringClass() == Object.class && args[0].getClass().isArray()) {
+                        handle = MethodHandles.publicLookup().findVirtual(args[0].getClass(), "clone", MethodType.methodType(Object.class));
+                    } else if (parameterCount == 1 && methodName.equals("forName") && m.getDeclaringClass() == Class.class) {
+                        handle = MethodHandles.insertArguments(CLASS_FOR_NAME, 1, Boolean.TRUE, sender.getClassLoader());
+                    } else {
                         MethodHandles.Lookup lookup = LOOKUP;
                         if (!vmplugin.checkAccessible(lookup.lookupClass(), m.getDeclaringClass(), m.getModifiers(), false)) {
                             Method newLookup = vmplugin.getClass().getMethod("of", Class.class);
                             lookup = (MethodHandles.Lookup) newLookup.invoke(null, sender);
                         }
                         handle = lookup.unreflect(m);
-                    } catch (ReflectiveOperationException e) {
-                        throw new GroovyBugError(e);
                     }
+                } catch (ReflectiveOperationException e) {
+                    throw new GroovyBugError(e);
                 }
                 if (LOG_ENABLED) LOG.info("successfully unreflected cached method");
                 if (isStaticCategoryTypeMethod) {
diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index 690394cfde..b5a565cecc 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -619,6 +619,9 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
 
     // GROOVY-10319
     void testArrayClone() {
+        assertScript '''
+            assert (new int[9]).clone().length == 9
+        '''
         assertScript '''
             package p // must be in package for protected method check
 
diff --git a/src/test/org/codehaus/groovy/transform/ImmutableTransformTest.groovy b/src/test/org/codehaus/groovy/transform/ImmutableTransformTest.groovy
index 9ae1e14a1e..f664a2724b 100644
--- a/src/test/org/codehaus/groovy/transform/ImmutableTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/ImmutableTransformTest.groovy
@@ -112,13 +112,15 @@ class ImmutableTransformTest extends GroovyShellTestCase {
     @Test
     void testCloneableField() {
         def (originalDolly, lab) = evaluate("""
-            import groovy.transform.Immutable
+            import groovy.transform.*
 
+            @AutoClone
             class Dolly implements Cloneable {
                 String name
             }
 
-            @Immutable class Lab {
+            @Immutable
+            class Lab {
                 String name
                 Cloneable clone
             }
@@ -139,8 +141,8 @@ class ImmutableTransformTest extends GroovyShellTestCase {
 
     @Test
     void testCloneableFieldNotCloneableObject() {
-        def cls = shouldFail(CloneNotSupportedException) {
-            def objects = evaluate("""
+        shouldFail(CloneNotSupportedException) {
+            evaluate("""
                 import groovy.transform.Immutable
 
                 class Dolly {
@@ -156,8 +158,6 @@ class ImmutableTransformTest extends GroovyShellTestCase {
                 [dolly, new Lab(name: "Area 51", clone: dolly)]
             """)
         }
-
-        assert cls == 'Dolly'
     }
 
     @Test
@@ -165,19 +165,18 @@ class ImmutableTransformTest extends GroovyShellTestCase {
         def objects = evaluate("""
             import groovy.transform.Immutable
             @Immutable class HasList {
-                String[] letters
-                List nums
+                char[] letters
+                List   numbers
             }
-            def letters = 'A,B,C'.split(',')
-            def nums = [1, 2]
-            [new HasList(letters:letters, nums:nums),
-             new HasList(letters, nums)]
+            def letters = 'ABC'.toCharArray()
+            def numbers = [1, 2]
+            [new HasList(letters:letters, numbers:numbers), new HasList(letters, numbers)]
         """)
 
         assertEquals objects[0].hashCode(), objects[1].hashCode()
         assertEquals objects[0], objects[1]
         assert objects[0].letters.size() == 3
-        assert objects[0].nums.size() == 2
+        assert objects[0].numbers.size() == 2
     }
 
     @Test