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:04 UTC
[groovy] 02/02: GROOVY-11011: SC: apply array flow type
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'
}