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 2022/11/22 21:13:25 UTC

[groovy] branch master updated: GROOVY-8219: no trait fields in `@TupleConstructor(includeFields=true)`

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


The following commit(s) were added to refs/heads/master by this push:
     new 0d6eb1b70b GROOVY-8219: no trait fields in `@TupleConstructor(includeFields=true)`
0d6eb1b70b is described below

commit 0d6eb1b70b3341ea0c19313b988699dc8d1e5e7d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Nov 22 15:13:10 2022 -0600

    GROOVY-8219: no trait fields in `@TupleConstructor(includeFields=true)`
    
    without `allnames=true`
---
 .../codehaus/groovy/ast/tools/GeneralUtils.java    | 17 ++++---
 .../transform/AbstractASTTransformation.java       |  4 +-
 .../TupleConstructorASTTransformation.java         | 12 ++---
 .../{Groovy7584Bug.groovy => Groovy7584.groovy}    | 41 ++++++++--------
 .../transform/TupleConstructorTransformTest.groovy | 57 +++++++++++++++++++++-
 5 files changed, 95 insertions(+), 36 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
index 06edc9e3ee..c9a5bfee51 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
@@ -540,23 +540,24 @@ public class GeneralUtils {
         }
         if (includeFields) {
             for (FieldNode fNode : cNode.getFields()) {
-                if ((fNode.isStatic() && !includeStatic) || fNode.isSynthetic() || cNode.getProperty(fNode.getName()) != null || names.contains(fNode.getName())) {
+                if ((fNode.isStatic() && !includeStatic) || fNode.isSynthetic()) {
                     continue;
                 }
-
-                // internal field
-                if (fNode.getName().contains("$") && !allNames) {
+                if (fNode.isPrivate() && !cNode.equals(origType)) {
                     continue;
                 }
-
-                if (fNode.isPrivate() && !cNode.equals(origType)) {
+                String fName = fNode.getName();
+                if (names.contains(fName) || cNode.getProperty(fName) != null) {
+                    continue;
+                }
+                if (!allNames && (fName.contains("$") || fName.contains("__"))) { // "special"
                     continue;
                 }
                 if (fNode.isFinal() && fNode.getInitialExpression() != null && skipReadonly) {
                     continue;
                 }
-                result.add(new PropertyNode(fNode, fNode.getModifiers(), null, null));
-                names.add(fNode.getName());
+                names.add(fName);
+                result.add(new PropertyNode(fNode, fNode.getModifiers() & 0x1F, null, null));
             }
         }
         if (!(isObjectType(cNode)) && traverseSuperClasses && reverse) {
diff --git a/src/main/java/org/codehaus/groovy/transform/AbstractASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/AbstractASTTransformation.java
index 3e56632cf7..e47b3eeb61 100644
--- a/src/main/java/org/codehaus/groovy/transform/AbstractASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/AbstractASTTransformation.java
@@ -49,9 +49,9 @@ import java.util.List;
 import java.util.Map;
 
 import static groovy.transform.Undefined.isUndefined;
+import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.getInstanceNonPropertyFieldNames;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.getSuperNonPropertyFields;
-import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
 
 public abstract class AbstractASTTransformation implements ASTTransformation, ErrorCollecting {
     public static final ClassNode RETENTION_CLASSNODE = ClassHelper.makeWithoutCaching(Retention.class);
@@ -366,7 +366,7 @@ public abstract class AbstractASTTransformation implements ASTTransformation, Er
         }
         final List<String> pNames = new ArrayList<>();
         for (PropertyNode pNode : BeanUtils.getAllProperties(cNode, includeSuperProperties, includeStatic, allProperties)) {
-            pNames.add(pNode.getField().getName());
+            pNames.add(pNode.getName());
         }
         boolean result = true;
         if (includeFields || includeSuperFields) {
diff --git a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
index 396e8fdb1f..ad9fb5d88c 100644
--- a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
@@ -131,14 +131,14 @@ public class TupleConstructorASTTransformation extends AbstractASTTransformation
         if (parent instanceof ClassNode) {
             ClassNode cNode = (ClassNode) parent;
             if (!checkNotInterface(cNode, MY_TYPE_NAME)) return;
-            boolean includeFields = memberHasValue(anno, "includeFields", true);
-            boolean includeProperties = !memberHasValue(anno, "includeProperties", false);
-            boolean includeSuperFields = memberHasValue(anno, "includeSuperFields", true);
-            boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties", true);
-            boolean allProperties = memberHasValue(anno, "allProperties", true);
+            boolean includeFields = memberHasValue(anno, "includeFields", Boolean.TRUE);
+            boolean includeProperties = !memberHasValue(anno, "includeProperties", Boolean.FALSE);
+            boolean includeSuperFields = memberHasValue(anno, "includeSuperFields", Boolean.TRUE);
+            boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties", Boolean.TRUE);
+            boolean allProperties = memberHasValue(anno, "allProperties", Boolean.TRUE);
             List<String> excludes = getMemberStringList(anno, "excludes");
             List<String> includes = getMemberStringList(anno, "includes");
-            boolean allNames = memberHasValue(anno, "allNames", true);
+            boolean allNames = memberHasValue(anno, "allNames", Boolean.TRUE);
             if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME)) return;
             if (!checkPropertyList(cNode, includes, "includes", anno, MY_TYPE_NAME, includeFields, includeSuperProperties, allProperties, includeSuperFields, false))
                 return;
diff --git a/src/test/groovy/bugs/Groovy7584Bug.groovy b/src/test/groovy/bugs/Groovy7584.groovy
similarity index 63%
rename from src/test/groovy/bugs/Groovy7584Bug.groovy
rename to src/test/groovy/bugs/Groovy7584.groovy
index 42b65e20f9..c42431ffcb 100644
--- a/src/test/groovy/bugs/Groovy7584Bug.groovy
+++ b/src/test/groovy/bugs/Groovy7584.groovy
@@ -18,41 +18,44 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
+import org.junit.Test
 
-class Groovy7584Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy7584 {
+
+    @Test
     void testTraitFieldModifiersAreRetained() {
-        assertScript """
+        assertScript '''
+            import groovy.transform.ToString
             import static java.lang.reflect.Modifier.*
 
             trait User {
                 final String name = 'Foo'
-                public static final boolean loggedIn = true
-                private transient final int ANSWER = 42
+                final private transient int answer = 42
+                final public static boolean LOGGED_IN = true
             }
 
-            @groovy.transform.ToString(includeFields=true, includeNames=true)
-            class Person implements User { }
+            @ToString(allProperties=true, includeNames=true)
+            class Person implements User {
+            }
 
-            def tos = new Person().toString()
-            assert tos.contains('name:Foo')
-            assert tos.contains('User__ANSWER:42')
-            assert tos.contains('User__name:Foo')
+            assert Person.User__LOGGED_IN
+            assert new Person().toString() == 'Person(name:Foo)'
 
-            def loggedInField = Person.getDeclaredFields().find {
-                it.name.contains('loggedIn')
+            def loggedInField = Person.declaredFields.find {
+                it.name.contains('LOGGED_IN')
             }
-            assert isPublic(loggedInField.modifiers)
             assert isFinal(loggedInField.modifiers)
+            assert isPublic(loggedInField.modifiers)
             assert isStatic(loggedInField.modifiers)
-            assert Person.User__loggedIn
 
-            def answerField = Person.getDeclaredFields().find {
-                it.name.contains('ANSWER')
+            def answerField = Person.declaredFields.find {
+                it.name.contains('answer')
             }
+            assert isFinal(answerField.modifiers)
             assert isPrivate(answerField.modifiers)
             assert isTransient(answerField.modifiers)
-            assert isFinal(answerField.modifiers)
-        """
+        '''
     }
 }
diff --git a/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy b/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
index 296d77cf33..1eeab1cb99 100644
--- a/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
@@ -125,6 +125,46 @@ final class TupleConstructorTransformTest {
         '''
     }
 
+    // GROOVY-7950
+    @Test
+    void testTraitPropsAndAllProperties() {
+        assertScript shell, '''
+            trait T {
+                Number n
+            }
+
+            @TupleConstructor(allProperties=true, includes='s,n')
+            class C implements T {
+                String s
+            }
+
+            def obj = new C('answer',42)
+            assert obj.s == 'answer'
+            assert obj.n == 42
+        '''
+    }
+
+    // GROOVY-8219
+    @Test
+    void testTraitPropsAndIncludeFields() {
+        assertScript shell, '''
+            trait T {
+                Number n = 42
+            }
+
+            @TupleConstructor(includeFields=true)
+            class C implements T {
+                String s = ''
+                public x
+            }
+
+            def obj = new C()
+            assert obj.n == 42
+            assert obj.s == ''
+            assert obj.x == null
+        '''
+    }
+
     // GROOVY-7522
     @Test
     void testExistingConstructorTakesPrecedence() {
@@ -350,7 +390,7 @@ final class TupleConstructorTransformTest {
         '''
     }
 
-    // GROOVY-8455, GROOVY-8453
+    // GROOVY-8453, GROOVY-8455
     @Test
     void testPropPsuedoPropAndFieldOrderIncludingInheritedMembers() {
         assertScript shell, '''
@@ -400,6 +440,21 @@ final class TupleConstructorTransformTest {
         '''
     }
 
+    // GROOVY-8207
+    @Test
+    void testDefaults() {
+        assertScript shell, '''
+            @TupleConstructor(defaults=false, includeFields=true)
+            class C {
+                protected int f
+            }
+
+            def obj = new C(42)
+            assert obj.@f == 42
+            assert C.declaredConstructors.length == 1
+        '''
+    }
+
     // GROOVY-10361
     @Test
     void testDefaultsMode() {