Community
Participate
Working Groups
Build ID: M20090211-1700 Steps To Reproduce: 1. create annotation with @Inherited 2. create annotation processor for this annotation that checks something and may write an error 3. use annotation and processor like this: a. create BaseClass and apply the annotation b. create SubClass inheriting BaseClass More information: Problem: the processor seems to be called (for the SubClass!) only if a clean + build is done. For the BaseClass the processor is called on every build. We are using the Java 6 style annotation processing. Batch Mode is NOT used. Perhaps some code is usefull: @Inherited @Documented @Retention( RetentionPolicy.SOURCE ) @Target( ElementType.TYPE ) public @interface NameRestriction { String value(); } @SupportedAnnotationTypes( "entwickler.tools.annotation.NameRestriction" ) @SupportedSourceVersion( SourceVersion.RELEASE_6 ) public class NameRestrictionProcessor extends AbstractProcessor { @Override public boolean process( final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv ) { JOptionPane.showMessageDialog( null, "Hi" ); return false; } } @NameRestriction(".*Class") public class BaseClass {} public class SubClazz extends BaseClass{}
I suspect this is a dup of bug 269934, but I will test and confirm.
Sorry, just waking up here, this has nothing whatsoever to do with 269934. What you're saying is that if class Sub is a subclass of class Base, and Base is annotated with an annotation that is @Inherited, then you would expect Sub to be processed just as if it itself were annotated. In other words, you expect the "root elements" set to contain subclasses of annotated elements, as well as the annotated elements themselves. See also http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6250150 for discussion of a related bug in Sun's apt tool. This report seems to confirm the expectation that @Inherited should affect the set of units to be processed (of course, javac does not support incremental compilation, but at least this is a comment on the intention of the spec). The intersection of @Inherited and incremental compilation is a big hole in the JSR269 spec and pretty rough terrain, and I think you are running into a few different problems. Problem #1 is that your annotation has @Retention( RetentionPolicy.SOURCE ). It's not really clear what @Inherited means for a SOURCE annotation - you are making some unjustified assumptions there about the compiler internals, i.e., the compiler is allowed to first compile Base and then compile Sub against Base.class rather than Base.java, and in that case the annotation is lost. So I would strongly suggest that if you want to use @Inherited it should only be for annotations with CLASS or higher retention. I don't see any explicit discussion of that in the Jave Language Spec, but it seems prudent to me. The second problem is that the compiler does not consider annotations to be "structural" when it decides what units to include in an incremental compilation. That is, changing the annotation on Base does not cause Sub to be recompiled - by contrast, changing the visibility of a method in Base would cause Sub to be recompiled. This is bug 149768, which is fixed in Eclipse 3.5M5 and later. If you use 3.5M5 or later you'll notice that changing the ".*Class" string in Base will cause Sub to be recompiled, just as if you'd added a method to Base. The third problem, though, is still present in 3.5M6: changing Sub and recompiling does not trigger annotation processing on Sub. That is, the compiler is deciding that Sub does not have annotations so it doesn't need to be processed, and it is ignoring the presence of @Inherited on the base class. I think that is essentially the same as the Sun bug mentioned above and although it is a grey area in the spec I think we should address it.
Yes- you hit the mark. Thank you for the extensive description. Regrettably changing the retention to CLASS is not an option in this case- as we do not want to deploy the annotations. (They are meant to be used for quality ensurance only) I've not read JSR269. However I thought if inheritance works on Clean + Compile it also should work on incremental compile. But I can clearly see your point that a base class may exist in binary form only (without SOURCE annotations)... Hopefully any solution for this problem can be found.
Created attachment 133471 [details] Passing test for CompilationParticipant I've added a test to the APT test code (pluggable.tests.BuilderTest) that demonstrates the problem when Sub is edited. However, the attached patch to JDT test code also demonstrates that JDT appears to be calling the compilation participant with the expected files, i.e., when Sub is edited it does get reprocessed. So the bug may be in the implementation of the APT compilation participant.
Actually we get as far as RoundDispatcher.round(), so the problem has nothing to do with JDT core. The problem is simply that at this point there are no unclaimed annotations, so we decide not to process anything. Presumably we need to treat inherited annotations as if they were present in determining the set of unclaimed annotations, but that feels like it will be a little tricky to do without introducing some side effects. We probably need to think a bit about exactly what the distinction should be between classes that inherit annotations versus classes that actually are annotated. The JSR269 spec is quite unclear on this topic but it does call out some differences.
I don't know whether the problem also exists for Java 5 processors but that is a lower priority. For JSR269 processors, we collect annotations in two places: from binary types passed in as command-line .class files in RoundEnvImpl.collectAnnotations(), and from ASTs in the AnnotationDiscoveryVisitor. In both of those places, we would need to also search the superclass hierarchy of each class being inspected, to see if the superclass is annotated with an inherited annotation. (Note that annotation inheritance only applies to class annotations, and only to class inheritance, not interface implementation.) One difficulty is that we need to be able to distinguish between a class that actually contains an annotation versus one that inherits an annotation, in order to correctly implement Element.getAnnotationMirrors(). Interface implementations that might be affected include: ElementsImpl.getAllAnnotationMirrors() - should return inherited annos ElementImpl.getAnnotationMirrors() - should *not* return inherited annos ElementImpl.getAnnotation() - should return inherited anno RoundEnvImpl.getElementsAnnotatedWith() - should return inherited annos Internal methods to check: RoundEnvImpl.getRootAnnotations()
I've found that this bug's description is slightly inaccurate. If you do a clean build and inherit from a class on your classpath, inherited annotations still do not get processed. I think a more accurate description of the problem is that both the base class and the subclass need to be compiled at the same time for inherited annotations to be processed.
I agree. Changing the title accordingly.
*** Bug 336566 has been marked as a duplicate of this bug. ***
Hi, Do you have any plan to fix this bug sooner or later ? Thanks, regards, Gauthier
(In reply to Gauthier JACQUES from comment #10) > Hi, > > Do you have any plan to fix this bug sooner or later ? > > Thanks, regards, > > Gauthier No one is working on this.
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.
Problem still occurs. If BaseClass (located in dependent JAR or Eclipse workspace) is annotated with some (Inherited) annotation, annotation processor is not called for SubClass in Eclipse. When using javac (mvn clean install) everything works. It would be nice if this could be fixed.
reopening