From joe.darcy at oracle.com Wed May 22 22:07:24 2013 From: joe.darcy at oracle.com (Joe Darcy) Date: Wed, 22 May 2013 22:07:24 -0700 Subject: FYI, JSR 308 and the annotation processing discovery process In-Reply-To: <515A5C52.50907@oracle.com> References: <5155291F.2050907@oracle.com> <51561161.8030207@oracle.com> <515A5C52.50907@oracle.com> Message-ID: <519DA40C.9090703@oracle.com> Hello, An update on updating annotation processing discovery to account for the annotation changes made in JSR 308 (type annotations and declaration annotations on type parameters) as well as repeating annotations: the proposed specification change is: @@ -88,7 +90,8 @@ * configuration mechanisms, such as command line options; for * details, refer to the particular tool's documentation. Which * processors the tool asks to {@linkplain #process run} is a function - * of what annotations are present on the {@linkplain + * of the types of the annotations {@linkplain AnnotatedConstruct present} + * on the {@linkplain * RoundEnvironment#getRootElements root elements}, what {@linkplain * #getSupportedAnnotationTypes annotation types a processor * processes}, and whether or not a processor {@linkplain #process @@ -106,6 +109,28 @@ * processing {@code "*"} can claim the (empty) set of annotation * types. * + *

