groovy
  1. groovy
  2. GROOVY-3361

Groovy compiler support for JSR 269

    Details

    • Type: New Feature New Feature
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 2.x
    • Component/s: Compiler
    • Labels:
      None
    • Number of attachments :
      1

      Description

      The javac command in Java 6 supports JSR 269 annotation processors. We should explore whether we can leverage the features provided by the javac compiler during joint compilation (JSR 199 compiler API?) or provide some kind of native support. This overlaps with (and maybe maps directly on to) how ASTTransformations (@Grab, @Grapes) work - though there are some differences too which would need to be addressed.

      For a brief discussion starting point related to one use of such a feature, see:
      http://blogs.sun.com/geertjan/entry/running_groovy_on_the_netbeans

        Activity

        Hide
        Jesse Glick added a comment -

        Sample Maven project demonstrating the problem. Run 'mvn package' using JDK 6. Test output will show:

        Running testgroovy3361.ExampleTest
        loaded item with ID java-example
        Java example ran

        But the annotation from Example.groovy was not processed and so this service (ID groovy-example) is not loaded at runtime.

        Show
        Jesse Glick added a comment - Sample Maven project demonstrating the problem. Run 'mvn package' using JDK 6. Test output will show: Running testgroovy3361.ExampleTest loaded item with ID java-example Java example ran But the annotation from Example.groovy was not processed and so this service (ID groovy-example) is not loaded at runtime.
        Hide
        Jesse Glick added a comment -

        Using gmaven-runtime-1.6 and gmaven-plugin at 1.0-rc-5-SNAPSHOT, the behavior seems similar.

        Interestingly, once when I tried running this I saw it actually load groovy-example (before java-example), i.e. target/classes/META-INF/annotations/testgroovy3361.Marker correctly contained both java-example and groovy-example. When it tried to invoke Runnable.run(), however, rather than printing the impl from Example.groovy, it threw the InternalError from the generated Example.java. I have not been able to reproduce this behavior since then; might have been related to incremental compilation.

        Show
        Jesse Glick added a comment - Using gmaven-runtime-1.6 and gmaven-plugin at 1.0-rc-5-SNAPSHOT, the behavior seems similar. Interestingly, once when I tried running this I saw it actually load groovy-example (before java-example), i.e. target/classes/META-INF/annotations/testgroovy3361.Marker correctly contained both java-example and groovy-example. When it tried to invoke Runnable.run(), however, rather than printing the impl from Example.groovy, it threw the InternalError from the generated Example.java. I have not been able to reproduce this behavior since then; might have been related to incremental compilation.
        Hide
        blackdrag blackdrag added a comment -

        basically the request of this issue is to implement JSR 269 for groovyc. Is that right? That would mean to have some kind of mapping between groovy AST and the tree javac usually gives. Waht would we do with elements that cannot be represented?

        Show
        blackdrag blackdrag added a comment - basically the request of this issue is to implement JSR 269 for groovyc. Is that right? That would mean to have some kind of mapping between groovy AST and the tree javac usually gives. Waht would we do with elements that cannot be represented?
        Hide
        Renato Garcia added a comment -

        Hi,
        Any perspective on this really happening on 1.9 as tagged?

        Show
        Renato Garcia added a comment - Hi, Any perspective on this really happening on 1.9 as tagged?
        Hide
        Guillaume Laforge added a comment -

        It's tagged, but no concrete plan to implement it.
        What are you looking for exactly with this support? What are you trying to achieve?

        Show
        Guillaume Laforge added a comment - It's tagged, but no concrete plan to implement it. What are you looking for exactly with this support? What are you trying to achieve?
        Hide
        Renato Garcia added a comment -

        I have some APT processors being used for Java that I would like to reuse them with Groovy. Basically, they generate code, descriptors and validate annotations. Although they could be implemented using AST transformation in Groovy, it would nice if I could just reuse them with Groovy.

        So, if there is any perspective of this really happening on 1.9 I'd rather wait, otherwise I'll use the AST approach.

        Show
        Renato Garcia added a comment - I have some APT processors being used for Java that I would like to reuse them with Groovy. Basically, they generate code, descriptors and validate annotations. Although they could be implemented using AST transformation in Groovy, it would nice if I could just reuse them with Groovy. So, if there is any perspective of this really happening on 1.9 I'd rather wait, otherwise I'll use the AST approach.
        Hide
        Paul King added a comment -

        At them moment, we haven't made much progress at all. Are any of your APT processors general enough that they could be made available as "test cases/examples" once we do get started?

        Show
        Paul King added a comment - At them moment, we haven't made much progress at all. Are any of your APT processors general enough that they could be made available as "test cases/examples" once we do get started?
        Hide
        Renato Garcia added a comment -

        I believe that the best examples from the ones we currently use are third party APT processors like: QuerDsl and Hibernate Validator

        Show
        Renato Garcia added a comment - I believe that the best examples from the ones we currently use are third party APT processors like: QuerDsl and Hibernate Validator
        Hide
        blackdrag blackdrag added a comment -

        If I see this right, then we are basically talking about a groovy side implementation of JSR269. That means to write a new APT tool, implement all com.sun.mirror classes on top of the Groovy AST. Since there is no modification done by the processro, this might be not much a problem - just requires a lot of time and tests. In the end there will be things in Groovy code, that cannot be expressed by a Java oriented API. THe question now is if that is relevant for this case or not. As I see it, the more advanced usages will use the javac compiler API, for example to scan the contents of a method. Which means we are not done with the mirror API, we need also the javac and source API.

        Implementing this will take a lot of effort.

        Show
        blackdrag blackdrag added a comment - If I see this right, then we are basically talking about a groovy side implementation of JSR269. That means to write a new APT tool, implement all com.sun.mirror classes on top of the Groovy AST. Since there is no modification done by the processro, this might be not much a problem - just requires a lot of time and tests. In the end there will be things in Groovy code, that cannot be expressed by a Java oriented API. THe question now is if that is relevant for this case or not. As I see it, the more advanced usages will use the javac compiler API, for example to scan the contents of a method. Which means we are not done with the mirror API, we need also the javac and source API. Implementing this will take a lot of effort.
        Hide
        Paul King added a comment -

        Yes, a full blown implementation could easily be lots of work. I wasn't thinking of going down the Java 5/APT path with the 'com.sun.*' packages but instead the JSR 269 APIs. In the first instance just trying to have some adapters similar to what you hint at above - calling the JSR 269 visitor methods whenever similar things were visited within the Groovy AST. I.e. the goal being to be able to potentially reuse very simple Java annotation processors and at least report when we/if we determine they can't be used.

        There are many more options to explore I guess:

        • JSR 269 has a suggested way to handle dealing with language differences across versions which might be nice to leverage (even if we just adapt it within our current AST structure rather than use JSR 269)
        • we could expand the Filer utilities to create Groovy source files instead of just Java ones
        • we could have our own groovyx model classes and groovyx annotation processor class
        • we could ensure at the minimum we at least allow annotation processor args to be passed through with joint compilation
        • we could rework some existing infrastructure to be more JSR 269 like, e.g. we could make @Grab follow this pattern and then in theory there would be a standard way for IDEs to see the 'grabbed' jars in the classpath

        But all of that is many person months of work and in some cases may not offer much over our current compiler phases - so at this stage I would consider that we are still in exploratory stages.

        Show
        Paul King added a comment - Yes, a full blown implementation could easily be lots of work. I wasn't thinking of going down the Java 5/APT path with the 'com.sun.*' packages but instead the JSR 269 APIs. In the first instance just trying to have some adapters similar to what you hint at above - calling the JSR 269 visitor methods whenever similar things were visited within the Groovy AST. I.e. the goal being to be able to potentially reuse very simple Java annotation processors and at least report when we/if we determine they can't be used. There are many more options to explore I guess: JSR 269 has a suggested way to handle dealing with language differences across versions which might be nice to leverage (even if we just adapt it within our current AST structure rather than use JSR 269) we could expand the Filer utilities to create Groovy source files instead of just Java ones we could have our own groovyx model classes and groovyx annotation processor class we could ensure at the minimum we at least allow annotation processor args to be passed through with joint compilation we could rework some existing infrastructure to be more JSR 269 like, e.g. we could make @Grab follow this pattern and then in theory there would be a standard way for IDEs to see the 'grabbed' jars in the classpath But all of that is many person months of work and in some cases may not offer much over our current compiler phases - so at this stage I would consider that we are still in exploratory stages.
        Hide
        Jesse Glick added a comment - - edited

        Implementations of com.sun.mirror interfaces is clearly impractical, and anyway unnecessary for a processor written for 269 compliance; only exotic processors cast to these interfaces, such as Lombok (which is unnecessary for Groovy anyway). Dealing with Groovy language constructs which cannot be clearly mapped to javax.model also seems out of scope, except possibly reporting such cases as warnings. Extensions to Filer seems unnecessary since any processor using such a feature would already be Groovy-specific.

        My request would just be that if you take a Java class which is successfully handled by a 269-compliant annotation processor, including (in general) generation of Java sources which then trigger an additional compilation round; rename it to use the *.groovy extension (assuming it is using no Java language features not supported by Groovy), as in the sample project I initially attached; and compile using default options; then the same annotation processor is run as before, with the same results.

        Show
        Jesse Glick added a comment - - edited Implementations of com.sun.mirror interfaces is clearly impractical, and anyway unnecessary for a processor written for 269 compliance; only exotic processors cast to these interfaces, such as Lombok (which is unnecessary for Groovy anyway). Dealing with Groovy language constructs which cannot be clearly mapped to javax.model also seems out of scope, except possibly reporting such cases as warnings. Extensions to Filer seems unnecessary since any processor using such a feature would already be Groovy-specific. My request would just be that if you take a Java class which is successfully handled by a 269-compliant annotation processor, including (in general) generation of Java sources which then trigger an additional compilation round; rename it to use the *.groovy extension (assuming it is using no Java language features not supported by Groovy), as in the sample project I initially attached; and compile using default options; then the same annotation processor is run as before, with the same results.
        Hide
        Renato Garcia added a comment -

        In case anyone else is interested. The groovy-eclipse compiler, including the command line and maven plugin, supports the processing of annotated Groovy classes, just like Java classes without any additional configuration.

        Show
        Renato Garcia added a comment - In case anyone else is interested. The groovy-eclipse compiler, including the command line and maven plugin, supports the processing of annotated Groovy classes, just like Java classes without any additional configuration.
        Hide
        Murali Mohan Rath added a comment -

        I am using gradle. And the annotation processor does not work on the groovy classes.

        Show
        Murali Mohan Rath added a comment - I am using gradle. And the annotation processor does not work on the groovy classes.

          People

          • Assignee:
            Unassigned
            Reporter:
            Paul King
          • Votes:
            7 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated: