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 2018/11/10 10:41:26 UTC

[2/3] groovy git commit: GROOVY-8872: Populate the parameter names from the byte code when available (add test)

GROOVY-8872: Populate the parameter names from the byte code when available (add test)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/66c87071
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/66c87071
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/66c87071

Branch: refs/heads/GROOVY_2_5_X
Commit: 66c8707165081d201d90dd79e9ff9610147dd4c6
Parents: c8944a5
Author: Paul King <pa...@asert.com.au>
Authored: Sat Nov 10 17:28:56 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Sat Nov 10 20:39:48 2018 +1000

----------------------------------------------------------------------
 .../codehaus/groovy/ast/tools/GeneralUtils.java |   4 +
 .../groovy/groovy/ant/Groovy8872Test.groovy     | 100 +++++++++++--------
 2 files changed, 61 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/66c87071/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
----------------------------------------------------------------------
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 a312b2f..f0b20e0 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
@@ -619,6 +619,10 @@ public class GeneralUtils {
         return new BooleanExpression(new BinaryExpression(expr, EQ, new ConstantExpression(0)));
     }
 
+    public static ListExpression listX(List<Expression> args) {
+        return new ListExpression(args);
+    }
+
     public static ListExpression list2args(List args) {
         ListExpression result = new ListExpression();
         for (Object o : args) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/66c87071/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy8872Test.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy8872Test.groovy b/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy8872Test.groovy
index 1cd46e7..e43714a 100644
--- a/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy8872Test.groovy
+++ b/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy8872Test.groovy
@@ -18,26 +18,19 @@
  */
 package groovy.ant
 
-class Groovy8669Test extends AntTestCase {
-    private scriptAllOnPath = '''
-    def anno = AnnotatedClass.annotations[0]
-    def type = anno.annotationType()
-    assert type.name == 'MyAnnotation'
-    assert type.getDeclaredMethod('value').invoke(anno).name == 'ValueClass'
-    '''
-
-    private scriptNoValueClass = '''
-    // using annotations will cause ValueClass not to be found
-    // but should still be able to use the class otherwise
-    assert AnnotatedClass.name.size() == 14
-    '''
+class Groovy8872Test extends AntTestCase {
+    private scriptParamNameCheck = '''
+        @ExtractParamNames
+        abstract class DummyClass implements JavaInterface, GroovyInterface {}
 
-    private scriptNoAnnotationOnPath = '''
-    // class should be usable but won't have annotations
-    assert !AnnotatedClass.annotations
+        def paramNames = DummyClass.paramNames
+        assert paramNames == [
+            ['name', 'dob', 'vip'],
+            ['id', 'eventName', 'dateOfEvent']
+        ]
     '''
 
-    void testCreateZip() {
+    void testParameterNamesSeenInAST() {
 //        def debugLogger = new org.apache.tools.ant.DefaultLogger()
 //        debugLogger.setMessageOutputLevel(4)
 //        debugLogger.setOutputPrintStream(System.out)
@@ -45,43 +38,64 @@ class Groovy8669Test extends AntTestCase {
 
         doInTmpDir { ant, baseDir ->
             baseDir.src {
-                'ValueClass.java'('''
-                    public class ValueClass{ }
+                'JavaInterface.java'('''
+                    import java.util.Date;
+
+                    public interface JavaInterface {
+                        void addPerson(String name, Date dob, boolean vip);
+                    }
+                ''')
+                'GroovyInterface.groovy'('''
+                    interface GroovyInterface {
+                        void addEvent(int id, String eventName, Date dateOfEvent)
+                    }
                 ''')
-                'MyAnnotation.java'('''
-                    import java.lang.annotation.*;
+                'ExtractParamNames.groovy'('''
+                    import org.codehaus.groovy.transform.GroovyASTTransformationClass
+                    import java.lang.annotation.*
 
+                    /**
+                     * Test transform adds a static method to a class that returns a map from the name
+                     * for each found method to its parameter names.
+                     */
+                    @java.lang.annotation.Documented
+                    @Retention(RetentionPolicy.SOURCE)
                     @Target(ElementType.TYPE)
-                    @Retention(RetentionPolicy.RUNTIME)
-                    public @interface MyAnnotation {
-                        Class<ValueClass> value();
-                    }
+                    @GroovyASTTransformationClass("ExtractParamNamesTransformation")
+                    @interface ExtractParamNames { }
                 ''')
-                'AnnotatedClass.java'('''
-                    @MyAnnotation(ValueClass.class)
-                    class AnnotatedClass { }
+                'ExtractParamNamesTransformation.groovy'('''
+                    import org.codehaus.groovy.ast.*
+                    import org.codehaus.groovy.ast.expr.*
+                    import org.codehaus.groovy.ast.stmt.*
+                    import org.codehaus.groovy.transform.*
+                    import org.codehaus.groovy.control.*
+                    import static org.codehaus.groovy.ast.tools.GeneralUtils.*
+
+                    @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+                    class ExtractParamNamesTransformation extends AbstractASTTransformation {
+                        void visit(ASTNode[] nodes, SourceUnit source) {
+                            init(nodes, source)
+                            def classNode = nodes[1]
+                            assert classNode instanceof ClassNode
+                            def result = listX(classNode.abstractMethods.collect{ list2args(it.parameters.name) })
+                            classNode.addField(new FieldNode("paramNames", ACC_PUBLIC+ACC_STATIC+ACC_FINAL,
+                                               ClassHelper.LIST_TYPE.plainNodeReference, classNode, result))
+                        }
+                    }
                 ''')
             }
 //            ant.project.addBuildListener(debugLogger)
             ant.mkdir(dir: 'build')
             ant.javac(classpath: '.', destdir: 'build', srcdir: 'src',
-                    includes: '*.java', includeantruntime: 'false', fork: 'true')
-            ['ValueClass', 'MyAnnotation', 'AnnotatedClass'].each { name ->
-                ant.mkdir(dir: "build$name")
-                ant.copy(file: "build/${name}.class", todir: "build$name")
+                    includes: '*.java', includeantruntime: 'false', fork: 'true') {
+                compilerarg(value: '-parameters')
             }
+            ant.taskdef(name: 'groovyc', classname: 'org.codehaus.groovy.ant.Groovyc')
+            ant.groovyc(srcdir: 'src', destdir: 'build', parameters: 'true')
             ant.taskdef(name: 'groovy', classname: 'org.codehaus.groovy.ant.Groovy')
-            ant.groovy(scriptAllOnPath) {
-                classpath { pathelement(path: 'buildValueClass') }
-                classpath { pathelement(path: 'buildMyAnnotation') }
-                classpath { pathelement(path: 'buildAnnotatedClass') }
-            }
-            ant.groovy(scriptNoValueClass) {
-                classpath { pathelement(path: 'buildMyAnnotation') }
-                classpath { pathelement(path: 'buildAnnotatedClass') }
-            }
-            ant.groovy(scriptNoAnnotationOnPath) {
-                classpath { pathelement(path: 'buildAnnotatedClass') }
+            ant.groovy(scriptParamNameCheck) {
+                classpath { pathelement(path: 'build') }
             }
         }
     }