# HG changeset patch # User jjg # Date 1363656793 25200 # Node ID 97f6839673d6b64e3d6ea8decba296d545ae6f56 # Parent 40adaf938847a5e256017261aa826e4ade8977c4 8007803: Implement javax.lang.model API for Type Annotations Reviewed-by: darcy diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/code/Printer.java --- a/src/share/classes/com/sun/tools/javac/code/Printer.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Printer.java Mon Mar 18 18:33:13 2013 -0700 @@ -311,9 +311,9 @@ } if (args.head.unannotatedType().getKind() == TypeKind.ARRAY) { buf.append(visit(((ArrayType) args.head.unannotatedType()).elemtype, locale)); - if (args.head.getAnnotations().nonEmpty()) { + if (args.head.getAnnotationMirrors().nonEmpty()) { buf.append(' '); - buf.append(args.head.getAnnotations()); + buf.append(args.head.getAnnotationMirrors()); buf.append(' '); } buf.append("..."); diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Mar 18 18:33:13 2013 -0700 @@ -483,12 +483,12 @@ */ @Deprecated public A getAnnotation(Class annoType) { - return JavacElements.getAnnotation(this, annoType); + return JavacAnnoConstructs.getAnnotation(this, annoType); } // This method is part of the javax.lang.model API, do not use this in javac code. public A[] getAnnotationsByType(Class annoType) { - return JavacElements.getAnnotations(this, annoType); + return JavacAnnoConstructs.getAnnotations(this, annoType); } // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList @@ -935,11 +935,12 @@ } /** - * @deprecated this method should never be used by javac internally. + * Since this method works in terms of the runtime representation + * of annotations, it should never be used by javac internally. */ - @Override @Deprecated + @Override public A getAnnotation(Class annoType) { - return JavacElements.getAnnotation(this, annoType); + return JavacAnnoConstructs.getAnnotation(this, annoType); } public R accept(ElementVisitor v, P p) { @@ -1444,6 +1445,10 @@ return v.visitMethodSymbol(this, p); } + public Type getReceiverType() { + return asType().getReceiverType(); + } + public Type getReturnType() { return asType().getReturnType(); } diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/code/Type.java --- a/src/share/classes/com/sun/tools/javac/code/Type.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Mon Mar 18 18:33:13 2013 -0700 @@ -25,6 +25,9 @@ package com.sun.tools.javac.code; +import com.sun.tools.javac.model.JavacAnnoConstructs; +import com.sun.tools.javac.model.JavacTypes; +import java.lang.annotation.Annotation; import java.util.Collections; import java.util.EnumMap; import java.util.EnumSet; @@ -258,6 +261,23 @@ return this; } + @Override + public List getAnnotationMirrors() { + return List.nil(); + } + + @Override + public A getAnnotation(Class annotationType) { + return null; + } + + @Override + public A[] getAnnotationsByType(Class annotationType) { + @SuppressWarnings("unchecked") + A[] tmp = (A[]) java.lang.reflect.Array.newInstance(annotationType, 0); + return tmp; + } + /** Return the base types of a list of types. */ public static List baseTypes(List ts) { @@ -354,8 +374,8 @@ } if (args.head.unannotatedType().tag == ARRAY) { buf.append(((ArrayType)args.head.unannotatedType()).elemtype); - if (args.head.getAnnotations().nonEmpty()) { - buf.append(args.head.getAnnotations()); + if (args.head.getAnnotationMirrors().nonEmpty()) { + buf.append(args.head.getAnnotationMirrors()); } buf.append("..."); } else { @@ -366,7 +386,6 @@ /** Access methods. */ - public List getAnnotations() { return List.nil(); } public List getTypeArguments() { return List.nil(); } public Type getEnclosingType() { return null; } public List getParameterTypes() { return List.nil(); } @@ -1581,13 +1600,23 @@ } @Override - public TypeKind getKind() { - return underlyingType.getKind(); + public List getAnnotationMirrors() { + return typeAnnotations; } @Override - public List getAnnotations() { - return typeAnnotations; + public A getAnnotation(Class annotationType) { + return JavacAnnoConstructs.getAnnotation(this, annotationType); + } + + @Override + public A[] getAnnotationsByType(Class annotationType) { + return JavacAnnoConstructs.getAnnotationsByType(this, annotationType); + } + + @Override + public TypeKind getKind() { + return underlyingType.getKind(); } @Override diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Mar 18 18:33:13 2013 -0700 @@ -4279,7 +4279,7 @@ validateAnnotatedType(errtree, type); if (type.tsym != null && type.tsym.isStatic() && - type.getAnnotations().nonEmpty()) { + type.getAnnotationMirrors().nonEmpty()) { // Enclosing static classes cannot have type annotations. log.error(errtree.pos(), "cant.annotate.static.class"); } diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java --- a/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Mon Mar 18 18:33:13 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -273,7 +273,7 @@ /** * ExceptionProxy for MirroredTypeException. - * The toString, hashCode, and equals methods foward to the underlying + * The toString, hashCode, and equals methods forward to the underlying * type. */ private static final class MirroredTypeExceptionProxy extends ExceptionProxy { diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Mon Mar 18 18:33:13 2013 -0700 @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.tools.javac.model; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.AnnotatedType; +import com.sun.tools.javac.util.ListBuffer; +import static com.sun.tools.javac.code.TypeTag.CLASS; + +/** + * Utility methods for operating on annotated constructs. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class JavacAnnoConstructs { + + // + + /** + * An internal-use utility that creates a runtime view of an + * annotation. This is the implementation of + * Element.getAnnotation(Class). + */ + public static
A getAnnotation(Symbol annotated, + Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + Attribute.Compound c; + if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { + c = getAttributeOnClass((ClassSymbol)annotated, annoType); + } else { + c = getAttribute(annotated, annoType); + } + return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType); + } + + // Helper to getAnnotation[s] + private static Attribute.Compound getAttribute(Symbol annotated, + Class annoType) { + String name = annoType.getName(); + + for (Attribute.Compound anno : annotated.getRawAttributes()) { + if (name.equals(anno.type.tsym.flatName().toString())) + return anno; + } + + return null; + } + + // Helper to getAnnotation[s] + private static Attribute.Compound getAttributeOnClass(ClassSymbol annotated, + Class annoType) { + boolean inherited = annoType.isAnnotationPresent(Inherited.class); + Attribute.Compound result = null; + while (annotated.name != annotated.name.table.names.java_lang_Object) { + result = getAttribute(annotated, annoType); + if (result != null || !inherited) + break; + Type sup = annotated.getSuperclass(); + if (!sup.hasTag(CLASS) || sup.isErroneous()) + break; + annotated = (ClassSymbol) sup.tsym; + } + return result; + } + + /** + * An internal-use utility that creates a runtime view of + * annotations. This is the implementation of + * Element.getAnnotations(Class). + */ + public static A[] getAnnotations(Symbol annotated, + Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + // If annoType does not declare a container this is equivalent to wrapping + // getAnnotation(...) in an array. + Class containerType = getContainer(annoType); + if (containerType == null) { + A res = getAnnotation(annotated, annoType); + int size; + if (res == null) { + size = 0; + } else { + size = 1; + } + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + if (res != null) + arr[0] = res; + return arr; + } + + // So we have a containing type + String name = annoType.getName(); + String annoTypeName = annoType.getSimpleName(); + String containerTypeName = containerType.getSimpleName(); + int directIndex = -1, containerIndex = -1; + Attribute.Compound direct = null, container = null; + Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]); + + // Find directly present annotations + for (int i = 0; i < rawAttributes.length; i++) { + if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + directIndex = i; + direct = rawAttributes[i]; + } else if(containerTypeName != null && + containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + containerIndex = i; + container = rawAttributes[i]; + } + } + + // Deal with inherited annotations + if (annotated.kind == Kinds.TYP && + (annotated instanceof ClassSymbol)) { + ClassSymbol s = (ClassSymbol)annotated; + if (direct == null && container == null) { + direct = getAttributeOnClass(s, annoType); + container = getAttributeOnClass(s, containerType); + + // both are inherited and found, put container last + if (direct != null && container != null) { + directIndex = 0; + containerIndex = 1; + } else if (direct != null) { + directIndex = 0; + } else { + containerIndex = 0; + } + } else if (direct == null) { + direct = getAttributeOnClass(s, annoType); + if (direct != null) + directIndex = containerIndex + 1; + } else if (container == null) { + container = getAttributeOnClass(s, containerType); + if (container != null) + containerIndex = directIndex + 1; + } + } + + // Pack them in an array + Attribute[] contained0 = new Attribute[0]; + if (container != null) + contained0 = unpackAttributes(container); + ListBuffer compounds = ListBuffer.lb(); + for (Attribute a : contained0) + if (a instanceof Attribute.Compound) + compounds = compounds.append((Attribute.Compound)a); + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); + + int size = (direct == null ? 0 : 1) + contained.length; + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + + // if direct && container, which is first? + int insert = -1; + int length = arr.length; + if (directIndex >= 0 && containerIndex >= 0) { + if (directIndex < containerIndex) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 1; + } else { + arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 0; + length--; + } + } else if (directIndex >= 0) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + return arr; + } else { + // Only container + insert = 0; + } + + for (int i = 0; i + insert < length; i++) + arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType); + + return arr; + } + + // + + // + + /** + * An internal-use utility that creates a runtime view of an + * annotation. This is the implementation of + * TypeMirror.getAnnotation(Class). + */ + public static A getAnnotation(AnnotatedType annotated, Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + Attribute.Compound c = getAttribute(annotated, annoType); + return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType); + } + + // Helper to getAnnotation[s] + private static Attribute.Compound getAttribute(Type annotated, + Class annoType) { + String name = annoType.getName(); + + for (Attribute.Compound anno : annotated.getAnnotationMirrors()) { + if (name.equals(anno.type.tsym.flatName().toString())) + return anno; + } + + return null; + } + + /** + * An internal-use utility that creates a runtime view of + * annotations. This is the implementation of + * TypeMirror.getAnnotationsByType(Class). + */ + public static A[] getAnnotationsByType(AnnotatedType annotated, Class annoType) { + if (!annoType.isAnnotation()) + throw new IllegalArgumentException("Not an annotation type: " + + annoType); + // If annoType does not declare a container this is equivalent to wrapping + // getAnnotation(...) in an array. + Class containerType = getContainer(annoType); + if (containerType == null) { + A res = getAnnotation(annotated, annoType); + int size; + if (res == null) { + size = 0; + } else { + size = 1; + } + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + if (res != null) + arr[0] = res; + return arr; + } + + // So we have a containing type + String name = annoType.getName(); + String annoTypeName = annoType.getSimpleName(); + String containerTypeName = containerType.getSimpleName(); + int directIndex = -1, containerIndex = -1; + Attribute.Compound direct = null, container = null; + Attribute.Compound[] rawAttributes = annotated.getAnnotationMirrors().toArray(new Attribute.Compound[0]); + + // Find directly present annotations + for (int i = 0; i < rawAttributes.length; i++) { + if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + directIndex = i; + direct = rawAttributes[i]; + } else if(containerTypeName != null && + containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { + containerIndex = i; + container = rawAttributes[i]; + } + } + + // Pack them in an array + Attribute[] contained0 = new Attribute[0]; + if (container != null) + contained0 = unpackAttributes(container); + ListBuffer compounds = ListBuffer.lb(); + for (Attribute a : contained0) { + if (a instanceof Attribute.Compound) + compounds = compounds.append((Attribute.Compound)a); + } + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); + + int size = (direct == null ? 0 : 1) + contained.length; + @SuppressWarnings("unchecked") // annoType is the Class for A + A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); + + // if direct && container, which is first? + int insert = -1; + int length = arr.length; + if (directIndex >= 0 && containerIndex >= 0) { + if (directIndex < containerIndex) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 1; + } else { + arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + insert = 0; + length--; + } + } else if (directIndex >= 0) { + arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); + return arr; + } else { + // Only container + insert = 0; + } + + for (int i = 0; i + insert < length; i++) + arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType); + + return arr; + } + + // + + // + + // Needed to unpack the runtime view of containing annotations + private static final Class REPEATABLE_CLASS = initRepeatable(); + private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod(); + + private static Class initRepeatable() { + try { + // Repeatable will not be available when bootstrapping on + // JDK 7 so use a reflective lookup instead of a class + // literal for Repeatable.class. + return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class); + } catch (ClassNotFoundException e) { + return null; + } catch (SecurityException e) { + return null; + } + } + + private static Method initValueElementMethod() { + if (REPEATABLE_CLASS == null) + return null; + + Method m = null; + try { + m = REPEATABLE_CLASS.getMethod("value"); + if (m != null) + m.setAccessible(true); + return m; + } catch (NoSuchMethodException e) { + return null; + } + } + + // Helper to getAnnotations + private static Class getContainer(Class annoType) { + // Since we can not refer to java.lang.annotation.Repeatable until we are + // bootstrapping with java 8 we need to get the Repeatable annotation using + // reflective invocations instead of just using its type and element method. + if (REPEATABLE_CLASS != null && + VALUE_ELEMENT_METHOD != null) { + // Get the Repeatable instance on the annotations declaration + Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS); + if (repeatable != null) { + try { + // Get the value element, it should be a class + // indicating the containing annotation type + @SuppressWarnings("unchecked") + Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable); + if (containerType == null) + return null; + + return containerType; + } catch (ClassCastException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } catch (InvocationTargetException e ) { + return null; + } + } + } + return null; + } + + // Helper to getAnnotations + private static Attribute[] unpackAttributes(Attribute.Compound container) { + // We now have an instance of the container, + // unpack it returning an instance of the + // contained type or null + return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values; + } + + // +} diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/model/JavacElements.java --- a/src/share/classes/com/sun/tools/javac/model/JavacElements.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacElements.java Mon Mar 18 18:33:13 2013 -0700 @@ -25,10 +25,6 @@ package com.sun.tools.javac.model; -import java.lang.annotation.Annotation; -import java.lang.annotation.Inherited; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Map; import javax.lang.model.SourceVersion; @@ -40,7 +36,6 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.comp.Env; @@ -98,237 +93,6 @@ enter = Enter.instance(context); } - /** - * An internal-use utility that creates a runtime view of an - * annotation. This is the implementation of - * Element.getAnnotation(Class). - */ - public static A getAnnotation(Symbol annotated, - Class annoType) { - if (!annoType.isAnnotation()) - throw new IllegalArgumentException("Not an annotation type: " - + annoType); - Attribute.Compound c; - if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { - c = getAttributeOnClass((ClassSymbol)annotated, annoType); - } else { - c = getAttribute(annotated, annoType); - } - return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType); - } - - // Helper to getAnnotation[s] - private static Attribute.Compound getAttribute(Symbol annotated, - Class annoType) { - String name = annoType.getName(); - - for (Attribute.Compound anno : annotated.getRawAttributes()) - if (name.equals(anno.type.tsym.flatName().toString())) - return anno; - - return null; - } - // Helper to getAnnotation[s] - private static Attribute.Compound getAttributeOnClass(ClassSymbol annotated, - Class annoType) { - boolean inherited = annoType.isAnnotationPresent(Inherited.class); - Attribute.Compound result = null; - while (annotated.name != annotated.name.table.names.java_lang_Object) { - result = getAttribute(annotated, annoType); - if (result != null || !inherited) - break; - Type sup = annotated.getSuperclass(); - if (!sup.hasTag(CLASS) || sup.isErroneous()) - break; - annotated = (ClassSymbol) sup.tsym; - } - return result; - } - - /** - * An internal-use utility that creates a runtime view of - * annotations. This is the implementation of - * Element.getAnnotations(Class). - */ - public static A[] getAnnotations(Symbol annotated, - Class annoType) { - if (!annoType.isAnnotation()) - throw new IllegalArgumentException("Not an annotation type: " - + annoType); - // If annoType does not declare a container this is equivalent to wrapping - // getAnnotation(...) in an array. - Class containerType = getContainer(annoType); - if (containerType == null) { - A res = getAnnotation(annotated, annoType); - int size; - if (res == null) { - size = 0; - } else { - size = 1; - } - @SuppressWarnings("unchecked") // annoType is the Class for A - A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); - if (res != null) - arr[0] = res; - return arr; - } - - // So we have a containing type - String name = annoType.getName(); - String annoTypeName = annoType.getSimpleName(); - String containerTypeName = containerType.getSimpleName(); - int directIndex = -1, containerIndex = -1; - Attribute.Compound direct = null, container = null; - Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]); - - // Find directly present annotations - for (int i = 0; i < rawAttributes.length; i++) { - if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { - directIndex = i; - direct = rawAttributes[i]; - } else if(containerTypeName != null && - containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { - containerIndex = i; - container = rawAttributes[i]; - } - } - // Deal with inherited annotations - if (annotated.kind == Kinds.TYP && - (annotated instanceof ClassSymbol)) { - ClassSymbol s = (ClassSymbol)annotated; - if (direct == null && container == null) { - direct = getAttributeOnClass(s, annoType); - container = getAttributeOnClass(s, containerType); - - // both are inherited and found, put container last - if (direct != null && container != null) { - directIndex = 0; - containerIndex = 1; - } else if (direct != null) { - directIndex = 0; - } else { - containerIndex = 0; - } - } else if (direct == null) { - direct = getAttributeOnClass(s, annoType); - if (direct != null) - directIndex = containerIndex + 1; - } else if (container == null) { - container = getAttributeOnClass(s, containerType); - if (container != null) - containerIndex = directIndex + 1; - } - } - - // Pack them in an array - Attribute[] contained0 = new Attribute[0]; - if (container != null) - contained0 = unpackAttributes(container); - ListBuffer compounds = ListBuffer.lb(); - for (Attribute a : contained0) - if (a instanceof Attribute.Compound) - compounds = compounds.append((Attribute.Compound)a); - Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); - - int size = (direct == null ? 0 : 1) + contained.length; - @SuppressWarnings("unchecked") // annoType is the Class for A - A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size); - - // if direct && container, which is first? - int insert = -1; - int length = arr.length; - if (directIndex >= 0 && containerIndex >= 0) { - if (directIndex < containerIndex) { - arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); - insert = 1; - } else { - arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType); - insert = 0; - length--; - } - } else if (directIndex >= 0) { - arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType); - return arr; - } else { - // Only container - insert = 0; - } - - for (int i = 0; i + insert < length; i++) - arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType); - - return arr; - } - - // Needed to unpack the runtime view of containing annotations - private static final Class REPEATABLE_CLASS = initRepeatable(); - private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod(); - - private static Class initRepeatable() { - try { - // Repeatable will not be available when bootstrapping on - // JDK 7 so use a reflective lookup instead of a class - // literal for Repeatable.class. - return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class); - } catch (ClassNotFoundException e) { - return null; - } catch (SecurityException e) { - return null; - } - } - private static Method initValueElementMethod() { - if (REPEATABLE_CLASS == null) - return null; - - Method m = null; - try { - m = REPEATABLE_CLASS.getMethod("value"); - if (m != null) - m.setAccessible(true); - return m; - } catch (NoSuchMethodException e) { - return null; - } - } - - // Helper to getAnnotations - private static Class getContainer(Class annoType) { - // Since we can not refer to java.lang.annotation.Repeatable until we are - // bootstrapping with java 8 we need to get the Repeatable annotation using - // reflective invocations instead of just using its type and element method. - if (REPEATABLE_CLASS != null && - VALUE_ELEMENT_METHOD != null) { - // Get the Repeatable instance on the annotations declaration - Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS); - if (repeatable != null) { - try { - // Get the value element, it should be a class - // indicating the containing annotation type - @SuppressWarnings("unchecked") - Class containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable); - if (containerType == null) - return null; - - return containerType; - } catch (ClassCastException e) { - return null; - } catch (IllegalAccessException e) { - return null; - } catch (InvocationTargetException e ) { - return null; - } - } - } - return null; - } - // Helper to getAnnotations - private static Attribute[] unpackAttributes(Attribute.Compound container) { - // We now have an instance of the container, - // unpack it returning an instance of the - // contained type or null - return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values; - } - public PackageSymbol getPackageElement(CharSequence name) { String strName = name.toString(); if (strName.equals("")) diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/com/sun/tools/javac/model/JavacTypes.java --- a/src/share/classes/com/sun/tools/javac/model/JavacTypes.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacTypes.java Mon Mar 18 18:33:13 2013 -0700 @@ -25,7 +25,6 @@ package com.sun.tools.javac.model; -import java.lang.annotation.Annotation; import java.util.Collections; import java.util.EnumSet; import java.util.LinkedHashSet; diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/AnnotatedConstruct.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/javax/lang/model/AnnotatedConstruct.java Mon Mar 18 18:33:13 2013 -0700 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.lang.model; + +import java.lang.annotation.Annotation; +import java.util.List; +import javax.lang.model.element.*; + +/** + * Represent a construct that can have annotations. + * + * When annotations are on an {@linkplain element.Element element}, + * the are on a declaration. When annotations are on a {@linkplain + * type.TypeMirror type}, they are on a use of a type. + * + * @since 1.8 + */ +public interface AnnotatedConstruct { + /** + * Returns the annotations that are directly present on this + * element or type use. + * + * @return the annotations directly present on this element or type use; + * an empty list if there are none + */ + List getAnnotationMirrors(); + + /** + * Returns this element's or type use's annotation for the + * specified type if such an annotation is present, else {@code + * null}. The annotation may be either inherited or directly + * present on this element. + * + *

