Thu, 25 Jul 2013 11:02:27 +0200
8007961: javax.lang.model tests for repeating annotations fail in getAnnotationsByType
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 24 17:35:42 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Jul 25 11:02:27 2013 +0200 1.3 @@ -596,7 +596,7 @@ 1.4 1.5 // This method is part of the javax.lang.model API, do not use this in javac code. 1.6 public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(Class<A> annoType) { 1.7 - return JavacAnnoConstructs.getAnnotations(this, annoType); 1.8 + return JavacAnnoConstructs.getAnnotationsByType(this, annoType); 1.9 } 1.10 1.11 // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList
2.1 --- a/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Wed Jul 24 17:35:42 2013 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Thu Jul 25 11:02:27 2013 +0200 2.3 @@ -108,20 +108,38 @@ 2.4 } 2.5 2.6 // Helper to getAnnotation[s] 2.7 - private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated, 2.8 - Class<A> annoType) { 2.9 + private static <A extends Annotation> Attribute.Compound getAttributeOnClass( 2.10 + ClassSymbol annotated, 2.11 + final Class<A> annoType) 2.12 + { 2.13 boolean inherited = annoType.isAnnotationPresent(Inherited.class); 2.14 Attribute.Compound result = null; 2.15 - while (annotated.name != annotated.name.table.names.java_lang_Object) { 2.16 + 2.17 + result = getAttribute(annotated, annoType); 2.18 + if (result != null || !inherited) 2.19 + return result; 2.20 + 2.21 + while ((annotated = nextSupertypeToSearch(annotated)) != null) { 2.22 result = getAttribute(annotated, annoType); 2.23 - if (result != null || !inherited) 2.24 - break; 2.25 - Type sup = annotated.getSuperclass(); 2.26 - if (!sup.hasTag(CLASS) || sup.isErroneous()) 2.27 - break; 2.28 - annotated = (ClassSymbol) sup.tsym; 2.29 + if (result != null) 2.30 + return result; 2.31 } 2.32 - return result; 2.33 + return null; // no more supertypes to search 2.34 + } 2.35 + 2.36 + /** 2.37 + * Returns the next type to search for inherited annotations or {@code null} 2.38 + * if the next type can't be found. 2.39 + */ 2.40 + private static ClassSymbol nextSupertypeToSearch(ClassSymbol annotated) { 2.41 + if (annotated.name == annotated.name.table.names.java_lang_Object) 2.42 + return null; 2.43 + 2.44 + Type sup = annotated.getSuperclass(); 2.45 + if (!sup.hasTag(CLASS) || sup.isErroneous()) 2.46 + return null; 2.47 + 2.48 + return (ClassSymbol) sup.tsym; 2.49 } 2.50 2.51 /** 2.52 @@ -129,8 +147,9 @@ 2.53 * annotations. This is the implementation of 2.54 * Element.getAnnotations(Class). 2.55 */ 2.56 - public static <A extends Annotation> A[] getAnnotations(Symbol annotated, 2.57 - Class<A> annoType) { 2.58 + public static <A extends Annotation> A[] getAnnotationsByType(Symbol annotated, 2.59 + Class<A> annoType) 2.60 + { 2.61 if (!annoType.isAnnotation()) 2.62 throw new IllegalArgumentException("Not an annotation type: " 2.63 + annoType); 2.64 @@ -153,62 +172,48 @@ 2.65 } 2.66 2.67 // So we have a containing type 2.68 - String name = annoType.getName(); 2.69 String annoTypeName = annoType.getSimpleName(); 2.70 String containerTypeName = containerType.getSimpleName(); 2.71 int directIndex = -1, containerIndex = -1; 2.72 Attribute.Compound direct = null, container = null; 2.73 - Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]); 2.74 - 2.75 - // Find directly present annotations 2.76 - for (int i = 0; i < rawAttributes.length; i++) { 2.77 - if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { 2.78 - directIndex = i; 2.79 - direct = rawAttributes[i]; 2.80 + // Find directly (explicit or implicit) present annotations 2.81 + int index = -1; 2.82 + for (List<Attribute.Compound> list = annotated.getAnnotationMirrors(); 2.83 + !list.isEmpty(); 2.84 + list = list.tail) { 2.85 + Attribute.Compound attribute = list.head; 2.86 + index++; 2.87 + if (attribute.type.tsym.flatName().contentEquals(annoTypeName)) { 2.88 + directIndex = index; 2.89 + direct = attribute; 2.90 } else if(containerTypeName != null && 2.91 - containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { 2.92 - containerIndex = i; 2.93 - container = rawAttributes[i]; 2.94 + attribute.type.tsym.flatName().contentEquals(containerTypeName)) { 2.95 + containerIndex = index; 2.96 + container = attribute; 2.97 } 2.98 } 2.99 2.100 // Deal with inherited annotations 2.101 - if (annotated.kind == Kinds.TYP && 2.102 - (annotated instanceof ClassSymbol)) { 2.103 - ClassSymbol s = (ClassSymbol)annotated; 2.104 - if (direct == null && container == null) { 2.105 - direct = getAttributeOnClass(s, annoType); 2.106 - container = getAttributeOnClass(s, containerType); 2.107 - 2.108 - // both are inherited and found, put container last 2.109 - if (direct != null && container != null) { 2.110 - directIndex = 0; 2.111 - containerIndex = 1; 2.112 - } else if (direct != null) { 2.113 - directIndex = 0; 2.114 - } else { 2.115 - containerIndex = 0; 2.116 - } 2.117 - } else if (direct == null) { 2.118 - direct = getAttributeOnClass(s, annoType); 2.119 - if (direct != null) 2.120 - directIndex = containerIndex + 1; 2.121 - } else if (container == null) { 2.122 - container = getAttributeOnClass(s, containerType); 2.123 - if (container != null) 2.124 - containerIndex = directIndex + 1; 2.125 + if (direct == null && container == null) { 2.126 + if (annotated.kind == Kinds.TYP && 2.127 + (annotated instanceof ClassSymbol)) { 2.128 + ClassSymbol s = nextSupertypeToSearch((ClassSymbol)annotated); 2.129 + if (s != null) 2.130 + return getAnnotationsByType(s, annoType); 2.131 } 2.132 } 2.133 2.134 // Pack them in an array 2.135 - Attribute[] contained0 = new Attribute[0]; 2.136 + Attribute[] contained0 = null; 2.137 if (container != null) 2.138 contained0 = unpackAttributes(container); 2.139 ListBuffer<Attribute.Compound> compounds = ListBuffer.lb(); 2.140 - for (Attribute a : contained0) 2.141 - if (a instanceof Attribute.Compound) 2.142 - compounds = compounds.append((Attribute.Compound)a); 2.143 - Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); 2.144 + if (contained0 != null) { 2.145 + for (Attribute a : contained0) 2.146 + if (a instanceof Attribute.Compound) 2.147 + compounds = compounds.append((Attribute.Compound)a); 2.148 + } 2.149 + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[compounds.size()]); 2.150 2.151 int size = (direct == null ? 0 : 1) + contained.length; 2.152 @SuppressWarnings("unchecked") // annoType is the Class for A 2.153 @@ -298,35 +303,38 @@ 2.154 } 2.155 2.156 // So we have a containing type 2.157 - String name = annoType.getName(); 2.158 String annoTypeName = annoType.getSimpleName(); 2.159 String containerTypeName = containerType.getSimpleName(); 2.160 int directIndex = -1, containerIndex = -1; 2.161 Attribute.Compound direct = null, container = null; 2.162 - Attribute.Compound[] rawAttributes = annotated.getAnnotationMirrors().toArray(new Attribute.Compound[0]); 2.163 - 2.164 - // Find directly present annotations 2.165 - for (int i = 0; i < rawAttributes.length; i++) { 2.166 - if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { 2.167 - directIndex = i; 2.168 - direct = rawAttributes[i]; 2.169 + // Find directly (explicit or implicit) present annotations 2.170 + int index = -1; 2.171 + for (List<? extends Attribute.Compound> list = annotated.getAnnotationMirrors(); 2.172 + !list.isEmpty(); 2.173 + list = list.tail) { 2.174 + Attribute.Compound attribute = list.head; 2.175 + index++; 2.176 + if (attribute.type.tsym.flatName().contentEquals(annoTypeName)) { 2.177 + directIndex = index; 2.178 + direct = attribute; 2.179 } else if(containerTypeName != null && 2.180 - containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) { 2.181 - containerIndex = i; 2.182 - container = rawAttributes[i]; 2.183 + attribute.type.tsym.flatName().contentEquals(containerTypeName)) { 2.184 + containerIndex = index; 2.185 + container = attribute; 2.186 } 2.187 } 2.188 2.189 // Pack them in an array 2.190 - Attribute[] contained0 = new Attribute[0]; 2.191 + Attribute[] contained0 = null; 2.192 if (container != null) 2.193 contained0 = unpackAttributes(container); 2.194 ListBuffer<Attribute.Compound> compounds = ListBuffer.lb(); 2.195 - for (Attribute a : contained0) { 2.196 - if (a instanceof Attribute.Compound) 2.197 - compounds = compounds.append((Attribute.Compound)a); 2.198 + if (contained0 != null) { 2.199 + for (Attribute a : contained0) 2.200 + if (a instanceof Attribute.Compound) 2.201 + compounds = compounds.append((Attribute.Compound)a); 2.202 } 2.203 - Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]); 2.204 + Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[compounds.size()]); 2.205 2.206 int size = (direct == null ? 0 : 1) + contained.length; 2.207 @SuppressWarnings("unchecked") // annoType is the Class for A
3.1 --- a/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedA1Test.java Wed Jul 24 17:35:42 2013 -0700 3.2 +++ b/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedA1Test.java Thu Jul 25 11:02:27 2013 +0200 3.3 @@ -23,12 +23,11 @@ 3.4 3.5 /* 3.6 * @test 3.7 - * @bug 8004822 3.8 + * @bug 8004822 8007961 3.9 * @author mnunez 3.10 * @summary Language model api test basics for repeating annotations 3.11 * @library /tools/javac/lib 3.12 * @library supportingAnnotations 3.13 - * @ignore 8013407: test failures for repeating annotations 3.14 * @build JavacTestingAbstractProcessor ElementRepAnnoTester 3.15 * @compile -processor ElementRepAnnoTester -proc:only 3.16 * MixRepeatableAndOfficialContainerInheritedA1Test.java
4.1 --- a/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedB1Test.java Wed Jul 24 17:35:42 2013 -0700 4.2 +++ b/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedB1Test.java Thu Jul 25 11:02:27 2013 +0200 4.3 @@ -23,12 +23,11 @@ 4.4 4.5 /* 4.6 * @test 4.7 - * @bug 8004822 4.8 + * @bug 8004822 8007961 4.9 * @author mnunez 4.10 * @summary Language model api test basics for repeating annotations 4.11 * @library /tools/javac/lib 4.12 * @library supportingAnnotations 4.13 - * @ignore 8013407: test failures for repeating annotations 4.14 * @build JavacTestingAbstractProcessor ElementRepAnnoTester 4.15 * @compile -processor ElementRepAnnoTester -proc:only 4.16 * MixRepeatableAndOfficialContainerInheritedB1Test.java
5.1 --- a/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedB2Test.java Wed Jul 24 17:35:42 2013 -0700 5.2 +++ b/test/tools/javac/processing/model/element/repeatingAnnotations/MixRepeatableAndOfficialContainerInheritedB2Test.java Thu Jul 25 11:02:27 2013 +0200 5.3 @@ -23,12 +23,11 @@ 5.4 5.5 /* 5.6 * @test 5.7 - * @bug 8004822 5.8 + * @bug 8004822 8007961 5.9 * @author mnunez 5.10 * @summary Language model api test basics for repeating annotations 5.11 * @library /tools/javac/lib 5.12 * @library supportingAnnotations 5.13 - * @ignore 8013407: test failures for repeating annotations 5.14 * @build JavacTestingAbstractProcessor ElementRepAnnoTester 5.15 * @compile -processor ElementRepAnnoTester -proc:only 5.16 * MixRepeatableAndOfficialContainerInheritedB2Test.java
6.1 --- a/test/tools/javac/processing/model/element/repeatingAnnotations/RepeatableOverrideATest.java Wed Jul 24 17:35:42 2013 -0700 6.2 +++ b/test/tools/javac/processing/model/element/repeatingAnnotations/RepeatableOverrideATest.java Thu Jul 25 11:02:27 2013 +0200 6.3 @@ -23,12 +23,11 @@ 6.4 6.5 /* 6.6 * @test 6.7 - * @bug 8004822 6.8 + * @bug 8004822 8007961 6.9 * @author mnunez 6.10 * @summary Language model api test basics for repeating annotations 6.11 * @library /tools/javac/lib 6.12 * @library supportingAnnotations 6.13 - * @ignore 8013407: test failures for repeating annotations 6.14 * @build JavacTestingAbstractProcessor ElementRepAnnoTester 6.15 * @compile -processor ElementRepAnnoTester -proc:only RepeatableOverrideATest.java 6.16 */
7.1 --- a/test/tools/javac/processing/model/element/repeatingAnnotations/RepeatableOverrideBTest.java Wed Jul 24 17:35:42 2013 -0700 7.2 +++ b/test/tools/javac/processing/model/element/repeatingAnnotations/RepeatableOverrideBTest.java Thu Jul 25 11:02:27 2013 +0200 7.3 @@ -23,12 +23,11 @@ 7.4 7.5 /* 7.6 * @test 7.7 - * @bug 8004822 7.8 + * @bug 8004822 8007961 7.9 * @author mnunez 7.10 * @summary Language model api test basics for repeating annotations 7.11 * @library /tools/javac/lib 7.12 * @library supportingAnnotations 7.13 - * @ignore 8013407: test failures for repeating annotations 7.14 * @build JavacTestingAbstractProcessor ElementRepAnnoTester 7.15 * @compile -processor ElementRepAnnoTester -proc:only RepeatableOverrideBTest.java 7.16 */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/processing/model/inheritedByType/EnsureOrder.java Thu Jul 25 11:02:27 2013 +0200 8.3 @@ -0,0 +1,106 @@ 8.4 +/* 8.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +/** 8.28 + * @test 8.29 + * @summary test that order is respected when inheriting both legacy container and single anno 8.30 + * @bug 8007961 8.31 + * @library /tools/javac/lib 8.32 + * @build JavacTestingAbstractProcessor EnsureOrder 8.33 + * @compile -processor EnsureOrder -proc:only EnsureOrder.java 8.34 + */ 8.35 + 8.36 +import java.util.Set; 8.37 +import java.lang.annotation.*; 8.38 +import javax.annotation.processing.*; 8.39 +import javax.lang.model.SourceVersion; 8.40 +import static javax.lang.model.SourceVersion.*; 8.41 +import javax.lang.model.element.*; 8.42 +import javax.lang.model.util.*; 8.43 +import static javax.lang.model.util.ElementFilter.*; 8.44 +import static javax.tools.Diagnostic.Kind.*; 8.45 +import static javax.tools.StandardLocation.*; 8.46 +import com.sun.tools.javac.util.Assert; 8.47 + 8.48 +@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE}) 8.49 +@Inherited 8.50 +@Retention(RetentionPolicy.RUNTIME) 8.51 +@Repeatable(Foos.class) 8.52 +@interface Foo { 8.53 + int value(); 8.54 +} 8.55 + 8.56 +@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE}) 8.57 +@Inherited 8.58 +@Retention(RetentionPolicy.RUNTIME) 8.59 +@interface Foos { 8.60 + Foo[] value(); 8.61 +} 8.62 + 8.63 +@Foos({@Foo(0), @Foo(1)}) @Foo(2) 8.64 +class Base {} 8.65 + 8.66 +class Sub extends Base {} 8.67 + 8.68 +public class EnsureOrder<@Foos({@Foo(0), @Foo(1)}) @Foo(2)T> extends JavacTestingAbstractProcessor { 8.69 + public boolean process(Set<? extends TypeElement> annotations, 8.70 + RoundEnvironment roundEnv) { 8.71 + if (!roundEnv.processingOver()) { 8.72 + int hasRun = 0; 8.73 + for (Element element : roundEnv.getRootElements()) { 8.74 + Name elemName = element.getSimpleName(); 8.75 + if (elemName.contentEquals("Base")) { 8.76 + hasRun++; 8.77 + Foo[] foos = element.getAnnotationsByType(Foo.class); 8.78 + Assert.check(foos.length == 3); 8.79 + Assert.check(foos[0].value() == 0); 8.80 + Assert.check(foos[1].value() == 1); 8.81 + Assert.check(foos[2].value() == 2); 8.82 + } 8.83 + if (elemName.contentEquals("Sub")) { 8.84 + hasRun++; 8.85 + Foo[] foos = element.getAnnotationsByType(Foo.class); 8.86 + Assert.check(foos.length == 3); 8.87 + Assert.check(foos[0].value() == 0); 8.88 + Assert.check(foos[1].value() == 1); 8.89 + Assert.check(foos[2].value() == 2); 8.90 + } 8.91 + if (elemName.contentEquals("EnsureOrder")) { 8.92 + for (TypeParameterElement t : ((TypeElement)element).getTypeParameters()) { 8.93 + if (t.getSimpleName().contentEquals("T")) { 8.94 + hasRun++; 8.95 + Foo[] foos = t.getAnnotationsByType(Foo.class); 8.96 + Assert.check(foos.length == 3); 8.97 + Assert.check(foos[0].value() == 0); 8.98 + Assert.check(foos[1].value() == 1); 8.99 + Assert.check(foos[2].value() == 2); 8.100 + } 8.101 + } 8.102 + } 8.103 + } 8.104 + if (hasRun != 3) 8.105 + throw new RuntimeException("Couldn't find elements"); 8.106 + } 8.107 + return true; 8.108 + } 8.109 +}