Mon, 22 Apr 2013 10:24:19 +0200
8011027: Type parameter annotations not passed through to javax.lang.model
Reviewed-by: jjg, darcy
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Apr 19 11:10:40 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Apr 22 10:24:19 2013 +0200 1.3 @@ -465,19 +465,12 @@ 1.4 * This is the implementation for {@code 1.5 * javax.lang.model.element.Element.getAnnotationMirrors()}. 1.6 */ 1.7 - public final List<? extends AnnotationMirror> getAnnotationMirrors() { 1.8 + @Override 1.9 + public List<Attribute.Compound> getAnnotationMirrors() { 1.10 return getRawAttributes(); 1.11 } 1.12 1.13 /** 1.14 - * TODO: Should there be a {@code 1.15 - * javax.lang.model.element.Element.getTypeAnnotationMirrors()}. 1.16 - */ 1.17 - public final List<Attribute.TypeCompound> getTypeAnnotationMirrors() { 1.18 - return getRawTypeAttributes(); 1.19 - } 1.20 - 1.21 - /** 1.22 * @deprecated this method should never be used by javac internally. 1.23 */ 1.24 @Deprecated 1.25 @@ -657,6 +650,24 @@ 1.26 } 1.27 1.28 @Override 1.29 + public List<Attribute.Compound> getAnnotationMirrors() { 1.30 + return onlyTypeVariableAnnotations(owner.getRawTypeAttributes()); 1.31 + } 1.32 + 1.33 + private List<Attribute.Compound> onlyTypeVariableAnnotations( 1.34 + List<Attribute.TypeCompound> candidates) { 1.35 + // Declaration annotations on TypeParameters are stored in type attributes 1.36 + List<Attribute.Compound> res = List.nil(); 1.37 + for (Attribute.TypeCompound a : candidates) { 1.38 + if (a.position.type == TargetType.CLASS_TYPE_PARAMETER || 1.39 + a.position.type == TargetType.METHOD_TYPE_PARAMETER) 1.40 + res = res.prepend(a); 1.41 + } 1.42 + 1.43 + return res = res.reverse(); 1.44 + } 1.45 + 1.46 + @Override 1.47 public <R, P> R accept(ElementVisitor<R, P> v, P p) { 1.48 return v.visitTypeParameter(this, p); 1.49 }
2.1 --- a/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Fri Apr 19 11:10:40 2013 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Mon Apr 22 10:24:19 2013 +0200 2.3 @@ -206,7 +206,7 @@ 2.4 sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { 2.5 // Make sure all type annotations from the symbol are also 2.6 // on the owner. 2.7 - sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors()); 2.8 + sym.owner.annotations.appendUniqueTypes(sym.getRawTypeAttributes()); 2.9 } 2.10 } 2.11
3.1 --- a/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Fri Apr 19 11:10:40 2013 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Mon Apr 22 10:24:19 2013 +0200 3.3 @@ -33,10 +33,13 @@ 3.4 import com.sun.tools.javac.code.Kinds; 3.5 import com.sun.tools.javac.code.Symbol; 3.6 import com.sun.tools.javac.code.Symbol.ClassSymbol; 3.7 +import com.sun.tools.javac.code.Symbol.TypeVariableSymbol; 3.8 +import com.sun.tools.javac.code.TargetType; 3.9 import com.sun.tools.javac.code.Type; 3.10 import com.sun.tools.javac.code.Type.AnnotatedType; 3.11 import com.sun.tools.javac.util.ListBuffer; 3.12 import static com.sun.tools.javac.code.TypeTag.CLASS; 3.13 +import com.sun.tools.javac.util.List; 3.14 3.15 /** 3.16 * Utility methods for operating on annotated constructs. 3.17 @@ -61,8 +64,12 @@ 3.18 throw new IllegalArgumentException("Not an annotation type: " 3.19 + annoType); 3.20 Attribute.Compound c; 3.21 - if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { 3.22 + if (annotated.kind == Kinds.TYP && 3.23 + annotated instanceof ClassSymbol) { 3.24 c = getAttributeOnClass((ClassSymbol)annotated, annoType); 3.25 + } else if (annotated.kind == Kinds.TYP && 3.26 + annotated instanceof TypeVariableSymbol) { 3.27 + c = getAttributeOnTypeVariable((TypeVariableSymbol)annotated, annoType); 3.28 } else { 3.29 c = getAttribute(annotated, annoType); 3.30 } 3.31 @@ -83,6 +90,24 @@ 3.32 } 3.33 3.34 // Helper to getAnnotation[s] 3.35 + private static <A extends Annotation> Attribute.Compound 3.36 + getAttributeOnTypeVariable(TypeVariableSymbol annotated, Class<A> annoType) { 3.37 + String name = annoType.getName(); 3.38 + 3.39 + // Declaration annotations on type variables are stored in type attributes 3.40 + // on the owner of the TypeVariableSymbol 3.41 + List<Attribute.Compound> res = List.nil(); 3.42 + List<Attribute.TypeCompound> candidates = annotated.owner.getRawTypeAttributes(); 3.43 + for (Attribute.TypeCompound anno : candidates) 3.44 + if (anno.position.type == TargetType.CLASS_TYPE_PARAMETER || 3.45 + anno.position.type == TargetType.METHOD_TYPE_PARAMETER) 3.46 + if (name.equals(anno.type.tsym.flatName().toString())) 3.47 + return anno; 3.48 + 3.49 + return null; 3.50 + } 3.51 + 3.52 + // Helper to getAnnotation[s] 3.53 private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated, 3.54 Class<A> annoType) { 3.55 boolean inherited = annoType.isAnnotationPresent(Inherited.class);
4.1 --- a/src/share/classes/com/sun/tools/javac/model/JavacElements.java Fri Apr 19 11:10:40 2013 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/model/JavacElements.java Mon Apr 22 10:24:19 2013 +0200 4.3 @@ -402,9 +402,10 @@ 4.4 * @param e the element being examined 4.5 * @return all annotations of the element 4.6 */ 4.7 + @Override 4.8 public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { 4.9 Symbol sym = cast(Symbol.class, e); 4.10 - List<Attribute.Compound> annos = sym.getRawAttributes(); 4.11 + List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 4.12 while (sym.getKind() == ElementKind.CLASS) { 4.13 Type sup = ((ClassSymbol) sym).getSuperclass(); 4.14 if (!sup.hasTag(CLASS) || sup.isErroneous() || 4.15 @@ -413,7 +414,7 @@ 4.16 } 4.17 sym = sup.tsym; 4.18 List<Attribute.Compound> oldAnnos = annos; 4.19 - List<Attribute.Compound> newAnnos = sym.getRawAttributes(); 4.20 + List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors(); 4.21 for (Attribute.Compound anno : newAnnos) { 4.22 if (isInherited(anno.type) && 4.23 !containsAnnoOfType(oldAnnos, anno.type)) {
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java Mon Apr 22 10:24:19 2013 +0200 5.3 @@ -0,0 +1,190 @@ 5.4 +/* 5.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8011027 5.30 + * @library /tools/javac/lib 5.31 + * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations 5.32 + * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java 5.33 + */ 5.34 + 5.35 +import java.util.*; 5.36 +import java.lang.annotation.*; 5.37 +import javax.annotation.processing.*; 5.38 +import javax.lang.model.element.*; 5.39 +import javax.lang.model.util.*; 5.40 +import javax.tools.*; 5.41 + 5.42 +public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor { 5.43 + int round = 0; 5.44 + 5.45 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 5.46 + if (++round == 1) { 5.47 + int found = (new Scanner()).scan(roundEnv.getRootElements(), null); 5.48 + if (found == expect) { 5.49 + ; //nop 5.50 + } else { 5.51 + error("unexpected number of results: expected " + expect 5.52 + + ", found " + found); 5.53 + } 5.54 + 5.55 + } 5.56 + return true; 5.57 + } 5.58 + 5.59 + class Scanner extends JavacTestingAbstractProcessor.ElementScanner<Integer,Void> { 5.60 + @Override 5.61 + public Integer visitExecutable(ExecutableElement e, Void p) { 5.62 + super.visitExecutable(e, p); 5.63 + found += check(e, e.getTypeParameters()); 5.64 + return found; 5.65 + } 5.66 + 5.67 + @Override 5.68 + public Integer visitType(TypeElement e, Void p) { 5.69 + super.visitType(e, p); 5.70 + found += check(e, e.getTypeParameters()); 5.71 + return found; 5.72 + } 5.73 + 5.74 + int found; 5.75 + } 5.76 + 5.77 + int check(Element e, List<? extends TypeParameterElement> typarams) { 5.78 + if (typarams.isEmpty()) 5.79 + return 0; 5.80 + if (typarams.size() != 1) 5.81 + return 0; 5.82 + 5.83 + for (TypeParameterElement tpe: typarams) { 5.84 + boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors()); 5.85 + boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe)); 5.86 + boolean b3 = checkGetAnnotation(tpe); 5.87 + boolean b4 = checkGetAnnotations(tpe); 5.88 + return b1 && b2 && b3 && b4 ? 1 : 0; 5.89 + } 5.90 + return 0; 5.91 + } 5.92 + 5.93 + boolean checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l) { 5.94 + if (l.size() != 3) { 5.95 + error("To few annotations, got " + l.size() + 5.96 + ", should be 3", tpe); 5.97 + return false; 5.98 + } 5.99 + 5.100 + AnnotationMirror m = l.get(0); 5.101 + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) { 5.102 + error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement()); 5.103 + return false; 5.104 + } 5.105 + m = l.get(1); 5.106 + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) { 5.107 + error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement()); 5.108 + return false; 5.109 + } 5.110 + m = l.get(2); 5.111 + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) { 5.112 + error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement()); 5.113 + return false; 5.114 + } 5.115 + return true; 5.116 + } 5.117 + 5.118 + boolean checkGetAnnotation(TypeParameterElement tpe) { 5.119 + Foo f = tpe.getAnnotation(Foo.class); 5.120 + if (f == null) 5.121 + error("Expecting @Foo to be present in getAnnotation()", tpe); 5.122 + 5.123 + Bar b = tpe.getAnnotation(Bar.class); 5.124 + if (b == null) 5.125 + error("Expecting @Bar to be present in getAnnotation()", tpe); 5.126 + 5.127 + Baz z = tpe.getAnnotation(Baz.class); 5.128 + if (z == null) 5.129 + error("Expecting @Baz to be present in getAnnotation()", tpe); 5.130 + 5.131 + return f != null && 5.132 + b != null && 5.133 + z != null; 5.134 + } 5.135 + 5.136 + boolean checkGetAnnotations(TypeParameterElement tpe) { 5.137 + Foo[] f = tpe.getAnnotationsByType(Foo.class); 5.138 + if (f.length != 1) { 5.139 + error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe); 5.140 + return false; 5.141 + } 5.142 + 5.143 + Bar[] b = tpe.getAnnotationsByType(Bar.class); 5.144 + if (b.length != 1) { 5.145 + error("Expecting 1 @Bar to be present in getAnnotationsByType()", tpe); 5.146 + return false; 5.147 + } 5.148 + 5.149 + Baz[] z = tpe.getAnnotationsByType(Baz.class); 5.150 + if (z.length != 1) { 5.151 + error("Expecting 1 @Baz to be present in getAnnotationsByType()", tpe); 5.152 + return false; 5.153 + } 5.154 + 5.155 + return true; 5.156 + } 5.157 + 5.158 + void note(String msg) { 5.159 + messager.printMessage(Diagnostic.Kind.NOTE, msg); 5.160 + } 5.161 + 5.162 + void note(String msg, Element e) { 5.163 + messager.printMessage(Diagnostic.Kind.NOTE, msg, e); 5.164 + } 5.165 + 5.166 + void error(String msg, Element e) { 5.167 + messager.printMessage(Diagnostic.Kind.ERROR, msg, e); 5.168 + } 5.169 + 5.170 + void error(String msg) { 5.171 + messager.printMessage(Diagnostic.Kind.ERROR, msg); 5.172 + } 5.173 + 5.174 + // additional generic elements to test 5.175 + <@Foo @Bar @Baz X> X m(X x) { return x; } 5.176 + 5.177 + interface Intf<@Foo @Bar @Baz X> { X m() ; } 5.178 + 5.179 + class Class<@Foo @Bar @Baz X> { 5.180 + <@Foo @Bar @Baz Y> Class() { } 5.181 + } 5.182 + 5.183 + final int expect = 5; // top level class, plus preceding examples 5.184 +} 5.185 + 5.186 +@Target(ElementType.TYPE_PARAMETER) 5.187 +@interface Foo {} 5.188 + 5.189 +@Target(ElementType.TYPE_PARAMETER) 5.190 +@interface Bar {} 5.191 + 5.192 +@Target(ElementType.TYPE_PARAMETER) 5.193 +@interface Baz {}