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/04/13 16:42:02 UTC

[groovy] branch GROOVY_4_0_X updated (4c7e13cc43 -> a4dac87444)

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

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


 discard 4c7e13cc43 do not write shared `ClassNode` instances
 discard 204149ccc8 Trivial refactoring: reuse `ArrayTypeUtils.dimension`
     new 8afa3dc17b do not write shared `ClassNode` instances
     new a4dac87444 GROOVY-11011: SC: apply array flow type

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (4c7e13cc43)
            \
             N -- N -- N   refs/heads/GROOVY_4_0_X (a4dac87444)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 2 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:
 src/main/groovy/groovy/util/FileTreeBuilder.groovy | 44 +++++------
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  4 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 10 ++-
 src/spec/test/builder/FileTreeBuilderTest.groovy   | 13 +++-
 src/test/groovy/util/FileTreeBuilderTest.groovy    | 85 +++++++++++++---------
 5 files changed, 88 insertions(+), 68 deletions(-)


[groovy] 01/02: do not write shared `ClassNode` instances

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

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

commit 8afa3dc17b84cefc2280750ab1bf4e317552cbf0
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Apr 12 15:23:07 2023 -0500

    do not write shared `ClassNode` instances
---
 .../java/org/codehaus/groovy/classgen/ExtendedVerifier.java | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 14810acedc..1c857607cf 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -172,11 +172,14 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport {
         extractTypeUseAnnotations(node.getAnnotations(), node.getReturnType(), METHOD_TARGET);
     }
 
