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

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

commit 5bd68c5bb61197f2535abb9918c406894556f6a3
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Tue Jul 15 12:19:43 2025 -0500

    minor items
---
 .../transform/RecordTypeASTTransformation.java     |  24 ++--
 .../TupleConstructorASTTransformation.java         |   9 +-
 .../org/codehaus/groovy/classgen/RecordTest.groovy | 122 +++++++++++++--------
 3 files changed, 90 insertions(+), 65 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java 
b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
index 09e7d579a0..2a344463ce 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
@@ -212,17 +212,17 @@ public class RecordTypeASTTransformation extends 
AbstractASTTransformation imple
             isAtLeastJDK16 = isAtLeast(targetBytecode, 
CompilerConfiguration.JDK16);
             message = "Expecting JDK16+ but found " + targetBytecode;
         }
+        List<PropertyNode> pList = 
Collections.unmodifiableList(getInstanceProperties(cNode));
         boolean isNative = (isAtLeastJDK16 && mode != RecordTypeMode.EMULATE);
         if (isNative) {
-            String sName = cNode.getUnresolvedSuperClass().getName();
+            String scName = cNode.getUnresolvedSuperClass().getName();
             // don't expect any parent to be set at this point but we only 
check at grammar
             // level when using the record keyword so do a few more sanity 
checks here
-            if (!sName.equals(OBJECT) && !sName.equals(RECORD_CLASS_NAME)) {
-                addError("Invalid superclass for native record found: " + 
sName, cNode);
+            if (!scName.equals(OBJECT) && !scName.equals(RECORD_CLASS_NAME)) {
+                addError("Invalid superclass for native record found: " + 
scName, cNode);
             }
             
cNode.setSuperClass(compilationUnit.getClassNodeResolver().resolveName(RECORD_CLASS_NAME,
 compilationUnit).getClassNode());
             cNode.setModifiers(cNode.getModifiers() | Opcodes.ACC_RECORD);
-            final List<PropertyNode> pList = getInstanceProperties(cNode);
             if (!pList.isEmpty()) {
                 cNode.setRecordComponents(new ArrayList<>());
             }
@@ -246,18 +246,18 @@ public class RecordTypeASTTransformation extends 
AbstractASTTransformation imple
         makeClassFinal(this, cNode);
         makeInnerRecordStatic(cNode);
 
-        final List<PropertyNode> pList = getInstanceProperties(cNode);
         for (PropertyNode pNode : pList) {
             adjustPropertyForShallowImmutability(cNode, pNode, handler);
             pNode.setModifiers(pNode.getModifiers() | ACC_FINAL);
         }
-        final List<FieldNode> fList = cNode.getFields();
+        List<FieldNode> fList = cNode.getFields();
         for (FieldNode fNode : fList) {
             ensureNotPublic(this, cName, fNode);
         }
+
         // 0L serialVersionUID by default
         if (cNode.getDeclaredField("serialVersionUID") == null) {
-            cNode.addField("serialVersionUID", ACC_PRIVATE | ACC_STATIC | 
ACC_FINAL, long_TYPE, constX(0L));
+            cNode.addField("serialVersionUID", ACC_PRIVATE | ACC_STATIC | 
ACC_FINAL, long_TYPE, constX(0L, true));
         }
 
         if (!hasAnnotation(cNode, ToStringASTTransformation.MY_TYPE)) {
@@ -282,11 +282,11 @@ public class RecordTypeASTTransformation extends 
AbstractASTTransformation imple
         }
 
         if (hasAnnotation(cNode, TupleConstructorASTTransformation.MY_TYPE)) {
-            AnnotationNode tupleCons = 
cNode.getAnnotations(TupleConstructorASTTransformation.MY_TYPE).get(0);
-            if (unsupportedTupleAttribute(tupleCons, "excludes")) return;
-            if (unsupportedTupleAttribute(tupleCons, "includes")) return;
-            if (unsupportedTupleAttribute(tupleCons, "includeProperties")) 
return;
-            if (unsupportedTupleAttribute(tupleCons, "includeSuperFields")) 
return;
+            AnnotationNode tupleConstructor = 
cNode.getAnnotations(TupleConstructorASTTransformation.MY_TYPE).get(0);
+            if (unsupportedTupleAttribute(tupleConstructor, "excludes")) 
return;
+            if (unsupportedTupleAttribute(tupleConstructor, "includes")) 
return;
+            if (unsupportedTupleAttribute(tupleConstructor, 
"includeProperties")) return;
+            if (unsupportedTupleAttribute(tupleConstructor, 
"includeSuperFields")) return;
         }
 
         if (options != null && memberHasValue(options, COPY_WITH, 
Boolean.TRUE) && !hasDeclaredMethod(cNode, COPY_WITH, 1)) {
diff --git 
a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
 
b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
index e6d6fc4746..e3b226167e 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
@@ -208,8 +208,7 @@ public class TupleConstructorASTTransformation extends 
AbstractASTTransformation
         if (pre != null) {
             superInPre = copyStatementsWithSuperAdjustment(pre, preBody);
             if (superInPre && callSuper) {
-                xform.addError("Error during " + MY_TYPE_NAME + " processing, 
can't have a super call in 'pre' " +
-                        "closure and also 'callSuper' enabled", cNode);
+                xform.addError("Error during " + MY_TYPE_NAME + " processing, 
can't have a super call in 'pre' closure and also 'callSuper' enabled", cNode);
             }
         }
 
@@ -268,7 +267,7 @@ public class TupleConstructorASTTransformation extends 
AbstractASTTransformation
         }
 
         int modifiers = getVisibility(anno, cNode, ConstructorNode.class, 
ACC_PUBLIC);
-        Parameter[] signature = params.toArray(Parameter.EMPTY_ARRAY);
+        Parameter[] signature = params.toArray(Parameter[]::new);
         if (cNode.getDeclaredConstructor(signature) != null) {
             if (sourceUnit != null) {
                 String warning = String.format(
@@ -287,15 +286,13 @@ public class TupleConstructorASTTransformation extends 
AbstractASTTransformation
             if (namedVariant) {
                 BlockStatement inner = new BlockStatement();
                 Parameter mapParam = 
param(ClassHelper.MAP_TYPE.getPlainNodeReference(), NAMED_ARGS);
-                List<Parameter> genParams = new ArrayList<>();
-                genParams.add(mapParam);
                 ArgumentListExpression args = new ArgumentListExpression();
                 List<String> propNames = new ArrayList<>();
                 Map<Parameter, Expression> seen = new HashMap<>();
                 for (Parameter p : params) {
                     if (!processImplicitNamedParam(xform, tupleCtor, mapParam, 
inner, args, propNames, p, false, seen)) return;
                 }
-                NamedVariantASTTransformation.createMapVariant(xform, 
tupleCtor, anno, mapParam, genParams, cNode, inner, args, propNames);
+                NamedVariantASTTransformation.createMapVariant(xform, 
tupleCtor, anno, mapParam, List.of(mapParam), cNode, inner, args, propNames);
             }
 
             if (sourceUnit != null && !body.isEmpty()) {
diff --git a/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy 
b/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy
index 2ebdc3c1ea..13a7dfb48e 100644
--- a/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy
+++ b/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy
@@ -28,7 +28,9 @@ import org.codehaus.groovy.control.ClassNodeResolver
 import org.codehaus.groovy.control.CompilationUnit
 import org.codehaus.groovy.control.CompilerConfiguration
 import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
-import org.junit.Test
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.CsvSource
 
 import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.isAtLeastJdk
@@ -37,6 +39,15 @@ import static org.junit.Assume.assumeTrue
 
 final class RecordTest {
 
+    private final GroovyShell shell = GroovyShell.withConfig {
+        imports {
+            star 'groovy.transform'
+            staticStar 'java.lang.reflect.Modifier'
+            staticMember 'groovy.test.GroovyAssert', 'shouldFail'
+            staticMember 'org.codehaus.groovy.ast.ClassHelper', 'make'
+        }
+    }
+
     @Test
     void testNativeRecordOnJDK16_groovy() {
         assumeTrue(isAtLeastJdk('16.0'))
@@ -104,7 +115,7 @@ final class RecordTest {
                 import java.lang.annotation.*;
                 import java.util.*;
 
-                public record Person(@NotNull @NotNull2 @NotNull3 String name, 
int age, @NotNull2 @NotNull3 List<String> locations, String[] titles) {}
+                record Person(@NotNull @NotNull2 @NotNull3 String name, int 
age, @NotNull2 @NotNull3 List<String> locations, String[] titles) {}
 
                 @Retention(RetentionPolicy.RUNTIME)
                 @Target({ElementType.RECORD_COMPONENT})
@@ -213,17 +224,6 @@ final class RecordTest {
         }
     }
 
-    
//--------------------------------------------------------------------------
-
-    private final GroovyShell shell = GroovyShell.withConfig {
-        imports {
-            star 'groovy.transform'
-            staticStar 'java.lang.reflect.Modifier'
-            staticMember 'groovy.test.GroovyAssert', 'shouldFail'
-            staticMember 'org.codehaus.groovy.ast.ClassHelper', 'make'
-        }
-    }
-
     @Test
     void testNativeRecordOnJDK16ByDefault() {
         assumeTrue(isAtLeastJdk('16.0'))
@@ -524,45 +524,73 @@ final class RecordTest {
         '''
     }
 
-    @Test
-    void testTupleConstructor() {
-        for (pair in [['RecordType', 'TupleConstructor'], ['defaults=false', 
'defaultsMode=DefaultsMode.OFF']].combinations()) {
-            assertScript shell, """
-                @${pair[0]}(${pair[1]}, namedVariant=false)
-                record Person(String name, Date dob) {
-                    //Person(String,Date)
-                    //Person(String)  no!
-                    //Person(Map)     no!
-                    //Person()        no!
-
-                    public Person { // implies @TupleConstructor(pre={...})
-                        assert name.length() > 1
-                    }
-
-                    Person(Person that) {
-                        this(that.name(), that.dob())
-                    }
+    @ParameterizedTest @CsvSource([
+        'RecordType, defaults=false',
+        'TupleConstructor, defaults=false',
+        'RecordType, defaultsMode=DefaultsMode.OFF',
+        'TupleConstructor, defaultsMode=DefaultsMode.OFF'
+    ])
+    void testTupleConstructor(String type, String mode) {
+        assertScript shell, """
+            @$type($mode, namedVariant=false)
+            record Person(String name, Date dob) {
+                //Person(String,Date)
+                //Person(String)  no!
+                //Person(Map)     no!
+                //Person()        no!
+
+                public Person { // implies @TupleConstructor(pre={...})
+                    assert name.length() > 1
+                }
 
-                    //getAt(int i)
-                    //toList()
-                    //toMap()
+                Person(Person that) {
+                    this(that.name(), that.dob())
                 }
 
-                assert Person.declaredConstructors.length == 2 // copy and 
tuple
+                //getAt(int i)
+                //toList()
+                //toMap()
+            }
+
+            assert Person.declaredConstructors.length == 2 // copy and tuple
 
-                def person = new Person('Frank Grimes', new Date())
-                def doppel = new Person(person)
-                shouldFail {
-                    new Person(name:'Frank Grimes', dob:null)
-                }
-                shouldFail {
-                    new Person('Frank Grimes')
-                }
-                shouldFail {
-                    new Person()
+            def person = new Person('Frank Grimes', new Date())
+            def doppel = new Person(person)
+            shouldFail {
+                new Person(name:'Frank Grimes', dob:null)
+            }
+            shouldFail {
+                new Person('Frank Grimes')
+            }
+            shouldFail {
+                new Person()
+            }
+        """
+    }
+
+    @Test
+    void testMapConstructor() {
+        assertScript shell, '''import static java.time.Month.NOVEMBER as NOV
+
+            record Person(String name, LocalDate born) {
+                Person {
+                    assert name.length() > 1
                 }
-            """
-        }
+            }
+
+            def person = new Person(name: 'Frank Grimes', born: 
LocalDate.of(1955,11,5))
+            assert person.name() == 'Frank Grimes'
+            assert person.born().dayOfMonth == 5
+            assert person.born().month == NOV
+            assert person.born().year == 1955
+
+            shouldFail {
+                new Person(name:'', born:LocalDate.now())
+            }
+            shouldFail {
+                new Person(name:'John Doe')
+            }
+        '''
     }
 
     @Test

Reply via email to