Community
Participate
Working Groups
Build Identifier: 20100917-0705 Source that is generated in the last round (when RoundEnvironment.processingOver()==true) is not compiled. The annotation processor writes the .java files to .apt_generated, but the corresponding .class files are not created. Reproducible: Always Steps to Reproduce: Use a annotation processor like: @Override public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) { if( roundEnvironment.processingOver()) { writeSourcefile(); } }
That is correct behavior as per the APT spec. You should not generate any new sources in the final round. It is okay to generate non-source resources, such as XML files, that are not compiled. The final round is there basically in order to support generation of compound or summary resources, such as deployment descriptors.
The documentation of javac says: "After a round occurs where no new source files are generated, the annotation processors will be invoked one last time, to give them a chance to complete any work they may need to do. Finally, unless the -proc:only option is used, the compiler will compile the original and all the generated source files." (from http://download.oracle.com/javase/6/docs/technotes/tools/solaris/javac.html#processing ) In my eyes, the term "any work" includes generating new source files. The compilation process starts _after_ the last round of annotation processing is finished. Furthermore, the annotation processing API does not restrict the type of files generated in the last round. I found http://bugs.sun.com/view_bug.do?bug_id=6634138 which describes the same problem as discussed here. This bug was accepted and fixed for the javac, so I suppose that compiling generated source files from all rounds is the correct behaviour.
I've always taken "After a round where no new source files are generated" to mean that you shouldn't be generating more new source files after that; I think that was the intention of the group working on JSR269. But you're right, it doesn't explicitly say that you can't generate new source files in the final round; so if javac is doing that I guess we will need to as well. Reopening.
By the way, what is the use case for doing this?
Created attachment 183105 [details] Test case Test case demonstrating the problem. Run annotations.jardesc in order to regenerate the annotations jar, and then run BuilderTests.
Olivier, cc'ing you since the fix to this will be in the compiler. I will try to propose a patch.
(In reply to comment #6) > Olivier, cc'ing you since the fix to this will be in the compiler. I will try > to propose a patch. Ok, I'll let you provide a patch for this one.
Created attachment 183153 [details] Proposed fix + regression test Possible fix. Walter, please review.
We probably need to move this to JDT/Core as the fix is inside the compiler code. Walter, move back to APT if you believe this is better in APT.
Fix looks good to me. +1. I wonder if we should also include this in 3.6.2? I think this would not break any existing annotation processors because it is unlikely that there are processors relying on being able to generate a Java type in the final round and not have it be compiled - especially if javac is behaving differently than Eclipse. Holger, do you have input on that?
I don't think this patch would break any existing annotation processors. But I know of at least one real world annotation processor that generates source files in the last round: the Hibernate JPA 2 Metamodel Generator [1]. If I find out how to compile and include your patch into my Eclipse, I will test it with the org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor. [1] http://www.hibernate.org/subprojects/jpamodelgen
I would need PMC approval to backport to 3.6.2.
I'll release the patch today.
Walter, I let you release the regression test in the apt tests. I'll take care of releasing the patch in the compiler.
Be careful to properly update the copyrights.
Released for 3.7M4. Regression test still need to be committed for apt. Walter, once this is done, please close as FIXED.
(In reply to comment #11) > I don't think this patch would break any existing annotation processors. But I > know of at least one real world annotation processor that generates source > files in the last round: the Hibernate JPA 2 Metamodel Generator [1]. If I find > out how to compile and include your patch into my Eclipse, I will test it with > the org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor. > > [1] http://www.hibernate.org/subprojects/jpamodelgen You can easily test the patch by loading inside your workspace org.eclipse.jdt.core from CVS. Then you export and select run inside host. This will install the HEAD version of jdt.core inside your host. On the next restart, you should use the version of JDT/Core that contains the fix. Of course this means that you need to run HEAD. If you want to run 3.6.1+, then you select the branch R3_6_maintenance of JDT/Core and you apply the patch, export into host and restart.
There are several reasons why I don't like to see this in 3.6.2: - It (including the diff to javac) has been like that for years. - The new bug does not seem to a have major impact on a product, at least it was not reported so far. - We do more work which could affect clients and the generated code could be different as we produce new class files.
To test the patch, you can: 1. Download and install the latest stream stable release of Eclipse (3.7M3). 2. In the Plugin Development perspective, Plugins view, import the org.eclipse.jdt.core plug-in as a source project. 3. Copy the text of the proposed patch onto the clipboard, or download it as a file. 4. Team -> Apply Patch. Don't worry about the patches to the test projects, you can ignore those; there is just one change to Compiler.java that you need to apply. 5. Run As -> Eclipse Application. That should start a second Eclipse instance running; in that second ("target") instance you can try building something with the Hibernate JPA processor and see if it works. If you want to point the target instance at a particular existing workspace, you do that by editing the Run As configuration. Thanks! What kind of files does the JPA processor generate on the final round? (I'm just trying to understand why it doesn't do them during the normal rounds.)
(In reply to comment #18) > There are several reasons why I don't like to see this in 3.6.2: > - It (including the diff to javac) has been like that for years. > - The new bug does not seem to a have major impact on a product, at least it > was not reported so far. I've had a chance to sleep on it now and I agree with Dani's points. Any change to the compiler should either have some time to settle in, or it should be motivated by a clearly urgent need (e.g. a regression).
Tests are committed. I'll make sure to tag the test project before the next I-build.
I can confirm that the source files from the Hibernate JPA processor get compiled with the Compiler rev. 1.117. Walter and Olivier, thank you for providing this patch! (In reply to comment #19) > Thanks! What kind of files does the JPA processor generate on the final round? > (I'm just trying to understand why it doesn't do them during the normal > rounds.) As far as I understand, the org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor collects information in every round and builds up an internal data structure. Only in the final round, source files are created from this data structure. Other ways of programming this task are possible, it's just the programmers choice to do it this way.
The reporter himself has confirmed that the bug has been fixed. Verified for 3.7M4.