-    private void visitTypeAnnotations(ClassNode node) {
-        if (Boolean.TRUE.equals(node.getNodeMetaData(EXTENDED_VERIFIER_SEEN))) return;
-        node.putNodeMetaData(EXTENDED_VERIFIER_SEEN, Boolean.TRUE);
-        visitAnnotations(node, node.getTypeAnnotations(), TYPE_PARAMETER_TARGET);
-        visitGenericsTypeAnnotations(node);
+    private void visitTypeAnnotations(final ClassNode node) {
+        if ((node.isRedirectNode() || node.isPrimaryClassNode())
+                && !Boolean.TRUE.equals(node.getNodeMetaData(EXTENDED_VERIFIER_SEEN))) {
+            node.putNodeMetaData(EXTENDED_VERIFIER_SEEN, Boolean.TRUE); // one-time look
+
+            visitAnnotations(node, node.getTypeAnnotations(), TYPE_PARAMETER_TARGET);
+            visitGenericsTypeAnnotations(node);
+        }
     }
 
     private void visitGenericsTypeAnnotations(ClassNode node) {


[groovy] 02/02: GROOVY-11011: SC: apply array flow type

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

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

commit a4dac87444935ec5c2f96ca0cd42cb84cf1ce4f6
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Apr 13 10:51:09 2023 -0500

    GROOVY-11011: SC: apply array flow type
---
 src/main/groovy/groovy/util/FileTreeBuilder.groovy | 44 +++++------
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  4 +-
 src/spec/test/builder/FileTreeBuilderTest.groovy   | 13 +++-
 src/test/groovy/util/FileTreeBuilderTest.groovy    | 85 +++++++++++++---------
 4 files changed, 82 insertions(+), 64 deletions(-)

diff --git a/src/main/groovy/groovy/util/FileTreeBuilder.groovy b/src/main/groovy/groovy/util/FileTreeBuilder.groovy
index af41a6ce28..b96a2a6287 100644
--- a/src/main/groovy/groovy/util/FileTreeBuilder.groovy
+++ b/src/main/groovy/groovy/util/FileTreeBuilder.groovy
@@ -18,7 +18,10 @@
  */
 package groovy.util
 
+import groovy.transform.AutoFinal
 import groovy.transform.CompileStatic
+import groovy.transform.stc.ClosureParams
+import groovy.transform.stc.FromString
 
 /**
  * A builder dedicated at generating a file directory structure from a
@@ -70,6 +73,7 @@ import groovy.transform.CompileStatic
  *
  * @since 2.4.2
  */
+@AutoFinal
 @CompileStatic
 class FileTreeBuilder {
 
@@ -117,13 +121,9 @@ class FileTreeBuilder {
      * @param spec closure for generating the file contents
      * @return the created file
      */
-    File file(String name, @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) {
+    File file(String name, @ClosureParams(value = FromString, options = 'File') @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) {
         def file = new File(baseDir, name)
-        def clone = (Closure) spec.clone()
-        clone.delegate = file
-        clone.resolveStrategy = Closure.DELEGATE_FIRST
-        clone(file)
-        file
+        file.tap(spec)
     }
 
     /**
@@ -132,25 +132,26 @@ class FileTreeBuilder {
      * @return the created directory
      */
     File dir(String name) {
-        def f = new File(baseDir, name)
-        f.mkdirs()
-        f
+        def file = new File(baseDir, name)
+        file.mkdirs()
+        file
     }
 
     /**
      * Creates a new directory and allows to specify a subdirectory structure using the closure as a specification
      * @param name name of the directory to be created
-     * @param cl specification of the subdirectory structure
+     * @param spec specification of the subdirectory structure
      * @return the created directory
      */
-    File dir(String name, @DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure cl) {
+    File dir(String name, @DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure spec) {
         def oldBase = baseDir
         def newBase = dir(name)
         try {
             baseDir = newBase
-            cl.delegate = this
-            cl.resolveStrategy = Closure.DELEGATE_FIRST
-            cl()
+            def clone = (Closure) spec.clone()
+            clone.delegate = this
+            clone.resolveStrategy = Closure.DELEGATE_FIRST
+            clone()
         } finally {
             baseDir = oldBase
         }
@@ -165,19 +166,18 @@ class FileTreeBuilder {
         baseDir
     }
 
-    @SuppressWarnings('Instanceof')
-    def methodMissing(String name, args) {
-        if (args instanceof Object[] && ((Object[]) args).length == 1) {
-            def arg = ((Object[]) args)[0]
+    def methodMissing(String name, Object args) {
+        if (args instanceof Object[] && args.length == 1) {
+            def arg = args[0]
             if (arg instanceof Closure) {
-                dir(name, arg)
+                dir(name, (Closure<?>) arg)
             } else if (arg instanceof CharSequence) {
                 file(name, arg.toString())
             } else if (arg instanceof byte[]) {
-                file(name, arg)
+                file(name, (byte[]) arg)
             } else if (arg instanceof File) {
-                file(name, arg)
+                file(name, (File) arg)
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index e6b8923d13..2e28616b07 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -161,8 +161,7 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter {
         ClassNode receiverType = getPropertyOwnerType(receiver, isClassReceiver);
         if (receiverType.isArray() && "length".equals(propertyName)) {
             receiver.visit(controller.getAcg());
-            ClassNode arrayGetReturnType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
-            controller.getOperandStack().doGroovyCast(arrayGetReturnType);
+            controller.getOperandStack().doGroovyCast(receiverType); // GROOVY-5683, GROOVY-11011
             controller.getMethodVisitor().visitInsn(ARRAYLENGTH);
             controller.getOperandStack().replace(int_TYPE);
             return;
@@ -685,6 +684,7 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter {
         int m1 = operandStack.getStackLength();
         // visit receiver
         receiver.visit(controller.getAcg());
+        operandStack.doGroovyCast(rType); // GROOVY-11011
         // visit arguments as array index
         arguments.visit(controller.getAcg());
         operandStack.doGroovyCast(int_TYPE);
diff --git a/src/spec/test/builder/FileTreeBuilderTest.groovy b/src/spec/test/builder/FileTreeBuilderTest.groovy
index 83b29a9e95..323a051524 100644
--- a/src/spec/test/builder/FileTreeBuilderTest.groovy
+++ b/src/spec/test/builder/FileTreeBuilderTest.groovy
@@ -18,15 +18,19 @@
  */
 package builder
 
-import groovy.test.GroovyTestCase
+import org.junit.After
+import org.junit.Test
+
+final class FileTreeBuilderTest {
 
-class FileTreeBuilderTest extends GroovyTestCase {
     File tmpDir
 
+    @After
     void tearDown() {
         tmpDir.deleteDir()
     }
 
+    @Test
     void testFileTreeBuilder() {
         // tag::example[]
         tmpDir = File.createTempDir()
@@ -51,6 +55,7 @@ class FileTreeBuilderTest extends GroovyTestCase {
          // end::example_assert[]
     }
 
+    @Test
     void testFileTreeBuilderShortHandSyntax() {
         // tag::shorthand_syntax[]
         tmpDir = File.createTempDir()
@@ -73,5 +78,5 @@ class FileTreeBuilderTest extends GroovyTestCase {
          assert new File(tmpDir, '/src/main/groovy/Foo.groovy').text == 'println "Hello"'
          assert new File(tmpDir, '/src/test/groovy/FooTest.groovy').text == 'class FooTest extends groovy.test.GroovyTestCase {}'
          // end::shorthand_syntax_assert[]
-    }    
- }
+    }
+}
diff --git a/src/test/groovy/util/FileTreeBuilderTest.groovy b/src/test/groovy/util/FileTreeBuilderTest.groovy
index ebbd7f436c..ed40a7ab45 100644
--- a/src/test/groovy/util/FileTreeBuilderTest.groovy
+++ b/src/test/groovy/util/FileTreeBuilderTest.groovy
@@ -18,50 +18,57 @@
  */
 package groovy.util
 
-import groovy.test.GroovyTestCase
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
 
-class FileTreeBuilderTest extends GroovyTestCase {
-    File tmpDir
-    FileTreeBuilder builder
+final class FileTreeBuilderTest {
 
+    private File tmpDir
+    private FileTreeBuilder root
+
+    @Before
     void setUp() {
-        super.setUp()
         tmpDir = File.createTempDir()
-        builder = new FileTreeBuilder(tmpDir)
+        root = new FileTreeBuilder(tmpDir)
     }
 
+    @After
     void tearDown() {
         tmpDir.deleteDir()
-        builder = null
-        tmpDir = null
     }
 
+    @Test
     void testFileWithText() {
-        def file = builder.file('foo.txt','foo')
+        def file = root.file('foo.txt','foo')
         assert file.exists()
         assert file.text == 'foo'
     }
 
+    @Test
     void testFileWithBytes() {
-        def file = builder.file('foo.txt','foo'.getBytes('utf-8'))
+        def file = root.file('foo.txt','foo'.getBytes('utf-8'))
         assert file.exists()
         assert file.getText('utf-8') == 'foo'
     }
 
+    @Test
     void testFileWithFile() {
-        def f1 = builder.file('foo.txt', 'foo')
-        def f2 = builder.file('bar.txt', f1)
+        def f1 = root.file('foo.txt', 'foo')
+        def f2 = root.file('bar.txt', f1)
         assert f2.exists()
         assert f2.text == 'foo'
     }
 
+    @Test
     void testFileWithClosureSpec() {
-        def file = builder.file('foo.txt') { file ->
-            file << 'foo'
+        def file = root.file('foo.txt') { foo_txt ->
+            foo_txt << 'foo'
         }
         assert file.exists()
         assert file.text == 'foo'
-        def file2 = builder.file('foo.txt') {
+
+        def file2 = root.file('foo.txt') {
             withWriter('utf-8') {
                 it.write('foo')
             }
@@ -70,53 +77,59 @@ class FileTreeBuilderTest extends GroovyTestCase {
         assert file2.text == 'foo'
     }
 
+    @Test
     void testDir() {
-        def dir = builder.dir('sub')
-        assert dir.directory
-        assert dir.parentFile == builder.baseDir
+        def dir = root.dir('sub')
+        assert dir.isDirectory()
+        assert dir.name == 'sub'
+        assert dir.parentFile == root.baseDir
     }
 
+    @Test
     void testDirWithClosure() {
         File f = null
-        def dir = builder.dir('sub') {
+        def dir = root.dir('sub') {
             f = file('foo.txt','foo')
         }
-        assert dir.directory
-        assert dir.parentFile == builder.baseDir
+        assert dir.isDirectory()
+        assert dir.parentFile == root.baseDir
         assert f.text == 'foo'
         assert f.parentFile == dir
     }
 
+    @Test
     void testCall() {
-        File s1=null,s2=null,f1=null,f2=null
-        builder {
-            s1=dir('sub1') {
-                f1=file('foo.txt','foo')
+        File s1, s2, f1, f2
+        root {
+            s1 = dir('sub1') {
+                f1 = file('foo.txt','foo')
             }
-            s2=dir('sub2') {
-                f2=file('bar.txt', 'bar')
+            s2 = dir('sub2') {
+                f2 = file('bar.txt', 'bar')
             }
         }
         assert f1.text == 'foo'
         assert f2.text == 'bar'
         assert f1.parentFile == s1
         assert f2.parentFile == s2
-        assert s1.parentFile == builder.baseDir
-        assert s2.parentFile == builder.baseDir
+        assert s1.parentFile == root.baseDir
+        assert s2.parentFile == root.baseDir
     }
 
+    @Test
     void testCreateDirWithMethodMissing() {
-        File dir = builder.dir {}
-        assert dir.directory
+        File dir = root.dir({}) // not dir(String) or dir(String,Closure)
+        assert dir.isDirectory()
         assert dir.name == 'dir'
-        assert dir.parentFile == builder.baseDir
+        assert dir.parentFile == root.baseDir
     }
 
+    @Test
     void testCreateFileWithMethodMissing() {
-        File f1 = builder.'foo.txt'('foo')
-        File f2 = builder.'bar.txt'('foo'.getBytes('utf-8'))
-        File f3 = builder.'baz.txt'(f2)
-        [f1,f2,f3].each {
+        File f1 = root.'foo.txt'('foo')
+        File f2 = root.'bar.txt'('foo'.getBytes('utf-8'))
+        File f3 = root.'baz.txt'(f2)
+        [f1, f2, f3].each {
             assert it.exists()
             assert it.getText('utf-8') == 'foo'
         }