8005295: Use mandated information for printing of repeating annotations
Reviewed-by: jjg
This commit is contained in:
parent
f26cd2ac1c
commit
863feab998
@ -522,11 +522,84 @@ public class PrintingProcessor extends AbstractProcessor {
|
|||||||
private void printAnnotations(Element e) {
|
private void printAnnotations(Element e) {
|
||||||
List<? extends AnnotationMirror> annots = e.getAnnotationMirrors();
|
List<? extends AnnotationMirror> annots = e.getAnnotationMirrors();
|
||||||
for(AnnotationMirror annotationMirror : annots) {
|
for(AnnotationMirror annotationMirror : annots) {
|
||||||
indent();
|
// Handle compiler-generated container annotations specially
|
||||||
writer.println(annotationMirror);
|
if (!printedContainerAnnotation(e, annotationMirror)) {
|
||||||
|
indent();
|
||||||
|
writer.println(annotationMirror);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean printedContainerAnnotation(Element e,
|
||||||
|
AnnotationMirror annotationMirror) {
|
||||||
|
/*
|
||||||
|
* If the annotation mirror is marked as mandated and
|
||||||
|
* looks like a container annotation, elide printing the
|
||||||
|
* container and just print the wrapped contents.
|
||||||
|
*/
|
||||||
|
if (elementUtils.getOrigin(e, annotationMirror) == Elements.Origin.MANDATED) {
|
||||||
|
// From JLS Chapter 9, an annotation interface AC is a
|
||||||
|
// containing annotation interface of A if AC declares
|
||||||
|
// a value() method whose return type is A[] and any
|
||||||
|
// methods declared by AC other than value() have a
|
||||||
|
// default value. As an implementation choice, if more
|
||||||
|
// than one annotation element is found on the outer
|
||||||
|
// annotation, in other words, something besides a
|
||||||
|
// "value" method, the annotation will not be treated
|
||||||
|
// as a wrapper for the purposes of printing. These
|
||||||
|
// checks are intended to preserve correctness in the
|
||||||
|
// face of some other kind of annotation being marked
|
||||||
|
// as mandated.
|
||||||
|
|
||||||
|
var entries = annotationMirror.getElementValues().entrySet();
|
||||||
|
if (entries.size() == 1) {
|
||||||
|
var annotationType = annotationMirror.getAnnotationType();
|
||||||
|
var annotationTypeAsElement = annotationType.asElement();
|
||||||
|
|
||||||
|
var entry = entries.iterator().next();
|
||||||
|
var annotationElements = entry.getValue();
|
||||||
|
|
||||||
|
// Check that the annotation type declaration has
|
||||||
|
// a single method named "value" and that it
|
||||||
|
// returns an array. A stricter check would be
|
||||||
|
// that it is an array of an annotation type and
|
||||||
|
// that annotation type in turn was repeatable.
|
||||||
|
if (annotationTypeAsElement.getKind() == ElementKind.ANNOTATION_TYPE) {
|
||||||
|
var annotationMethods =
|
||||||
|
ElementFilter.methodsIn(annotationTypeAsElement.getEnclosedElements());
|
||||||
|
if (annotationMethods.size() == 1) {
|
||||||
|
var valueMethod = annotationMethods.get(0);
|
||||||
|
var returnType = valueMethod.getReturnType();
|
||||||
|
|
||||||
|
if ("value".equals(valueMethod.getSimpleName().toString()) &&
|
||||||
|
returnType.getKind() == TypeKind.ARRAY) {
|
||||||
|
// Use annotation value visitor that
|
||||||
|
// returns a boolean if it prints out
|
||||||
|
// contained annotations as expected
|
||||||
|
// and false otherwise
|
||||||
|
|
||||||
|
return (new SimpleAnnotationValueVisitor14<Boolean, Void>(false) {
|
||||||
|
@Override
|
||||||
|
public Boolean visitArray(List<? extends AnnotationValue> vals, Void p) {
|
||||||
|
if (vals.size() < 2) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
for (var annotValue: vals) {
|
||||||
|
indent();
|
||||||
|
writer.println(annotValue.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).visit(annotationElements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Refactor
|
// TODO: Refactor
|
||||||
private void printParameters(ExecutableElement e) {
|
private void printParameters(ExecutableElement e) {
|
||||||
List<? extends VariableElement> parameters = e.getParameters();
|
List<? extends VariableElement> parameters = e.getParameters();
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 2021, 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 8005295
|
||||||
|
* @summary Verify repeating annotations are printed as expected
|
||||||
|
* @compile/ref=XprintRepeatingAnnotations.out -Xprint XprintRepeatingAnnotations.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.*;
|
||||||
|
|
||||||
|
@Foo(1)
|
||||||
|
@Foo(2)
|
||||||
|
@Bar(3)
|
||||||
|
@Bar(4)
|
||||||
|
public class XprintRepeatingAnnotations {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Repeatable(Foos.class)
|
||||||
|
@interface Foo {
|
||||||
|
int value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@interface Foos {
|
||||||
|
Foo[] value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Repeatable(Bars.class)
|
||||||
|
@interface Bar {
|
||||||
|
int value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@interface Bars {
|
||||||
|
Bar[] value();
|
||||||
|
int quux() default 1;
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
@Foo(1)
|
||||||
|
@Foo(2)
|
||||||
|
@Bars({@Bar(3), @Bar(4)})
|
||||||
|
public class XprintRepeatingAnnotations {
|
||||||
|
|
||||||
|
public XprintRepeatingAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.annotation.Retention(RUNTIME)
|
||||||
|
@java.lang.annotation.Documented
|
||||||
|
@java.lang.annotation.Repeatable(Foos.class)
|
||||||
|
@interface Foo {
|
||||||
|
|
||||||
|
int value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.annotation.Retention(RUNTIME)
|
||||||
|
@java.lang.annotation.Documented
|
||||||
|
@interface Foos {
|
||||||
|
|
||||||
|
Foo[] value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.annotation.Retention(RUNTIME)
|
||||||
|
@java.lang.annotation.Documented
|
||||||
|
@java.lang.annotation.Repeatable(Bars.class)
|
||||||
|
@interface Bar {
|
||||||
|
|
||||||
|
int value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.annotation.Retention(RUNTIME)
|
||||||
|
@java.lang.annotation.Documented
|
||||||
|
@interface Bars {
|
||||||
|
|
||||||
|
Bar[] value();
|
||||||
|
|
||||||
|
int quux() default 1;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user