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) {
|
||||
List<? extends AnnotationMirror> annots = e.getAnnotationMirrors();
|
||||
for(AnnotationMirror annotationMirror : annots) {
|
||||
indent();
|
||||
writer.println(annotationMirror);
|
||||
// Handle compiler-generated container annotations specially
|
||||
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
|
||||
private void printParameters(ExecutableElement e) {
|
||||
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