Bug 329156 - [compiler][APT] Source generated in last round not compiled
Summary: [compiler][APT] Source generated in last round not compiled
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.7 M4   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-10-31 05:42 EDT by Holger Jaekel CLA
Modified: 2010-12-07 09:41 EST (History)
4 users (show)

See Also:
daniel_megert: pmc_approved-


Attachments
Test case (10.60 KB, patch)
2010-11-15 03:01 EST, Walter Harley CLA
no flags Details | Diff
Proposed fix + regression test (12.93 KB, patch)
2010-11-15 14:47 EST, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Holger Jaekel CLA 2010-10-31 05:42:11 EDT
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();
	}
}
Comment 1 Walter Harley CLA 2010-11-13 18:41:49 EST
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.
Comment 2 Holger Jaekel CLA 2010-11-14 17:24:00 EST
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.
Comment 3 Walter Harley CLA 2010-11-14 20:06:33 EST
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.
Comment 4 Walter Harley CLA 2010-11-14 20:07:51 EST
By the way, what is the use case for doing this?
Comment 5 Walter Harley CLA 2010-11-15 03:01:14 EST
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.
Comment 6 Walter Harley CLA 2010-11-15 03:02:26 EST
Olivier, cc'ing you since the fix to this will be in the compiler.  I will try to propose a patch.
Comment 7 Olivier Thomann CLA 2010-11-15 09:48:16 EST
(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.
Comment 8 Olivier Thomann CLA 2010-11-15 14:47:31 EST
Created attachment 183153 [details]
Proposed fix + regression test

Possible fix. Walter, please review.
Comment 9 Olivier Thomann CLA 2010-11-15 14:48:35 EST
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.
Comment 10 Walter Harley CLA 2010-11-16 03:55:59 EST
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?
Comment 11 Holger Jaekel CLA 2010-11-16 04:26:06 EST
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
Comment 12 Olivier Thomann CLA 2010-11-16 08:59:52 EST
I would need PMC approval to backport to 3.6.2.
Comment 13 Olivier Thomann CLA 2010-11-16 09:00:07 EST
I'll release the patch today.
Comment 14 Olivier Thomann CLA 2010-11-16 09:08:00 EST
Walter, I let you release the regression test in the apt tests.
I'll take care of releasing the patch in the compiler.
Comment 15 Olivier Thomann CLA 2010-11-16 09:08:43 EST
Be careful to properly update the copyrights.
Comment 16 Olivier Thomann CLA 2010-11-16 09:10:15 EST
Released for 3.7M4.
Regression test still need to be committed for apt.
Walter, once this is done, please close as FIXED.
Comment 17 Olivier Thomann CLA 2010-11-16 09:13:02 EST
(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.
Comment 18 Dani Megert CLA 2010-11-16 09:19:49 EST
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.
Comment 19 Walter Harley CLA 2010-11-16 12:29:58 EST
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.)
Comment 20 Walter Harley CLA 2010-11-16 12:32:54 EST
(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).
Comment 21 Walter Harley CLA 2010-11-17 02:59:14 EST
Tests are committed. I'll make sure to tag the test project before the next I-build.
Comment 22 Holger Jaekel CLA 2010-11-21 11:47:43 EST
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.
Comment 23 Jay Arthanareeswaran CLA 2010-12-07 09:41:30 EST
The reporter himself has confirmed that the bug has been fixed.
Verified for 3.7M4.