The annotation returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return this element's or type use's annotation for the + * specified annotation type if present on this element, else + * {@code null} + * + * @see #getAnnotationMirrors() + * @see java.lang.reflect.AnnotatedElement#getAnnotation + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A getAnnotation(Class annotationType); + + /** + * Returns annotations that are present on this element or type use. + * + * If there are no annotations present on this element or type use, + * the return value is an array of length 0. + * + * The difference between this method and {@link #getAnnotation(Class)} + * is that this method detects if its argument is a repeatable + * annotation type (JLS 9.6), and if so, attempts to find one or more + * annotations of that type by "looking through" a container annotation. + * + *

The annotations returned by this method could contain an element + * whose value is of type {@code Class}. + * This value cannot be returned directly: information necessary to + * locate and load a class (such as the class loader to use) is + * not available, and the class might not be loadable at all. + * Attempting to read a {@code Class} object by invoking the relevant + * method on the returned annotation + * will result in a {@link MirroredTypeException}, + * from which the corresponding {@link TypeMirror} may be extracted. + * Similarly, attempting to read a {@code Class[]}-valued element + * will result in a {@link MirroredTypesException}. + * + *

+ * Note: This method is unlike others in this and related + * interfaces. It operates on runtime reflective information — + * representations of annotation types currently loaded into the + * VM — rather than on the representations defined by and used + * throughout these interfaces. Consequently, calling methods on + * the returned annotation object can throw many of the exceptions + * that can be thrown when calling methods on an annotation object + * returned by core reflection. This method is intended for + * callers that are written to operate on a known, fixed set of + * annotation types. + *
+ * + * @param
the annotation type + * @param annotationType the {@code Class} object corresponding to + * the annotation type + * @return this element's annotations for the specified annotation + * type if present on this element, else an empty array + * + * @see #getAnnotationMirrors() + * @see #getAnnotation(java.lang.Class) + * @see java.lang.reflect.AnnotatedElement#getAnnotationsByType + * @see EnumConstantNotPresentException + * @see AnnotationTypeMismatchException + * @see IncompleteAnnotationException + * @see MirroredTypeException + * @see MirroredTypesException + */ + A[] getAnnotationsByType(Class annotationType); +} diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/element/Element.java --- a/src/share/classes/javax/lang/model/element/Element.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/javax/lang/model/element/Element.java Mon Mar 18 18:33:13 2013 -0700 @@ -60,8 +60,7 @@ * @see TypeMirror * @since 1.6 */ -public interface Element { - +public interface Element extends javax.lang.model.AnnotatedConstruct { /** * Returns the type defined by this element. * @@ -89,119 +88,6 @@ ElementKind getKind(); /** - * Returns the annotations that are directly present on this element. - * - *

