You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/03/02 02:03:13 UTC

[groovy] branch GROOVY_3_0_X updated: Issue GROOVY-10505: mark trait variables helper methods with trait composition as generated (port to 3_0_X)

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

paulk 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 94375fe  Issue GROOVY-10505: mark trait variables helper methods with trait composition as generated (port to 3_0_X)
94375fe is described below

commit 94375fef24b365b2a9d1990dc38ec4d9c55771b8
Author: Alar Aule <al...@smit.ee>
AuthorDate: Thu Feb 24 19:04:10 2022 +0200

    Issue GROOVY-10505: mark trait variables helper methods with trait composition as generated (port to 3_0_X)
---
 .../transform/trait/TraitASTTransformation.java    |  11 +-
 .../groovy/transform/trait/TraitComposer.java      |   2 +-
 .../transform/GeneratedAnnotationTest.groovy       | 132 +++++++++++++++++++++
 3 files changed, 139 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index 8b44557..2eb9b0e 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -62,6 +62,7 @@ import java.util.List;
 import java.util.Set;
 
 import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
 import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
 import static org.apache.groovy.util.BeanUtils.capitalize;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
@@ -417,12 +418,12 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         if (getterBlock != null) {
             MethodNode getter = new MethodNode(getterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
             getter.setSynthetic(true);
-            cNode.addMethod(getter);
+            addGeneratedMethod(cNode, getter);
 
             if (node.getType().equals(ClassHelper.boolean_TYPE) || node.getType().equals(ClassHelper.Boolean_TYPE)) {
                 MethodNode secondGetter = new MethodNode("is" + capitalize(name), propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
                 secondGetter.setSynthetic(true);
-                cNode.addMethod(secondGetter);
+                addGeneratedMethod(cNode, secondGetter);
             }
         }
         if (setterBlock != null) {
@@ -432,7 +433,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
 
             MethodNode setter = new MethodNode(setterName, propNodeModifiers, ClassHelper.VOID_TYPE, params(setterParameter), ClassNode.EMPTY_ARRAY, setterBlock);
             setter.setSynthetic(true);
-            cNode.addMethod(setter);
+            addGeneratedMethod(cNode, setter);
         }
     }
 
@@ -502,7 +503,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
             }
         }
         // define setter/getter helper methods (setter added even for final fields for legacy compatibility)
-        target.addMethod(
+        addGeneratedMethod(target,
                 Traits.helperSetterName(field),
                 ACC_PUBLIC | ACC_ABSTRACT,
                 field.getOriginType(),
@@ -510,7 +511,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                 ClassNode.EMPTY_ARRAY,
                 null
         );
-        target.addMethod(
+        addGeneratedMethod(target,
                 Traits.helperGetterName(field),
                 ACC_PUBLIC | ACC_ABSTRACT,
                 field.getOriginType(),
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
index a7f1c49..82b5d99 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java
@@ -305,7 +305,7 @@ public abstract class TraitComposer {
                     AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE);
                     impl.addAnnotation(an);
                     cNode.addTransform(StaticCompileTransformation.class, an);
-                    cNode.addMethod(impl);
+                    addGeneratedMethod(cNode, impl);
                 }
             }
         }
diff --git a/src/test/org/codehaus/groovy/transform/GeneratedAnnotationTest.groovy b/src/test/org/codehaus/groovy/transform/GeneratedAnnotationTest.groovy
index 28c7842..c0c61fe 100644
--- a/src/test/org/codehaus/groovy/transform/GeneratedAnnotationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/GeneratedAnnotationTest.groovy
@@ -94,4 +94,136 @@ class GeneratedAnnotationTest extends GroovyShellTestCase {
         def method = person.class.declaredMethods.find { it.name == 'invokeMethod' }
         assert !('groovy.transform.Generated' in method.annotations*.annotationType().name)
     }
+
+    @Test
+    void testCapturedArgForGeneratedClosureIsAnnotatedWithGenerated_GROOVY9396() {
+        def objectUnderTest = evaluate'''
+        class ClassUnderTest {
+            Closure<String> c(String arg) {
+                def closureVar = {
+                    arg
+                }
+                closureVar
+            }
+        }
+        new ClassUnderTest()
+        '''
+
+        Closure<String> closure = objectUnderTest.class.getMethod('c', String).invoke(objectUnderTest, 'var')
+        def getArg = closure.class.getMethod('getArg')
+        assert getArg.annotations*.annotationType().name.contains('groovy.transform.Generated')
+    }
+
+    @Test
+    void testTraitComposerMarksGeneratedMethodsForVariablesAsGenerated_GROOVY10505() {
+        def objectUnderTest = evaluate'''
+        trait TraitWithVariable {
+            private String variableA
+        }
+        trait TraitWithFinalVariable {
+            private final String variableB
+        }
+        trait TraitWithStaticVariable {
+            private static String variableC
+        }
+        trait TraitWithVariableInitialized {
+            private String variableA = "simple variable initialized"
+        }
+        trait TraitWithFinalVariableInitialized {
+            private final String variableB = "final variable initialized"
+        }
+        trait TraitWithStaticVariableInitialized {
+            private static String variableC = "static variable initialized"
+        }
+        trait TraitCompose implements TraitWithVariable, TraitWithFinalVariable, TraitWithStaticVariable,
+                                        TraitWithVariableInitialized, TraitWithFinalVariableInitialized,
+                                        TraitWithStaticVariableInitialized {
+
+        }
+        class ClassUnderTest implements TraitCompose {
+
+        }
+        new ClassUnderTest()
+        '''
+
+        def method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithVariable__variableA$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithVariable__variableA$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithFinalVariable__variableB$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithFinalVariable__variableB$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithStaticVariable__variableC$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithStaticVariable__variableC$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithVariableInitialized__variableA$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithVariableInitialized__variableA$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithFinalVariableInitialized__variableB$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithFinalVariableInitialized__variableB$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithStaticVariableInitialized__variableC$get'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithStaticVariableInitialized__variableC$set'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+    }
+
+    @Test
+    void testTraitComposerMarksGeneratedMethodsForMethodsAsGenerated_GROOVY10505() {
+        def objectUnderTest = evaluate'''
+        trait TraitWithMethod {
+            String methodA() { "method without generated annotation" }
+        }
+        trait TraitWithMethodAsGenerated {
+            @groovy.transform.Generated
+            String methodB() { "method with generated annotation" }
+        }
+        trait TraitWithStaticMethod {
+            static String methodC() { "static method" }
+        }
+        trait TraitWithFinalMethod {
+            final String methodD() { "final method" }
+        }
+        trait TraitCompose implements TraitWithMethod, TraitWithMethodAsGenerated, TraitWithStaticMethod, TraitWithFinalMethod {
+
+        }
+        class ClassUnderTest implements TraitCompose {
+
+        }
+        new ClassUnderTest()
+        '''
+
+        def method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithMethodAsGeneratedtrait$super$methodB'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithMethodtrait$super$methodA'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'TraitWithFinalMethodtrait$super$methodD'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+
+        // and original methods are marked as they were
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'methodA'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated') == false
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'methodB'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated')
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'methodC'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated') == false
+
+        method = objectUnderTest.class.declaredMethods.find { it.name == 'methodD'}
+        assert method.annotations*.annotationType().name.contains('groovy.transform.Generated') == false
+    }
 }
\ No newline at end of file