AnyAnnotation Proposal
David Holmes
david.holmes at oracle.com
Tue Feb 7 02:25:28 PST 2012
On 7/02/2012 8:04 PM, Reinier Zwitserloot wrote:
> Probably, but I was under the impression a JEP can only be posted by a
> registered contributor or Oracle partner. I am mistaken on that account?
JEPs can be posted by any OpenJDK Committer.
http://openjdk.java.net/jeps/1
David
-----
> --Reinier Zwitserloot
>
>
>
> On Tue, Feb 7, 2012 at 08:48, Ben Evans<benjamin.john.evans at gmail.com>wrote:
>
>> Hi Reinier,
>>
>> Is this the kind of proposal that should really happen as an OpenJDK JEP?
>>
>> Thanks,
>>
>> Ben
>>
>> On Tue, Feb 7, 2012 at 12:40 AM, Reinier Zwitserloot
>> <reinier at zwitserloot.com> wrote:
>>> # The AnyAnnotation feature
>>>
>>> ___v1.0___
>>>
>>> Currently, the JLS specifies that only a direct subtype of
>>> `java.lang.annotation.Annotation`, defined using the `public @interface`
>>> syntax, is actually an annotation type, and that the return type of any
>>> member of an annotation declaration can only be an annotation type (or a
>>> primitive, String, Class, or a 1-dimensional array). It is therefore not
>>> possible in java 1.7 to create a member of an annotation declaration that
>>> implies 'any annotation is legal here'.
>>>
>>> This proposal addresses the lack of this feature. It also moves java
>> closer
>>> towards supporting hierarchical annotations (the ability to have one
>>> annotation declaration extend something other than
>>> `java.lang.annotation.Annotation` itself). In a nutshell, the proposed
>>> changes:
>>>
>>> * Allow `java.lang.annotation.Annotation` as a valid return type for
>>> annotation declaration members (in JDK 1.7 this is not legal). Using this
>>> class as return type means any annotation is intended to be legal.
>>> * Update the JLS to reflect this change (no changes to javadoc,
>> reflection
>>> core API, and JVM specification needed).
>>> * Patch an assert statement in the reflection core API, and 2 lines in
>>> javac, to support the spec.
>>> * Add a new loop detection scheme to avoid an endless loop in the
>> `default`
>>> construction of an annotation declaration member.
>>> * Expand on the impact this change will have, both in regards to which
>>> tooling options now become possible and what impact this change can have
>> on
>>> existing tools.
>>>
>>> ## Authors
>>>
>>> * Reinier Zwitserloot (r.zwitserloot at projectlombok.org)
>>> * Roel Spilker (r.spilker at projectlombok.org)
>>> * Sander Koning (s.koning at projectlombok.org)
>>> * Robbert Jan Grootjans (r.grootjans at projectlombok.org)
>>>
>>> ## Try it right now!
>>>
>>> A special try-it-out javac agent is available here:
>>>
>>> [
>>>
>> http://projectlombok.org/anyannotation](http://projectlombok.org/anyannotation)
>>>
>>> This agent 'live patches' any javac7 in memory only, so you can start
>>> experimenting right away with this feature.
>>>
>>> ## Changes required in the JDK and associated documentation
>>>
>>> ### JVM Specification: Zero changes required
>>>
>>> _Based on [Java Virtual Machine Specification SE7][JVMS]_
>>>
>>> 1. For annotations themselves: Section 4.7.16 - **The
>>> RuntimeVisibleAnnotations attribute** through Section 4.7.19 - **The
>>> RuntimeInvisibleParameterAnnotations attribute** specify how annotations
>>> should be encoded in the class file. These sections say the only way to
>>> store an annotation inside an annotation is as a new annotation block,
>> and
>>> such a block _includes_ the type of the annotation. Thus, in
>> `@Foo(@Bar)`,
>>> there is always a pointer to the constant pool entry with
>>> `com.package.Bar`. It is therefore not necessary to rely on the
>> signatures
>>> available in the `Foo` type to understand its parameter, and therefore no
>>> change is necessary to the class file format to support the case where
>>> `@Foo`'s parameter is of type `Annotation`.
>>>
>>> 2. For annotation type declarations, the JVMS basically contains no
>>> specifications. They are just plain interfaces with a bit set
>>> (`ACC_ANNOTATION` - see section 4.1 `access_flags`). The only new aspect
>>> (other than the `ACC_ANNOTATION` bit, which is not affected by this
>>> proposal) is the classfile encoding of the `default` value feature of an
>>> annotation declaration member, which is described in section 4.7.20 -
>> **The
>>> AnnotationDefault attribute**. The format of this attribute is explained
>> in
>>> terms of section 4.7.16's annotation structure, which already supports
>> this
>>> proposal without any changes required. There is absolutely no mention
>> that
>>> the value of an _AnnotationDefault_ block has to match the type of the
>>> `method_info`'s return type (that aspect of the annotation spec is
>> covered
>>> in the JLS only). In other words, the JVMS doesn't actually consider `int
>>> foo() default "Hello, World!";` illegal, though javac obviously would
>>> refuse to emit a class file if you tried it. This means that `Annotation
>>> onMethod() default @Deprecated;` isn't treated as illegal by the JVMS
>>> either, and thus the JVMS needs no updates to reflect that this would be
>> a
>>> legal construct now. There is furthermore no commentary about the fact
>> that
>>> the return type of an element of an `ACC_ANNOTATION` type can only be a
>>> primitive, String, Class, an annotation type, or a 1-dimensional array of
>>> those. Therefore, no comment needs to be added to explain that
>>> `java.lang.annotation.Annotation` is also legal even though it is not an
>>> annotation type according to the JLS.
>>>
>>> ### JLS Specification: A few changes required
>>>
>>> _based on [Java Language Specification SE7][JLS]_
>>>
>>> 1. 9.6 - **Annotation Types** This introductory section describes the
>>> actual declaration of an annotation type; no changes needed.
>>>
>>> 2. 9.6.1 - **Annotation Type Elements** requires two changes:
>>>
>>> _old:_
>>>
>>> It is a compile-time error if the return type of a method declared in an
>>> annotation
>>> type is not one of the following: a primitive type, String, Class, any
>>> parameterized
>>> invocation of Class, an enum type (S8.9), an annotation type, or an array
>>> type
>>> (S10) whose element type is one of the preceding types.
>>>
>>> _new:_
>>> It is a compile-time error if the return type of a method declared in an
>>> annotation
>>> type is not one of the following: a primitive type, String, Class, any
>>> parameterized
>>> invocation of Class, an enum type (S8.9), an annotation type,
>>> `java.lang.annotation.Annotation`,
>>> or an array type (S10) whose element type is one of the preceding types.
>>> [smaller]
>>> If the return type of an annotation method is declared to be
>>> `java.lang.annotation.Annotation` (or its array), any annotation (S9.7)
>> is
>>> a valid value:
>>> @interface Getter {
>>> Annotation[] onMethod() default {@NonNull};
>>> }
>>> [/smaller]
>>> _old:_
>>> It is a compile-time error if an annotation type declaration T contains
>> an
>>> element
>>> of type T, either directly or indirectly.
>>> [smaller]
>>> For example, this is illegal:
>>> @interface SelfRef { SelfRef value(); }
>>> and so is this:
>>> @interface Ping { Pong value(); }
>>> @interface Pong { Ping value(); }
>>> [/smaller]
>>> _new (optional change; add an example to clarify):_
>>> [smaller]
>>> For example, this is illegal:
>>> @interface SelfRef { SelfRef value(); }
>>> and so is this:
>>> @interface Ping { Pong value(); }
>>> @interface Pong { Ping value(); }
>>> as is this:
>>> @interface SelfRef { Annotation value() default @SelfRef; }
>>> [/smaller]
>>>
>>> 3. 9.6.2 - **Defaults for Annotation Type Elements** requires no changes.
>>> The relevant paragraph reads:
>>>
>>> It is a compile-time error if the type of the element is not commensurate
>>> (S9.7) with
>>> the default value specified.
>>>
>>> After applying the required changes to sections S9.6.1 and S9.7.1, this
>>> statement is still valid.
>>>
>>> 4. 9.6.3 - **Predefined Annotation Types** requires no changes.
>>>
>>> 5. 9.7 - **Annotations** requires no changes (this is an introduction
>>> section).
>>>
>>> 6. 9.7.1 - **Normal Annotations** requires one change and one optional
>>> change.
>>>
>>> The production rule for _ElementValue_ does not need changing because it
>>> already mentions it can consist of an _Annotation_.
>>> _old_:
>>> The return type of this method defines the element type of the
>>> element-value pair.
>>> _new_:
>>> The return type of this method defines the element type of the
>>> element-value pair.
>>> If the return type is `java.lang.annotation.Annotation`, any annotation
>> is
>>> a valid
>>> value.
>>> _old_:
>>> The type of V is assignment compatible (S5.2) with T, and furthermore:
>>> * If T is a primitive type or String, and V is a constant expression
>>> (S15.28).
>>> * V is not null.
>>> * If T is Class, or an invocation of Class, and V is a class literal
>>> (S15.8.2).
>>> * If T is an enum type, and V is an enum constant.
>>> _append an item to the list as clarification:_
>>> * If T is `java.lang.annotation.Annotation`, and V is an annotation.
>>>
>>> 7. 9.7.2 - **Marker Annotations** only describes a shorthand notation;
>>> needs no changes.
>>>
>>> 8. 9.7.3 - **Single-Element Annotations** only describes a shorthand
>>> notation; needs no changes.
>>>
>>> 9. 13.5.7 - **Evolution of Annotation Types** needs no changes.
>>>
>>> ### Changes to javadoc of existing java.* API: No changes required
>>>
>>> 1. method `java.lang.reflect.Method.getDefaultValue()`'s javadoc does not
>>> mention anything about annotation member's return types being restricted
>> to
>>> a subset of legal types, therefore no update to include
>>> `java.lang.annotation.Annotation` in this subset is required.
>>>
>>> 2. `java.lang.Class.isAnnotation()` (and `getModifiers()&
>>> java.lang.reflect.Modifier.ANNOTATION`) is the only aspect of `Class`
>> which
>>> is different / relevant for annotation types, and it also makes no
>> mention
>>> of the return type limitations.
>>>
>>> 3. Existing annotations in the java base library itself (`@Override`,
>>> `@Deprecated`, etc - listed in JLS sections 9.6.3.1-9.6.3.7) do not have
>>> any methods which are an annotation type, nor do any of these types seem
>>> like they could use one. No updates are required or suggested for any of
>>> them.
>>>
>>> 4. The javadoc on `java.lang.annotation.Annotation` itself remains valid.
>>> It might be prudent to expand it with a section that explains that it can
>>> be used as a return type for an annotation method, but the other legal
>>> return types for annotation declaration members don't have this either.
>>> Therefore, for consistency's sake, this proposal does not include a
>> change
>>> to this javadoc.
>>>
>>> ### Changes / additions to any of the method signatures of the reflection
>>> API or any other part of java base: No changes required
>>>
>>> * `java.lang.reflect.Method.getDefaultValue()` already returns
>>> `java.lang.Object` and thus needs no changes.
>>>
>>> * No new API is required to reflectively determine that a given
>> annotation
>>> declaration member's return type is `Annotation`, because the way this
>>> return type is reflected is via a `java.lang.Class` return type, which is
>>> already capable of conveying `Annotation` as a value. This part is one of
>>> the few ways existing tools might break, as they may erroneously assume
>>> this return value can only be `java.lang.Class.class`,
>>> `java.lang.String.class`, any of the primitive wrappers, or a type which
>> is
>>> an annotation type. This method could now also return
>>> `java.lang.annotation.Annotation` which is not itself an annotation type.
>>>
>>> * No new API is required to reflectively read out annotation values, as
>>> these will still be specific instances of annotations.
>>>
>>> * No new API is required to reflectively read out annotation defaults, as
>>> these, if present, will still be specific instances of annotations.
>>>
>>> ### Changes / additions to JVM library reflection core (java.*): No
>> changes
>>> needed
>>>
>>> 1. `java.lang.reflect.Method.getDefaultValue()` delegates work to
>> internal
>>> implementations and does not contain any code that would cause issues
>> with
>>> a `java.lang.annotation.Annotation` return type. It does first acquire
>> the
>>> return type of the method and then asks for an instance of the value that
>>> 'fits' this return type, but it leaves all checking to the internal
>>> implementations that provide both of these values (both the return type
>> and
>>> an instance for the value given the byte array containing the raw
>>> `annotationDefault` data). The work is deferred to
>>> `sun.reflect.annotation.AnnotationParser` and
>>> `sun.reflection.annotation.AnnotationType`, which do need patches (see
>>> below).
>>>
>>> 2. `java.lang.reflect.Method.getAnnotation(java.lang.Class
>>> annotationClass)` defers work to
>> `sun.reflect.annotation.AnnotationParser`
>>> and `sun.reflect.annotation.AnnotationType` as well. Same for
>>> `java.lang.reflect.Field.getAnnotation`, and
>>> `java.lang.Class.getAnnotation`. `java.lang.Package.getAnnotation` is a
>>> wrapper around a dummy `java.lang.Class` instance that holds annotation
>>> data (and thus, it too defers the work). These internal helpers do need
>>> patches (see below).
>>>
>>> ### Changes / additions to internal support classes used by reflective
>>> core: One tiny change needed to a system assertion
>>>
>>> 1. `sun.reflect.annotation.AnnotationType` - no changes necessary.
>>>
>>> 2. `sun.reflect.annotation.AnnotationInvocationHandler` - no changes
>>> necessary. In particular, the `equals()` implementation does not use the
>>> return type, only member values; all special handling defaults to
>>> `equals()`, `toString()`, `hashCode()` etc of the member value if the
>>> member value is an annotation type. annotation instances already have
>>> working `equals`, `hashCode`, `toString`, etc implementations, therefore
>> no
>>> changes are necessary.
>>>
>>> 3. `sun.reflect.annotation.AnnotationParser` - Minor changes necessary.
>>>
>>> _based on [Revision 9b8c96f96a0f of
>>> AnnotationParser.java][AnnotationParser]_
>>>
>>> * method `parseMemberValue` does NOT provide the expected type (parameter
>>> `memberType`) to the `parseAnnotation` helper method. Therefore, the fact
>>> that expected type is a previously invalid value
>>> (`java.lang.annotation.Annotation`) does not have any effect on parsing
>> the
>>> annotation in the class file data.
>>>
>>> * method `parseSig` does not check if the provided type is an annotation
>>> type. (It really can't, as the type is not guaranteed to be on the
>>> classpath, and therefore it has no way of knowing if the provided type is
>>> actually an annotation type. Nevertheless, the code does indeed include
>> no
>>> such check).
>>>
>>> * method 'parseArray' (helper of `parseMemberValue`) contains an
>> assertion
>>> (which can be enabled with the `-esa` javac option) on line 485 which
>> needs
>>> updating:
>>>
>>> - assert componentType.isAnnotation();
>>> + assert componentType.isAnnotation() || componentType ==
>>> java.lang.annotation.Annotation.class;
>>>
>>> ### Changes to javac: Some changes needed
>>>
>>> * javac checks that an annotation declaration member's return type is one
>>> of the allowed types. This check needs to be extended to consider
>>> `java.lang.annotation.Annotation` a legal return type value as well. No
>>> change in the way javac builds the class file to represent the annotation
>>> declaration is required:
>>>
>>> In com.sun.tools.javac.comp.Check:2267
>>> _based on [Revision ce654f4ecfd8 of Check.java][Check]_
>>>
>>> - if ((type.tsym.flags()& Flags.ANNOTATION) != 0) {
>>> + if ((type.tsym.flags()& Flags.ANNOTATION) != 0 || ||
>>> types.isSameType(type, syms.annotationType)) {
>>>
>>> * Loop detection: It is now possible to create 'loops' in default values,
>>> where the default value of an annotation is itself, or, indirectly, some
>>> other annotation, one of whose methods contains a default value that
>> points
>>> back itself. Prior to the introduction of this feature, the rule that the
>>> return types of annotation methods cannot contain a cyclic reference
>> would
>>> make it impossible for the default value to contain such a loop, but now
>>> this is no longer true, so a separate loop detection scheme needs to be
>>> implemented for default values.
>>>
>>> NB: The `checkAnnotationResType` method has been renamed in this patch to
>>> `checkAnnotationElementType` because it is now no longer used just to
>> check
>>> return types, but also to check the types in a `default` value.
>>>
>>> This change is a bit more involved and thus the full patch is listed here
>>> in posix diff format:
>>>
>>> Full patch of com.sun.tools.javac.comp.Check:
>>> _based on [Revision ce654f4ecfd8 of Check.java][Check]_
>>>
>>> 29d28
>>> < import java.util.Set;
>>> 33a33,34
>>> > import com.sun.tools.javac.tree.JCTree.JCAnnotation;
>>>> import com.sun.tools.javac.tree.JCTree.JCExpression;
>>> 38a40
>>>> import com.sun.tools.javac.code.Attribute.Array;
>>> 40a43
>>> > import com.sun.tools.javac.code.Type;
>>> 2267c2270
>>> < if ((type.tsym.flags()& Flags.ANNOTATION) != 0) return;
>>> ---
>>>> if ((type.tsym.flags()& Flags.ANNOTATION) != 0 ||
>>> types.isSameType(type, syms.annotationType)) return;
>>> 2497c2500,2501
>>> < checkAnnotationResType(meth.pos(), meth.restype.type);
>>> ---
>>>> checkAnnotationElementType(meth.pos(),
>> meth.restype.type);
>>> > checkNonCyclicAnnotationDefaultValues(meth);
>>> 2518c2522,2523
>>> < checkAnnotationResType(pos,
>>> ((MethodSymbol)s).type.getReturnType());
>>> ---
>>> > checkAnnotationElementType(pos,
>>> ((MethodSymbol)s).type.getReturnType());
>>>> checkNonCyclicAnnotationDefaultValues(pos,
>>> (MethodSymbol)s);
>>> 2526c2531
>>> < void checkAnnotationResType(DiagnosticPosition pos, Type type) {
>>> ---
>>>> void checkAnnotationElementType(DiagnosticPosition pos, Type type) {
>>> 2533c2538
>>> < checkAnnotationResType(pos, types.elemtype(type));
>>> ---
>>>> checkAnnotationElementType(pos, types.elemtype(type));
>>> 2539a2545,2579
>>> > private void checkNonCyclicAnnotationDefaultValues(JCMethodDecl
>>> meth) {
>>>> if (!isAnnotationType(meth.restype.type)) return;
>>> > if (meth.defaultValue == null) return;
>>>> meth.defaultValue.accept(new TreeScanner() {
>>> > @Override public void visitAnnotation(JCAnnotation tree) {
>>>> checkAnnotationElementType(tree.pos(), tree.type);
>>> > super.visitAnnotation(tree);
>>>> }
>>>> });
>>> > }
>>>>
>>>> private void checkNonCyclicAnnotationDefaultValues(final
>>> DiagnosticPosition pos, MethodSymbol meth) {
>>> > if (!isAnnotationType(meth.type.getReturnType())) return;
>>>> if (meth.defaultValue == null) return;
>>> > if (meth.defaultValue.type.tag == TypeTags.ARRAY) {
>>>> for (Attribute a : ((Array)meth.defaultValue).values) {
>>> > checkAnnotationElementType(pos, a.type);
>>>> }
>>> > }
>>>> else {
>>>> checkAnnotationElementType(pos, meth.defaultValue.type);
>>> > }
>>>> }
>>>>
>>> > private boolean isAnnotationType(Type type) {
>>>> switch (type.tag) {
>>> > case TypeTags.CLASS:
>>>> return types.isSameType(type, syms.annotationType);
>>> > case TypeTags.ARRAY:
>>>> return types.isSameType(types.elemtype(type),
>>> syms.annotationType);
>>> > default:
>>>> return false;
>>>> }
>>> > }
>>>>
>>>
>>> * The error message with key 'cyclic.annotation.element' doesn't need
>>> changing.
>>>
>>> * javac checks that an annotation's parameter is type compatible with the
>>> annotation's declaration. It does this using an 'assignment compatible'
>>> check, which will work fine with `java.lang.annotation.Annotation` as
>>> return type of the annotation declaration member method. However, this
>>> check is entered using an `if` statement which needs to be expanded:
>>>
>>> In com.sun.tools.javac.comp.Annotate:224
>>> _based on [Revision ce654f4ecfd8 of Annotate.java][Annotate]_
>>>
>>> - if ((expected.tsym.flags()& Flags.ANNOTATION) != 0) {
>>> + if ((expected.tsym.flags()& Flags.ANNOTATION) != 0 ||
>>> types.isSameType(expected, syms.annotationType)) {
>>>
>>> * No other changes are required. The error message with key
>>> `invalid.annotation.member.type` may need to be expanded to explain that
>>> `Annotation` is also a legal type.
>>>
>>> ### Changes to javax.lang.model: Some changes needed
>>>
>>> * javax.lang.model mostly requires no changes, except for the feature
>> where
>>> one can ask javax.lang.model to create an instance of a given annotation
>>> class, i.e.:
>>>
>>> for (Element elem : roundEnv.getRootElements()) {
>>> SomeAnnotation instanceOfAnnotation =
>>> elem.getAnnotation(SomeAnnotation.class);
>>> }
>>>
>>> The implementation of this feature in OpenJDK's javac obtains
>>> `java.lang.Class` instances (needed to create the proxies) entirely from
>>> traversing `SomeAnnotation.class` using reflection. As the return types
>> of
>>> the methods in `SomeAnnotation.class` would be
>>> `java.lang.annotation.Annotation`, this mechanism is no longer useful.
>>> Instead, the 'flat name' of the annotation argument itself needs to be
>>> turned into a `java.lang.Class` by using `Class.forName()`. Also, it is
>> now
>>> possible for an annotation argument to contain an annotation that is not
>> on
>>> the classpath of the annotation processor. The right approach is for this
>>> annotation instance to throw a `TypeMirrorException` as late as is
>> feasible
>>> (when the annotation method is invoked that would have to return an
>>> instance of a type that is not available, but not when i.e. `toString()`
>> is
>>> invoked). A full patch to the appropriate class is listed here (note that
>>> the alternate strategy of using `Class.forName` is only used for the new
>>> feature; existing annotations that do not use it are still created by
>>> traversing the annototation type via reflection):
>>>
>>> In com.sun.tools.javac.model.AnnotationProxyMaker
>>> _based on [Revision ce654f4ecfd8 of
>>> AnnotationProxyMaker.java][AnnotationProxyMaker]_
>>>
>>> 62c62,64
>>> < private final Class<? extends Annotation> annoType;
>>> ---
>>>> private Class<? extends Annotation> annoType;
>>> > private final Class<?> context;
>>>> private ClassLoader classLoader;
>>> 66c68
>>> < Class<? extends Annotation> annoType)
>> {
>>> ---
>>>> Class<? extends Annotation> annoType,
>>> Class<?> context) {
>>> 68a71
>>>> this.context = context;
>>> 77,78c80
>>> < AnnotationProxyMaker apm = new AnnotationProxyMaker(anno,
>>> annoType);
>>> < return annoType.cast(apm.generateAnnotation());
>>> ---
>>>> return annoType.cast(generateAnnotationInner(anno, annoType,
>>> annoType, null));
>>> 80a83,88
>>>> private static Object generateAnnotationInner(
>>>> Attribute.Compound anno, Class<? extends Annotation>
>>> annoType, Class<?> context, ClassLoader classLoader) {
>>> > AnnotationProxyMaker apm = new AnnotationProxyMaker(anno,
>>> annoType, context);
>>>> apm.classLoader = classLoader;
>>> > return apm.generateAnnotation();
>>>> }
>>> 81a90,100
>>> > private ClassLoader getAnnotationClassLoader() {
>>>> if (classLoader == null) {
>>> > ClassLoader cl = context.getClassLoader();
>>>> // Line above Could cause security exception, but
>>> > // no other part of javac uses doPrivileged;
>>>> // in particular line 259 of AnnotationParser also doesn't
>>> bother,
>>> > // and is in the same boat.
>>>> this.classLoader = cl != null ? cl :
>>> ClassLoader.getSystemClassLoader();
>>> > }
>>>> return classLoader;
>>>> }
>>> 85c104,116
>>> < private Annotation generateAnnotation() {
>>> ---
>>> > @SuppressWarnings("unchecked")
>>>> private Object generateAnnotation() {
>>> > if (annoType == Annotation.class) {
>>>> try {
>>>> Class<? extends Annotation> clazz = (Class<? extends
>>> Annotation>)
>>> >
>>>
>> getAnnotationClassLoader().loadClass(anno.type.tsym.flatName().toString());
>>>> annoType = clazz;
>>> > return AnnotationParser.annotationForMap(clazz,
>>>> getAllReflectedValues());
>>> > } catch (ClassNotFoundException e) {
>>>> return new MirroredTypeExceptionProxy(anno.type);
>>> > }
>>>> }
>>> 170a202
>>> >
>>> 239c271
>>> < value = generateAnnotation(c, nested);
>>> ---
>>>> value = generateAnnotationInner(c, nested, context,
>>> classLoader);
>>>
>>> ## Source and binary compatibility
>>>
>>> This proposal introduces no new or changed behaviour for any source code
>>> which is legal today, and no changes to the class file format. Therefore,
>>> existing source files which compile on javac 1.7 are not affected.
>>>
>>> Existing tools also notice no changes for existing source and class
>> files.
>>> However, newly compiled annotation declarations may now start using
>>> `java.lang.annotation.Annotation` as return type for members, and some
>>> existing tools may have assumed the legal set of return values couldn't
>>> change. These tools will need to be updated.
>>>
>>> Technically, it is possible for existing annotations to be 'widened' -
>> any
>>> return types which used to be a specific annotation type can be
>> generalized
>>> to `java.lang.annotation.Annotation`, but this might cause problems with
>>> consumers of this annotation. The same problem occurs for any library
>>> update where signatures are changed, however.
>>>
>>> ## Use cases for this feature
>>>
>>> One obvious use case for annotations is generating code. If this feature
>> is
>>> added to the JDK, it is possible to specify a list of annotations that
>>> should be put in the generated code. For example, an annotation that will
>>> generate a POJO with implementations for `equals`, `hashCode`, et cetera:
>>>
>>> @GeneratePOJO
>>> @AddAnnotations(onClass=@SuppressWarnings("all"))
>>> public class StudentTemplate {
>>> @AddAnnotations(onGetter={@NonNull, @javax.persistence.Id})
>>> private int unid;
>>> }
>>>
>>> This feature also takes a step towards allowing hierarchical annotation
>>> definitions (where an annotation extends another annotation type, instead
>>> of `java.lang.annotation.Annotation`.
>>>
>>> ## Testing the feature
>>>
>>> These patches, plus a test suite as well as a way to build a 'live
>> patching
>>> agent' which allows experimenting with these patches, are available here:
>>>
>>> * [github repository](
>> http://github.com/rspilker/jdk-proposal.anyannotation)
>>> - source repository
>>> * [live agent](http://projectlombok.org/anyannotation) - direct
>> download of
>>> the agent which allows immediate experimentation with any javac7.
>>>
>>> [JVMS]: http://docs.oracle.com/javase/7/specs/jvms/JVMS-JavaSE7.pdf
>>> [JLS]: http://docs.oracle.com/javase/7/specs/jls/JLS-JavaSE7.pdf
>>> [AnnotationParser]:
>>>
>> http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/reflect/annotation/AnnotationParser.java
>>> [Check]:
>>>
>> http://hg.openjdk.java.net/jdk7/jdk7/langtools/file/ce654f4ecfd8/src/share/classes/com/sun/tools/javac/comp/Check.java
>>> [Annotate]:
>>>
>> http://hg.openjdk.java.net/jdk7/jdk7/langtools/file/ce654f4ecfd8/src/share/classes/com/sun/tools/javac/comp/Annotate.java
>>> [AnnotationProxyMaker]:
>>>
>> http://hg.openjdk.java.net/jdk7/jdk7/langtools/file/ce654f4ecfd8/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java
>>>
>>
>
More information about the coin-dev
mailing list