An annotation type is considered present if there is at least + * one annotation of that type present on an element enclosed within + * the root elements of a round. Annotations on {@linkplain + * ElementType#TYPE_USE type uses} are not considered as part + * of the computation. For this purpose, a type parameter is + * considered to be enclosed by its {@linkplain + * TypeParameter#getGenericElement generic element}. An annotation is + * present if it meets the definition of being present given in {@link + * AnnotatedConstruct}. In brief, an annotation is considered present + * for the purposes of discovery if it is directly present or present + * via inheritance. An annotation is not considered present + * by virtue of being wrapped by a container + * annotation. Operationally, this is equivalent to an annotation + * being present on an element if and only if it would be included in + * the results of {@link Elements#getAllAnnotationMirrors()} called on + * that element. Since annotations inside container annotations are + * not considered present, to properly process {@linkplain + * java.lang.annotation.Repeatable repeatable annotation types}, + * processors are advised to include both the annotation and its + * container in the set of {@linkplain #getSupportedAnnotationTypes() + * supported annotation types} of a processor. + * *

Note that if a processor supports {@code "*"} and returns {@code * true}, all annotations are claimed. Therefore, a universal * processor being used to, for example, implement additional validity For more context, the webrev (which includes implementation changes) is at: http://cr.openjdk.java.net/~darcy/7162089.2/ Thanks, -Joe On 04/01/2013 09:19 PM, Joe Darcy wrote: > On 03/29/2013 03:10 PM, Alex Buckley wrote: >> On 3/28/2013 10:39 PM, Joe Darcy wrote: >>> FYI, as the JSR 269 maintenance lead, besides updating the >>> javax.lang.model.* API to handle new-in-Java-SE-8 features, I'm not >>> looking at updating the javax.annotation.processing API to deal with >>> those new annotation-related features too. >> >> "not looking"? Surely "now looking". > > Quite! > >> >>> "The tool uses a discovery process to find annotation processors and >>> decide whether or not they should be run. [...] Which processors the >>> tool asks to run is a function of what annotations are present on the >>> root elements, what annotation types a processor processes, and whether >>> or not a processor claims the annotations it processes. [...] For a >>> given round, the tool computes the set of annotation types on the root >>> elements. If there is at least one annotation type present, as >>> processors claim annotation types, they are removed from the set of >>> unmatched annotations." >> >> Close reading of the above paragraph reveals that: >> >> - a processor _claims_ annotation types >> - a processor _claims_ annotations >> - a processor _processes_ annotations >> - from a set of annotations, it is possible to remove annotation _types_ >> >> I contend there is at least one kind error going on here. > > I will tighten up the wording accordingly; thanks for the careful > reading. > >> >>> To this, I plan to add a paragraph explaining how type annotations do >>> not interact with the this discovery process; something like: >>> >>> "

An annotation type is considered present if there is at least one >>> annotation of that type on a declaration enclosed within the root >>> elements of a round. For this purpose, a type parameter is considered >>> to be enclosed by its generic element. Annotations on type uses are >>> not considered as part of the computation. >> >> There is quite a phase shift between the "For this purpose" sentence >> and the type uses sentence. I think a new paragraph is warranted: >> "Annotations on type uses are ignored when computing the set of >> annotation types present on the root elements." >> >>> For the purposes of JSR 308: >>> >>> * Declaration annotations on type parameters are included in discovery >>> * TYPE_USE annotations are *not* included as part of discovery >> >> You mean to put "For the purposes of JSR 308" into the SE 8 API spec? > > No. "For the purposes of JSR 308" is just for the purposes of this > email thread :-) > >> That would be wrong, as a JSR number is pure administration and the >> API spec should deal only in features. > > Agreed. > >> >> For the bullet points, beware: an annotation whose type targets >> TYPE_USE can appear on a type declaration or a type parameter >> declaration. Surely you want such an annotation on class Foo's >> declaration to be discovered. Do you mean: >> >> - Annotations on type parameter declarations are included in discovery. >> - Annotations on type uses are not included in discovery. >> >> > > Annotations on declarations, including declarations of type > parameters, are included in discovery. > > -Joe > From alex.buckley at oracle.com Thu May 23 11:59:45 2013 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 23 May 2013 11:59:45 -0700 Subject: FYI, JSR 308 and the annotation processing discovery process In-Reply-To: <519DA40C.9090703@oracle.com> References: <5155291F.2050907@oracle.com> <51561161.8030207@oracle.com> <515A5C52.50907@oracle.com> <519DA40C.9090703@oracle.com> Message-ID: <519E6721.80906@oracle.com> Thanks very much Joe. Some distressingly tricky stuff below: On 5/22/2013 10:07 PM, Joe Darcy wrote: > @@ -88,7 +90,8 @@ > * configuration mechanisms, such as command line options; for > * details, refer to the particular tool's documentation. Which > * processors the tool asks to {@linkplain #process run} is a function > - * of what annotations are present on the {@linkplain > + * of the types of the annotations {@linkplain AnnotatedConstruct > present} > + * on the {@linkplain > * RoundEnvironment#getRootElements root elements}, what {@linkplain > * #getSupportedAnnotationTypes annotation types a processor > * processes}, and whether or not a processor {@linkplain #process > @@ -106,6 +109,28 @@ It would be clearer and more kind-correct to say: "Which processors the tool asks to run is a function of i) the types of the annotations present on the root elements, ii) the annotation types supported by a processor, and iii) the annotation types claimed by a processor." The idea that a processor CLAIMS annotation types comes from line 104. And if this is right, Processor#process must be clarified. It takes a set of types - great - and returns whether the processor claims all annotations of those types. If you intend to draw an equivalence between "claiming all annotations of types X and Y" and "claiming the annotation types X and Y", please be explicit about it. Right now, the following method spec simply does not parse: "Processes a set of ANNOTATION TYPES on type elements originating from the prior round and returns whether or not THESE ANNOTATIONS are claimed by this processor." It would also be good to say "(see below)" when line 104 introduces the idea of annotation types being present, since the more common concept is of annotations being present. OK, moving to the new text... > + *

An annotation type is considered present if there is at least > + * one annotation of that type present on an element enclosed within > + * the root elements of a round. > + * Annotations on {@linkplain > + * ElementType#TYPE_USE type uses} are not considered as part > + * of the computation. An annotation might be able to target type uses _and_ traditional declaration locations. I think you want to ignore annotations which are _solely_ interested in targeting type uses. At the same time, remember that ElementType.TYPE_USE means "type uses _and_ type declarations and type parameter declarations". So, given an annotation type Foo with @Target(TYPE_USE) and no other @Target, would @Foo being present on a type declaration mean that annotation type Foo is present? The answer should be "yes", because the intent of ElementType.TYPE_USE is to supersede ElementType.TYPE (no doubt the prior @Target of Foo) and previous annotation processors would have processed @Foo on a type declaration just fine. BTW, line 102 should say "the tool computes the set of annotation types PRESENT on the root elements." > + * For this purpose, a type parameter is > + * considered to be enclosed by its {@linkplain > + * TypeParameter#getGenericElement generic element}. Big context switch here from type-oriented stuff to element-oriented. Please put it in in TypeParameterElement's spec. Please have a paragraph break before the "annotation is present" stuff. > + * An annotation is > + * present if it meets the definition of being present given in {@link > + * AnnotatedConstruct}. In brief, an annotation is considered present > + * for the purposes of discovery if it is directly present or present > + * via inheritance. An annotation is not considered present > + * by virtue of being wrapped by a container > + * annotation. Operationally, this is equivalent to an annotation > + * being present on an element if and only if it would be included in > + * the results of {@link Elements#getAllAnnotationMirrors()} called on > + * that element. Since annotations inside container annotations are > + * not considered present, to properly process {@linkplain > + * java.lang.annotation.Repeatable repeatable annotation types}, > + * processors are advised to include both the annotation and its > + * container in the set of {@linkplain #getSupportedAnnotationTypes() > + * supported annotation types} of a processor. This was going great until: "advised to include both the annotation and its container in the set of ..." - it should be "include both the repeatable annotation type and its containing annotation type in the set of ...". Alex