To get inherited annotations as well, use - * {@link Elements#getAllAnnotationMirrors(Element) getAllAnnotationMirrors}. - * - * @see ElementFilter - * - * @return the annotations directly present on this element; - * an empty list if there are none - */ - List getAnnotationMirrors(); - - /** - * Returns this element's annotation for the specified type if - * such an annotation is present, else {@code null}. The - * annotation may be either inherited or directly present on this - * element. - * - *

The annotation returned by this method could contain an element - * whose value is of type {@code Class}. - * This value cannot be returned directly: information necessary to - * locate and load a class (such as the class loader to use) is - * not available, and the class might not be loadable at all. - * Attempting to read a {@code Class} object by invoking the relevant - * method on the returned annotation - * will result in a {@link MirroredTypeException}, - * from which the corresponding {@link TypeMirror} may be extracted. - * Similarly, attempting to read a {@code Class[]}-valued element - * will result in a {@link MirroredTypesException}. - * - *

- * Note: This method is unlike others in this and related - * interfaces. It operates on runtime reflective information — - * representations of annotation types currently loaded into the - * VM — rather than on the representations defined by and used - * throughout these interfaces. Consequently, calling methods on - * the returned annotation object can throw many of the exceptions - * that can be thrown when calling methods on an annotation object - * returned by core reflection. This method is intended for - * callers that are written to operate on a known, fixed set of - * annotation types. - *
- * - * @param
the annotation type - * @param annotationType the {@code Class} object corresponding to - * the annotation type - * @return this element's annotation for the specified annotation - * type if present on this element, else {@code null} - * - * @see #getAnnotationMirrors() - * @see java.lang.reflect.AnnotatedElement#getAnnotation - * @see EnumConstantNotPresentException - * @see AnnotationTypeMismatchException - * @see IncompleteAnnotationException - * @see MirroredTypeException - * @see MirroredTypesException - */ - A getAnnotation(Class annotationType); - - /** - * Returns annotations that are present on this element. - * - * If there are no annotations present on this element, the return - * value is an array of length 0. - * - * The difference between this method and {@link #getAnnotation(Class)} - * is that this method detects if its argument is a repeatable - * annotation type (JLS 9.6), and if so, attempts to find one or more - * annotations of that type by "looking through" a container annotation. - * - *

The annotations returned by this method could contain an element - * whose value is of type {@code Class}. - * This value cannot be returned directly: information necessary to - * locate and load a class (such as the class loader to use) is - * not available, and the class might not be loadable at all. - * Attempting to read a {@code Class} object by invoking the relevant - * method on the returned annotation - * will result in a {@link MirroredTypeException}, - * from which the corresponding {@link TypeMirror} may be extracted. - * Similarly, attempting to read a {@code Class[]}-valued element - * will result in a {@link MirroredTypesException}. - * - *

- * Note: This method is unlike others in this and related - * interfaces. It operates on runtime reflective information — - * representations of annotation types currently loaded into the - * VM — rather than on the representations defined by and used - * throughout these interfaces. Consequently, calling methods on - * the returned annotation object can throw many of the exceptions - * that can be thrown when calling methods on an annotation object - * returned by core reflection. This method is intended for - * callers that are written to operate on a known, fixed set of - * annotation types. - *
- * - * @param
the annotation type - * @param annotationType the {@code Class} object corresponding to - * the annotation type - * @return this element's annotations for the specified annotation - * type if present on this element, else an empty array - * - * @see #getAnnotationMirrors() - * @see #getAnnotation(java.lang.Class) - * @see java.lang.reflect.AnnotatedElement#getAnnotationsByType - * @see EnumConstantNotPresentException - * @see AnnotationTypeMismatchException - * @see IncompleteAnnotationException - * @see MirroredTypeException - * @see MirroredTypesException - */ - A[] getAnnotationsByType(Class annotationType); - - /** * Returns the modifiers of this element, excluding annotations. * Implicit modifiers, such as the {@code public} and {@code static} * modifiers of interface members, are included. @@ -325,6 +211,19 @@ */ int hashCode(); + + /** + * {@inheritDoc} + * + *

To get inherited annotations as well, use {@link + * Elements#getAllAnnotationMirrors(Element) + * getAllAnnotationMirrors}. + * + * @see ElementFilter + * @since 1.6 + */ + @Override + List getAnnotationMirrors(); /** * Applies a visitor to this element. * diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/element/ExecutableElement.java --- a/src/share/classes/javax/lang/model/element/ExecutableElement.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/javax/lang/model/element/ExecutableElement.java Mon Mar 18 18:33:13 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,25 @@ List getParameters(); /** + * Returns the receiver type of this executable, + * or {@link javax.lang.model.type.NoType NoType} with + * kind {@link javax.lang.model.type.TypeKind#NONE NONE} + * if the executable has no receiver type. + * + * An executable which is an instance method, or a constructor of an + * inner class, has a receiver type derived from the {@linkplain + * #getEnclosingElement declaring type}. + * + * An executable which is a static method, or a constructor of a + * non-inner class, or an initializer (static or instance), has no + * receiver type. + * + * @return the receiver type of this executable + * @since 1.8 + */ + TypeMirror getReceiverType(); + + /** * Returns {@code true} if this method or constructor accepts a variable * number of arguments and returns {@code false} otherwise. * diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/type/ExecutableType.java --- a/src/share/classes/javax/lang/model/type/ExecutableType.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/javax/lang/model/type/ExecutableType.java Mon Mar 18 18:33:13 2013 -0700 @@ -78,6 +78,25 @@ List getParameterTypes(); /** + * Returns the receiver type of this executable, + * or {@link javax.lang.model.type.NoType NoType} with + * kind {@link javax.lang.model.type.TypeKind#NONE NONE} + * if the executable has no receiver type. + * + * An executable which is an instance method, or a constructor of an + * inner class, has a receiver type derived from the {@linkplain + * #getEnclosingElement declaring type}. + * + * An executable which is a static method, or a constructor of a + * non-inner class, or an initializer (static or instance), has no + * receiver type. + * + * @return the receiver type of this executable + * @since 1.8 + */ + TypeMirror getReceiverType(); + + /** * Returns the exceptions and other throwables listed in this * executable's {@code throws} clause. * diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/type/TypeMirror.java --- a/src/share/classes/javax/lang/model/type/TypeMirror.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/javax/lang/model/type/TypeMirror.java Mon Mar 18 18:33:13 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package javax.lang.model.type; +import java.lang.annotation.Annotation; +import java.util.List; import javax.lang.model.element.*; import javax.lang.model.util.Types; @@ -55,7 +57,7 @@ * @see Types * @since 1.6 */ -public interface TypeMirror { +public interface TypeMirror extends javax.lang.model.AnnotatedConstruct { /** * Returns the {@code kind} of this type. diff -r 40adaf938847 -r 97f6839673d6 src/share/classes/javax/lang/model/util/Types.java --- a/src/share/classes/javax/lang/model/util/Types.java Mon Mar 18 14:40:32 2013 -0700 +++ b/src/share/classes/javax/lang/model/util/Types.java Mon Mar 18 18:33:13 2013 -0700 @@ -59,6 +59,13 @@ /** * Tests whether two {@code TypeMirror} objects represent the same type. * + *

Since annotations are only meta-data associated with a type, + * the set of annotations on either argument is not taken + * into account when computing whether or not two {@code + * TypeMirror} objects are the same type. In particular, two + * {@code TypeMirror} objects can have different annotations and + * still be considered the same. + * *

Caveat: if either of the arguments to this method represents a * wildcard, this method will return false. As a consequence, a wildcard * is not the same type as itself. This might be surprising at first,