mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-04 23:48:33 +00:00
8011027: Type parameter annotations not passed through to javax.lang.model
Reviewed-by: jjg, darcy
This commit is contained in:
parent
2e806d1c3e
commit
16bec05e63
@ -465,18 +465,11 @@ public abstract class Symbol implements Element {
|
||||
* This is the implementation for {@code
|
||||
* javax.lang.model.element.Element.getAnnotationMirrors()}.
|
||||
*/
|
||||
public final List<? extends AnnotationMirror> getAnnotationMirrors() {
|
||||
@Override
|
||||
public List<Attribute.Compound> getAnnotationMirrors() {
|
||||
return getRawAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Should there be a {@code
|
||||
* javax.lang.model.element.Element.getTypeAnnotationMirrors()}.
|
||||
*/
|
||||
public final List<Attribute.TypeCompound> getTypeAnnotationMirrors() {
|
||||
return getRawTypeAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this method should never be used by javac internally.
|
||||
*/
|
||||
@ -656,6 +649,24 @@ public abstract class Symbol implements Element {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Attribute.Compound> getAnnotationMirrors() {
|
||||
return onlyTypeVariableAnnotations(owner.getRawTypeAttributes());
|
||||
}
|
||||
|
||||
private List<Attribute.Compound> onlyTypeVariableAnnotations(
|
||||
List<Attribute.TypeCompound> candidates) {
|
||||
// Declaration annotations on TypeParameters are stored in type attributes
|
||||
List<Attribute.Compound> res = List.nil();
|
||||
for (Attribute.TypeCompound a : candidates) {
|
||||
if (a.position.type == TargetType.CLASS_TYPE_PARAMETER ||
|
||||
a.position.type == TargetType.METHOD_TYPE_PARAMETER)
|
||||
res = res.prepend(a);
|
||||
}
|
||||
|
||||
return res = res.reverse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
|
||||
return v.visitTypeParameter(this, p);
|
||||
|
||||
@ -206,7 +206,7 @@ public class TypeAnnotations {
|
||||
sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
|
||||
// Make sure all type annotations from the symbol are also
|
||||
// on the owner.
|
||||
sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors());
|
||||
sym.owner.annotations.appendUniqueTypes(sym.getRawTypeAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,10 +33,13 @@ 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.Symbol.TypeVariableSymbol;
|
||||
import com.sun.tools.javac.code.TargetType;
|
||||
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;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
/**
|
||||
* Utility methods for operating on annotated constructs.
|
||||
@ -61,8 +64,12 @@ public class JavacAnnoConstructs {
|
||||
throw new IllegalArgumentException("Not an annotation type: "
|
||||
+ annoType);
|
||||
Attribute.Compound c;
|
||||
if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) {
|
||||
if (annotated.kind == Kinds.TYP &&
|
||||
annotated instanceof ClassSymbol) {
|
||||
c = getAttributeOnClass((ClassSymbol)annotated, annoType);
|
||||
} else if (annotated.kind == Kinds.TYP &&
|
||||
annotated instanceof TypeVariableSymbol) {
|
||||
c = getAttributeOnTypeVariable((TypeVariableSymbol)annotated, annoType);
|
||||
} else {
|
||||
c = getAttribute(annotated, annoType);
|
||||
}
|
||||
@ -82,6 +89,24 @@ public class JavacAnnoConstructs {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper to getAnnotation[s]
|
||||
private static <A extends Annotation> Attribute.Compound
|
||||
getAttributeOnTypeVariable(TypeVariableSymbol annotated, Class<A> annoType) {
|
||||
String name = annoType.getName();
|
||||
|
||||
// Declaration annotations on type variables are stored in type attributes
|
||||
// on the owner of the TypeVariableSymbol
|
||||
List<Attribute.Compound> res = List.nil();
|
||||
List<Attribute.TypeCompound> candidates = annotated.owner.getRawTypeAttributes();
|
||||
for (Attribute.TypeCompound anno : candidates)
|
||||
if (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
|
||||
anno.position.type == TargetType.METHOD_TYPE_PARAMETER)
|
||||
if (name.equals(anno.type.tsym.flatName().toString()))
|
||||
return anno;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper to getAnnotation[s]
|
||||
private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated,
|
||||
Class<A> annoType) {
|
||||
|
||||
@ -402,9 +402,10 @@ public class JavacElements implements Elements {
|
||||
* @param e the element being examined
|
||||
* @return all annotations of the element
|
||||
*/
|
||||
@Override
|
||||
public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
|
||||
Symbol sym = cast(Symbol.class, e);
|
||||
List<Attribute.Compound> annos = sym.getRawAttributes();
|
||||
List<Attribute.Compound> annos = sym.getAnnotationMirrors();
|
||||
while (sym.getKind() == ElementKind.CLASS) {
|
||||
Type sup = ((ClassSymbol) sym).getSuperclass();
|
||||
if (!sup.hasTag(CLASS) || sup.isErroneous() ||
|
||||
@ -413,7 +414,7 @@ public class JavacElements implements Elements {
|
||||
}
|
||||
sym = sup.tsym;
|
||||
List<Attribute.Compound> oldAnnos = annos;
|
||||
List<Attribute.Compound> newAnnos = sym.getRawAttributes();
|
||||
List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors();
|
||||
for (Attribute.Compound anno : newAnnos) {
|
||||
if (isInherited(anno.type) &&
|
||||
!containsAnnoOfType(oldAnnos, anno.type)) {
|
||||
|
||||
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8011027
|
||||
* @library /tools/javac/lib
|
||||
* @build JavacTestingAbstractProcessor TestTypeParameterAnnotations
|
||||
* @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.annotation.*;
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.util.*;
|
||||
import javax.tools.*;
|
||||
|
||||
public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor {
|
||||
int round = 0;
|
||||
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
if (++round == 1) {
|
||||
int found = (new Scanner()).scan(roundEnv.getRootElements(), null);
|
||||
if (found == expect) {
|
||||
; //nop
|
||||
} else {
|
||||
error("unexpected number of results: expected " + expect
|
||||
+ ", found " + found);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class Scanner extends JavacTestingAbstractProcessor.ElementScanner<Integer,Void> {
|
||||
@Override
|
||||
public Integer visitExecutable(ExecutableElement e, Void p) {
|
||||
super.visitExecutable(e, p);
|
||||
found += check(e, e.getTypeParameters());
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer visitType(TypeElement e, Void p) {
|
||||
super.visitType(e, p);
|
||||
found += check(e, e.getTypeParameters());
|
||||
return found;
|
||||
}
|
||||
|
||||
int found;
|
||||
}
|
||||
|
||||
int check(Element e, List<? extends TypeParameterElement> typarams) {
|
||||
if (typarams.isEmpty())
|
||||
return 0;
|
||||
if (typarams.size() != 1)
|
||||
return 0;
|
||||
|
||||
for (TypeParameterElement tpe: typarams) {
|
||||
boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors());
|
||||
boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe));
|
||||
boolean b3 = checkGetAnnotation(tpe);
|
||||
boolean b4 = checkGetAnnotations(tpe);
|
||||
return b1 && b2 && b3 && b4 ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l) {
|
||||
if (l.size() != 3) {
|
||||
error("To few annotations, got " + l.size() +
|
||||
", should be 3", tpe);
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationMirror m = l.get(0);
|
||||
if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) {
|
||||
error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement());
|
||||
return false;
|
||||
}
|
||||
m = l.get(1);
|
||||
if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) {
|
||||
error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement());
|
||||
return false;
|
||||
}
|
||||
m = l.get(2);
|
||||
if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) {
|
||||
error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean checkGetAnnotation(TypeParameterElement tpe) {
|
||||
Foo f = tpe.getAnnotation(Foo.class);
|
||||
if (f == null)
|
||||
error("Expecting @Foo to be present in getAnnotation()", tpe);
|
||||
|
||||
Bar b = tpe.getAnnotation(Bar.class);
|
||||
if (b == null)
|
||||
error("Expecting @Bar to be present in getAnnotation()", tpe);
|
||||
|
||||
Baz z = tpe.getAnnotation(Baz.class);
|
||||
if (z == null)
|
||||
error("Expecting @Baz to be present in getAnnotation()", tpe);
|
||||
|
||||
return f != null &&
|
||||
b != null &&
|
||||
z != null;
|
||||
}
|
||||
|
||||
boolean checkGetAnnotations(TypeParameterElement tpe) {
|
||||
Foo[] f = tpe.getAnnotationsByType(Foo.class);
|
||||
if (f.length != 1) {
|
||||
error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe);
|
||||
return false;
|
||||
}
|
||||
|
||||
Bar[] b = tpe.getAnnotationsByType(Bar.class);
|
||||
if (b.length != 1) {
|
||||
error("Expecting 1 @Bar to be present in getAnnotationsByType()", tpe);
|
||||
return false;
|
||||
}
|
||||
|
||||
Baz[] z = tpe.getAnnotationsByType(Baz.class);
|
||||
if (z.length != 1) {
|
||||
error("Expecting 1 @Baz to be present in getAnnotationsByType()", tpe);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void note(String msg) {
|
||||
messager.printMessage(Diagnostic.Kind.NOTE, msg);
|
||||
}
|
||||
|
||||
void note(String msg, Element e) {
|
||||
messager.printMessage(Diagnostic.Kind.NOTE, msg, e);
|
||||
}
|
||||
|
||||
void error(String msg, Element e) {
|
||||
messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
messager.printMessage(Diagnostic.Kind.ERROR, msg);
|
||||
}
|
||||
|
||||
// additional generic elements to test
|
||||
<@Foo @Bar @Baz X> X m(X x) { return x; }
|
||||
|
||||
interface Intf<@Foo @Bar @Baz X> { X m() ; }
|
||||
|
||||
class Class<@Foo @Bar @Baz X> {
|
||||
<@Foo @Bar @Baz Y> Class() { }
|
||||
}
|
||||
|
||||
final int expect = 5; // top level class, plus preceding examples
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_PARAMETER)
|
||||
@interface Foo {}
|
||||
|
||||
@Target(ElementType.TYPE_PARAMETER)
|
||||
@interface Bar {}
|
||||
|
||||
@Target(ElementType.TYPE_PARAMETER)
|
||||
@interface Baz {}
|
||||
Loading…
x
Reference in New Issue
Block a user