7151010: Add compiler support for repeating annotations

Reviewed-by: jjg, mcimadamore
This commit is contained in:
Joel Borggrén-Franck 2012-08-31 10:37:46 +01:00
parent de50ec6f3f
commit 9c23b8bad0
52 changed files with 2284 additions and 95 deletions

View file

@ -0,0 +1,294 @@
/*
* Copyright (c) 2012, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.javac.code;
import java.util.Map;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Pair;
import static com.sun.tools.javac.code.Kinds.PCK;
import com.sun.tools.javac.util.*;
/**
* Container for all annotations (attributes in javac) on a Symbol.
*
* This class is explicitly mutable. Its contents will change when attributes
* are annotated onto the Symbol. However this class depends on the facts that
* List (in javac) is immutable.
*
* An instance of this class can be in one of three states:
*
* NOT_STARTED indicates that the Symbol this instance belongs to have not been
* annotated (yet). Specifically if the declaration is not annotated this
* instance will never move past NOT_STARTED. You can never go back to
* NOT_STARTED.
*
* IN_PROGRESS annotations have been found on the declaration. Will be processed
* later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
* of attributes (and this moves out of the IN_PROGRESS state).
*
* "unnamed" this Annotations contains some attributes, possibly the final set.
* While in this state you can only prepend or append to the attributes not set
* it directly. You can also move back to the IN_PROGRESS sate using reset().
*
* <p><b>This is NOT part of any supported API. If you write code that depends
* on this, you do so at your own risk. This code and its internal interfaces
* are subject to change or deletion without notice.</b>
*/
public class Annotations {
private static final List<Attribute.Compound> NOT_STARTED = List.of(null);
private static final List<Attribute.Compound> IN_PROGRESS = List.of(null);
/*
* This field should never be null
*/
private List<Attribute.Compound> attributes = NOT_STARTED;
/*
* The Symbol this Annotatios belong to
*/
private final Symbol s;
public Annotations(Symbol s) {
this.s = s;
}
public List<Attribute.Compound> getAttributes() {
return filterSentinels(attributes);
}
public void setAttributes(List<Attribute.Compound> a) {
Assert.check(pendingCompletion() || !isStarted());
if (a == null) {
throw new NullPointerException();
}
attributes = a;
}
public void setAttributes(Annotations other) {
if (other == null) {
throw new NullPointerException();
}
setAttributes(other.getAttributes());
}
public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
Assert.check(pendingCompletion() || (!isStarted() && s.kind == PCK));
Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated = ctx.annotated;
boolean atLeastOneRepeated = false;
List<Attribute.Compound> buf = List.<Attribute.Compound>nil();
for (ListBuffer<Attribute.Compound> lb : annotated.values()) {
if (lb.size() == 1) {
buf = buf.prepend(lb.first());
} else { // repeated
buf = buf.prepend(new Placeholder(lb.toList(), s));
atLeastOneRepeated = true;
}
}
// Add non-repeating attributes
setAttributes(buf.reverse());
if (atLeastOneRepeated) {
// The Symbol s is now annotated with a combination of
// finished non-repeating annotations and placeholders for
// repeating annotations.
//
// We need to do this in two passes because when creating
// a container for a repeating annotation we must
// guarantee that the @ContainedBy on the
// contained annotation is fully annotated
//
// The way we force this order is to do all repeating
// annotations in a pass after all non-repeating are
// finished. This will work because @ContainedBy
// is non-repeating and therefore will be annotated in the
// fist pass.
// Queue a pass that will replace Attribute.Placeholders
// with Attribute.Compound (made from synthesized containers).
ctx.annotateRepeated(new Annotate.Annotator() {
@Override
public String toString() {
return "repeated annotation pass of: " + s + " in: " + s.owner;
}
@Override
public void enterAnnotation() {
complete(ctx);
}
});
}
}
public Annotations reset() {
attributes = IN_PROGRESS;
return this;
}
public boolean isEmpty() {
return !isStarted()
|| pendingCompletion()
|| attributes.isEmpty();
}
public boolean pendingCompletion() {
return attributes == IN_PROGRESS;
}
public Annotations append(List<Attribute.Compound> l) {
attributes = filterSentinels(attributes);
if (l.isEmpty()) {
; // no-op
} else if (attributes.isEmpty()) {
attributes = l;
} else {
attributes = attributes.appendList(l);
}
return this;
}
public Annotations prepend(List<Attribute.Compound> l) {
attributes = filterSentinels(attributes);
if (l.isEmpty()) {
; // no-op
} else if (attributes.isEmpty()) {
attributes = l;
} else {
attributes = attributes.prependList(l);
}
return this;
}
private List<Attribute.Compound> filterSentinels(List<Attribute.Compound> a) {
return (a == IN_PROGRESS || a == NOT_STARTED)
? List.<Attribute.Compound>nil()
: a;
}
private boolean isStarted() {
return attributes != NOT_STARTED;
}
private List<Attribute.Compound> getPlaceholders() {
List<Attribute.Compound> res = List.<Attribute.Compound>nil();
for (Attribute.Compound a : filterSentinels(attributes)) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
}
return res.reverse();
}
/*
* Replace Placeholders for repeating annotations with their containers
*/
private void complete(Annotate.AnnotateRepeatedContext ctx) {
Assert.check(!pendingCompletion());
Log log = ctx.log;
Env<AttrContext> env = ctx.env;
JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
try {
if (isEmpty()) {
return;
}
List<Attribute.Compound> result = List.nil();
for (Attribute.Compound a : getAttributes()) {
if (a instanceof Placeholder) {
Attribute.Compound replacement = replaceOne((Placeholder) a, ctx);
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
}
}
attributes = result.reverse();
Assert.check(Annotations.this.getPlaceholders().isEmpty());
} finally {
log.useSource(oldSource);
}
}
private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) {
Log log = ctx.log;
// Process repeated annotations
Attribute.Compound validRepeated =
ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor());
if (validRepeated != null) {
// Check that the container isn't manually
// present along with repeated instances of
// its contained annotation.
ListBuffer<Attribute.Compound> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
if (manualContainer != null) {
log.error(ctx.pos.get(manualContainer.first()), "invalid.containedby.annotation.repeated.and.container.present",
manualContainer.first().type.tsym);
}
}
// A null return will delete the Placeholder
return validRepeated;
}
private static class Placeholder extends Attribute.Compound {
private List<Attribute.Compound> placeholderFor;
private Symbol on;
public Placeholder(List<Attribute.Compound> placeholderFor, Symbol on) {
super(Type.noType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil());
this.placeholderFor = placeholderFor;
this.on = on;
}
@Override
public String toString() {
return "<placeholder: " + placeholderFor + " on: " + on + ">";
}
public List<Attribute.Compound> getPlaceholderFor() {
return placeholderFor;
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
@ -103,11 +103,11 @@ public abstract class Attribute implements AnnotationValue {
* represented as a ClassSymbol.
*/
public static class Class extends Attribute {
public final Type type;
public final Type classType;
public void accept(Visitor v) { v.visitClass(this); }
public Class(Types types, Type type) {
super(makeClassType(types, type));
this.type = type;
this.classType = type;
}
static Type makeClassType(Types types, Type type) {
Type arg = type.isPrimitive()
@ -118,13 +118,13 @@ public abstract class Attribute implements AnnotationValue {
types.syms.classType.tsym);
}
public String toString() {
return type + ".class";
return classType + ".class";
}
public Type getValue() {
return type;
return classType;
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitType(type, p);
return v.visitType(classType, p);
}
}
@ -212,6 +212,12 @@ public abstract class Attribute implements AnnotationValue {
super(type);
this.values = values;
}
public Array(Type type, List<Attribute> values) {
super(type);
this.values = values.toArray(new Attribute[values.size()]);
}
public void accept(Visitor v) { v.visitArray(this); }
public String toString() {
StringBuilder buf = new StringBuilder();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
@ -70,16 +70,16 @@ public class Lint
* Returns the result of combining the values in this object with
* the given annotations.
*/
public Lint augment(List<Attribute.Compound> attrs) {
return augmentor.augment(this, attrs);
public Lint augment(Annotations annots) {
return augmentor.augment(this, annots.getAttributes());
}
/**
* Returns the result of combining the values in this object with
* the given annotations and flags.
*/
public Lint augment(List<Attribute.Compound> attrs, long flags) {
Lint l = augmentor.augment(this, attrs);
public Lint augment(Annotations annots, long flags) {
Lint l = augmentor.augment(this, annots.getAttributes());
if ((flags & DEPRECATED) != 0) {
if (l == this)
l = new Lint(this);

View file

@ -203,6 +203,9 @@ public enum Source {
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowRepeatedAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public static SourceVersion toSourceVersion(Source source) {
switch(source) {
case JDK1_2:

View file

@ -72,22 +72,24 @@ public abstract class Symbol implements Element {
*/
public long flags() { return flags_field; }
/** The attributes of this symbol.
/** The attributes of this symbol are contained in this
* Annotations. The Annotations instance is NOT immutable.
*/
public List<Attribute.Compound> attributes_field;
public final Annotations annotations = new Annotations(this);
/** An accessor method for the attributes of this symbol.
* Attributes of class symbols should be accessed through the accessor
* method to make sure that the class symbol is loaded.
*/
public List<Attribute.Compound> getAnnotationMirrors() {
return Assert.checkNonNull(attributes_field);
return Assert.checkNonNull(annotations.getAttributes());
}
/** Fetch a particular annotation from a symbol. */
public Attribute.Compound attribute(Symbol anno) {
for (Attribute.Compound a : getAnnotationMirrors())
for (Attribute.Compound a : getAnnotationMirrors()) {
if (a.type.tsym == anno) return a;
}
return null;
}
@ -120,7 +122,6 @@ public abstract class Symbol implements Element {
this.owner = owner;
this.completer = null;
this.erasure_field = null;
this.attributes_field = List.nil();
this.name = name;
}
@ -657,10 +658,11 @@ public abstract class Symbol implements Element {
if (completer != null) complete();
if (package_info != null && package_info.completer != null) {
package_info.complete();
if (attributes_field.isEmpty())
attributes_field = package_info.attributes_field;
if (annotations.isEmpty()) {
annotations.setAttributes(package_info.annotations);
}
return Assert.checkNonNull(attributes_field);
}
return Assert.checkNonNull(annotations.getAttributes());
}
/** A package "exists" if a type or package that exists has
@ -762,7 +764,7 @@ public abstract class Symbol implements Element {
public List<Attribute.Compound> getAnnotationMirrors() {
if (completer != null) complete();
return Assert.checkNonNull(attributes_field);
return Assert.checkNonNull(annotations.getAttributes());
}
public Type erasure(Types types) {

View file

@ -156,6 +156,10 @@ public class Symtab {
public final Type systemType;
public final Type autoCloseableType;
public final Type trustMeType;
public final Type containedByType;
public final Type containerForType;
public final Type documentedType;
public final Type elementTypeType;
/** The symbol representing the length field of an array.
*/
@ -468,6 +472,10 @@ public class Symtab {
deprecatedType = enterClass("java.lang.Deprecated");
suppressWarningsType = enterClass("java.lang.SuppressWarnings");
inheritedType = enterClass("java.lang.annotation.Inherited");
containedByType = enterClass("java.lang.annotation.ContainedBy");
containerForType = enterClass("java.lang.annotation.ContainerFor");
documentedType = enterClass("java.lang.annotation.Documented");
elementTypeType = enterClass("java.lang.annotation.ElementType");
systemType = enterClass("java.lang.System");
autoCloseableType = enterClass("java.lang.AutoCloseable");
autoCloseableClose = new MethodSymbol(PUBLIC,

View file

@ -1358,6 +1358,20 @@ public class Types {
}
return result;
}
/**
* Returns an ArrayType with the component type t
*
* @param t The component type of the ArrayType
* @return the ArrayType for the given component
*/
public ArrayType makeArrayType(Type t) {
if (t.tag == VOID ||
t.tag >= PACKAGE) {
Assert.error("Type t must not be a a VOID or PACKAGE type, " + t.toString());
}
return new ArrayType(t, syms.arrayClass);
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="asSuper">
@ -3811,8 +3825,12 @@ public class Types {
// <editor-fold defaultstate="collapsed" desc="Annotation support">
public RetentionPolicy getRetention(Attribute.Compound a) {
return getRetention(a.type.tsym);
}
public RetentionPolicy getRetention(Symbol sym) {
RetentionPolicy vis = RetentionPolicy.CLASS; // the default
Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym);
Attribute.Compound c = sym.attribute(syms.retentionType.tsym);
if (c != null) {
Attribute value = c.member(names.value);
if (value != null && value instanceof Attribute.Enum) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
@ -25,7 +25,11 @@
package com.sun.tools.javac.comp;
import java.util.Map;
import java.util.Objects;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.tree.*;
@ -83,8 +87,9 @@ public class Annotate {
private int enterCount = 0;
ListBuffer<Annotator> q = new ListBuffer<Annotator>();
ListBuffer<Annotator> repeatedQ = new ListBuffer<Annotator>();
public void later(Annotator a) {
public void normal(Annotator a) {
q.append(a);
}
@ -92,6 +97,10 @@ public class Annotate {
q.prepend(a);
}
public void repeated(Annotator a) {
repeatedQ.append(a);
}
/** Called when the Enter phase starts. */
public void enterStart() {
enterCount++;
@ -109,6 +118,10 @@ public class Annotate {
try {
while (q.nonEmpty())
q.next().enterAnnotation();
while (repeatedQ.nonEmpty()) {
repeatedQ.next().enterAnnotation();
}
} finally {
enterCount--;
}
@ -124,6 +137,53 @@ public class Annotate {
String toString();
}
/**
* This context contains all the information needed to synthesize new
* annotations trees by the completer for repeating annotations.
*/
public class AnnotateRepeatedContext {
public final Env<AttrContext> env;
public final Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated;
public final Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos;
public final Log log;
public AnnotateRepeatedContext(Env<AttrContext> env,
Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated,
Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos,
Log log) {
Objects.requireNonNull(env);
Objects.requireNonNull(annotated);
Objects.requireNonNull(pos);
Objects.requireNonNull(log);
this.env = env;
this.annotated = annotated;
this.pos = pos;
this.log = log;
}
/**
* Process a list of repeating annotations returning a new
* Attribute.Compound that is the attribute for the synthesized tree
* for the container.
*
* @param repeatingAnnotations a List of repeating annotations
* @return a new Attribute.Compound that is the container for the repeatingAnnotations
*/
public Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> repeatingAnnotations) {
return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this);
}
/**
* Queue the Annotator a on the repeating annotations queue of the
* Annotate instance this context belongs to.
*
* @param a the Annotator to enqueue for repeating annotation annotating
*/
public void annotateRepeated(Annotator a) {
Annotate.this.repeated(a);
}
}
/* ********************************************************************
* Compute an attribute from its annotation.
@ -268,4 +328,219 @@ public class Annotate {
log.error(tree.pos(), "annotation.value.not.allowable.type");
return new Attribute.Error(attr.attribExpr(tree, env, expected));
}
/* *********************************
* Support for repeating annotations
***********************************/
/* Process repeated annotations. This method returns the
* synthesized container annotation or null IFF all repeating
* annotation are invalid. This method reports errors/warnings.
*/
private Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> annotations,
AnnotateRepeatedContext ctx) {
Attribute.Compound firstOccurrence = annotations.head;
List<Attribute> repeated = List.nil();
Type origAnnoType;
Type arrayOfOrigAnnoType = null;
Type targetContainerType = null;
MethodSymbol containerValueSymbol = null;
Assert.check(!annotations.isEmpty() &&
!annotations.tail.isEmpty()); // i.e. size() > 1
for (List<Attribute.Compound> al = annotations;
!al.isEmpty();
al = al.tail)
{
Attribute.Compound currentAnno = al.head;
origAnnoType = currentAnno.type;
if (arrayOfOrigAnnoType == null) {
arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
}
Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno));
if (currentContainerType == null) {
continue;
}
// Assert that the target Container is == for all repeated
// annos of the same annotation type, the types should
// come from the same Symbol, i.e. be '=='
Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
targetContainerType = currentContainerType;
containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));
if (containerValueSymbol == null) { // Check of CA type failed
// errors are already reported
continue;
}
repeated = repeated.prepend(currentAnno);
}
if (!repeated.isEmpty()) {
repeated = repeated.reverse();
JCAnnotation annoTree;
TreeMaker m = make.at(ctx.pos.get(firstOccurrence));
Pair<MethodSymbol, Attribute> p =
new Pair<MethodSymbol, Attribute>(containerValueSymbol,
new Attribute.Array(arrayOfOrigAnnoType, repeated));
annoTree = m.Annotation(new Attribute.Compound(targetContainerType,
List.of(p)));
Attribute.Compound c = enterAnnotation(annoTree,
targetContainerType,
ctx.env);
return c;
} else {
return null; // errors should have been reported elsewhere
}
}
/** Fetches the actual Type that should be the containing annotation. */
private Type getContainingType(Attribute.Compound currentAnno,
DiagnosticPosition pos)
{
Type origAnnoType = currentAnno.type;
TypeSymbol origAnnoDecl = origAnnoType.tsym;
// Fetch the ContainedBy annotation from the current
// annotation's declaration, or null if it has none
Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym);
if (ca == null) { // has no ContainedBy annotation
log.error(pos, "duplicate.annotation.missing.container", origAnnoType);
return null;
}
return filterSame(extractContainingType(ca, pos, origAnnoDecl),
origAnnoType);
}
// returns null if t is same as 's', returns 't' otherwise
private Type filterSame(Type t, Type s) {
if (t == null || s == null) {
return t;
}
return types.isSameType(t, s) ? null : t;
}
/** Extract the actual Type to be used for a containing annotation. */
private Type extractContainingType(Attribute.Compound ca,
DiagnosticPosition pos,
TypeSymbol annoDecl)
{
// The next three checks check that the ContainedBy annotation
// on the declaration of the annotation type that is repeating is
// valid.
// ContainedBy must have at least one element
if (ca.values.isEmpty()) {
log.error(pos, "invalid.containedby.annotation", annoDecl);
return null;
}
Pair<MethodSymbol,Attribute> p = ca.values.head;
Name name = p.fst.name;
if (name != names.value) { // should contain only one element, named "value"
log.error(pos, "invalid.containedby.annotation", annoDecl);
return null;
}
if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
log.error(pos, "invalid.containedby.annotation", annoDecl);
return null;
}
return ((Attribute.Class)p.snd).getValue();
}
/* Validate that the suggested targetContainerType Type is a valid
* container type for repeated instances of originalAnnoType
* annotations. Return null and report errors if this is not the
* case, return the MethodSymbol of the value element in
* targetContainerType if it is suitable (this is needed to
* synthesize the container). */
private MethodSymbol validateContainer(Type targetContainerType,
Type originalAnnoType,
DiagnosticPosition pos) {
MethodSymbol containerValueSymbol = null;
boolean fatalError = false;
// Validate that there is a (and only 1) value method
Scope scope = targetContainerType.tsym.members();
int nr_value_elems = 0;
boolean error = false;
for(Symbol elm : scope.getElementsByName(names.value)) {
nr_value_elems++;
if (nr_value_elems == 1 &&
elm.kind == Kinds.MTH) {
containerValueSymbol = (MethodSymbol)elm;
} else {
error = true;
}
}
if (error) {
log.error(pos,
"invalid.containedby.annotation.multiple.values",
targetContainerType,
nr_value_elems);
return null;
} else if (nr_value_elems == 0) {
log.error(pos,
"invalid.containedby.annotation.no.value",
targetContainerType);
return null;
}
// validate that the 'value' element is a method
// probably "impossible" to fail this
if (containerValueSymbol.kind != Kinds.MTH) {
log.error(pos,
"invalid.containedby.annotation.invalid.value",
targetContainerType);
fatalError = true;
}
// validate that the 'value' element has the correct return type
// i.e. array of original anno
Type valueRetType = containerValueSymbol.type.getReturnType();
Type expectedType = types.makeArrayType(originalAnnoType);
if (!(types.isArray(valueRetType) &&
types.isSameType(expectedType, valueRetType))) {
log.error(pos,
"invalid.containedby.annotation.value.return",
targetContainerType,
valueRetType,
expectedType);
fatalError = true;
}
// validate that all other elements of containing type has defaults
scope = targetContainerType.tsym.members();
error = false;
for(Symbol elm : scope.getElements()) {
if (elm.name != names.value &&
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
targetContainerType,
elm);
containerValueSymbol = null;
error = true;
}
}
if (error) {
fatalError = true;
}
// Explicitly no check for/validity of @ContainerFor. That is
// done on declaration of the container, and at reflect time.
// The rest of the conditions for a valid containing annotation are made
// in Check.validateRepeatedAnnotaton();
return fatalError ? null : containerValueSymbol;
}
}

View file

@ -662,10 +662,12 @@ public class Attr extends JCTree.Visitor {
// env.info.enclVar.attributes_field might not yet have been evaluated, and so might be
// null. In that case, calling augment will throw an NPE. To avoid this, for now we
// revert to the jdk 6 behavior and ignore the (unevaluated) attributes.
if (env.info.enclVar.attributes_field == null)
if (env.info.enclVar.annotations.pendingCompletion()) {
env.info.lint = lintEnv.info.lint;
else
env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.attributes_field, env.info.enclVar.flags());
} else {
env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.annotations,
env.info.enclVar.flags());
}
Lint prevLint = chk.setLint(env.info.lint);
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
@ -776,7 +778,7 @@ public class Attr extends JCTree.Visitor {
public void visitMethodDef(JCMethodDecl tree) {
MethodSymbol m = tree.sym;
Lint lint = env.info.lint.augment(m.attributes_field, m.flags());
Lint lint = env.info.lint.augment(m.annotations, m.flags());
Lint prevLint = chk.setLint(lint);
MethodSymbol prevMethod = chk.setMethod(m);
try {
@ -921,7 +923,7 @@ public class Attr extends JCTree.Visitor {
}
VarSymbol v = tree.sym;
Lint lint = env.info.lint.augment(v.attributes_field, v.flags());
Lint lint = env.info.lint.augment(v.annotations, v.flags());
Lint prevLint = chk.setLint(lint);
// Check that the variable's declared type is well-formed.
@ -3069,7 +3071,7 @@ public class Attr extends JCTree.Visitor {
lintEnv = lintEnv.next;
// Having found the enclosing lint value, we can initialize the lint value for this class
env.info.lint = lintEnv.info.lint.augment(c.attributes_field, c.flags());
env.info.lint = lintEnv.info.lint.augment(c.annotations, c.flags());
Lint prevLint = chk.setLint(env.info.lint);
JavaFileObject prev = log.useSource(c.sourcefile);
@ -3133,6 +3135,26 @@ public class Attr extends JCTree.Visitor {
if (tree.typarams.nonEmpty())
log.error(tree.typarams.head.pos(),
"intf.annotation.cant.have.type.params");
// If this annotation has a @ContainedBy, validate
Attribute.Compound containedBy = c.attribute(syms.containedByType.tsym);
if (containedBy != null) {
// get diagnositc position for error reporting
DiagnosticPosition cbPos = getDiagnosticPosition(tree, containedBy.type);
Assert.checkNonNull(cbPos);
chk.validateContainedBy(c, containedBy, cbPos);
}
// If this annotation has a @ContainerFor, validate
Attribute.Compound containerFor = c.attribute(syms.containerForType.tsym);
if (containerFor != null) {
// get diagnositc position for error reporting
DiagnosticPosition cfPos = getDiagnosticPosition(tree, containerFor.type);
Assert.checkNonNull(cfPos);
chk.validateContainerFor(c, containerFor, cfPos);
}
} else {
// Check that all extended classes and interfaces
// are compatible (i.e. no two define methods with same arguments
@ -3194,6 +3216,16 @@ public class Attr extends JCTree.Visitor {
}
}
// where
/** get a diagnostic position for an attribute of Type t, or null if attribute missing */
private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) {
for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) {
if (types.isSameType(al.head.annotationType.type, t))
return al.head.pos();
}
return null;
}
/** check if a class is a subtype of Serializable, if that is available. */
private boolean isSerializable(ClassSymbol c) {
try {

View file

@ -69,7 +69,6 @@ public class Check {
private final Infer infer;
private final Types types;
private final JCDiagnostic.Factory diags;
private final boolean skipAnnotations;
private boolean warnOnSyntheticConflicts;
private boolean suppressAbortOnBadClassFile;
private boolean enableSunApiLintControl;
@ -113,7 +112,6 @@ public class Check {
allowCovariantReturns = source.allowCovariantReturns();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
complexInference = options.isSet("complexinference");
skipAnnotations = options.isSet("skipAnnotations");
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
enableSunApiLintControl = options.isSet("enableSunApiLintControl");
@ -2422,14 +2420,13 @@ public class Check {
/** Check the annotations of a symbol.
*/
public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) {
if (skipAnnotations) return;
for (JCAnnotation a : annotations)
validateAnnotation(a, s);
}
/** Check an annotation of a symbol.
*/
public void validateAnnotation(JCAnnotation a, Symbol s) {
private void validateAnnotation(JCAnnotation a, Symbol s) {
validateAnnotationTree(a);
if (!annotationApplicable(a, s))
@ -2441,6 +2438,215 @@ public class Check {
}
}
/**
* Validate the proposed container 'containedBy' on the
* annotation type symbol 's'. Report errors at position
* 'pos'.
*
* @param s The (annotation)type declaration annotated with a @ContainedBy
* @param containerAnno the @ContainedBy on 's'
* @param pos where to report errors
*/
public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) {
Assert.check(types.isSameType(containedBy.type, syms.containedByType));
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containedby", s, containedBy);
return;
}
validateHasContainerFor(t.tsym, s, pos);
validateRetention(t.tsym, s, pos);
validateDocumented(t.tsym, s, pos);
validateInherited(t.tsym, s, pos);
validateTarget(t.tsym, s, pos);
}
/**
* Validate the proposed container 'containerFor' on the
* annotation type symbol 's'. Report errors at position
* 'pos'.
*
* @param s The (annotation)type declaration annotated with a @ContainerFor
* @param containerFor the @ContainedFor on 's'
* @param pos where to report errors
*/
public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) {
Assert.check(types.isSameType(containerFor.type, syms.containerForType));
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containerfor", s, containerFor);
return;
}
validateHasContainedBy(t.tsym, s, pos);
}
private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym);
if (containedBy == null) {
log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym);
return;
}
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containedby", container, contained);
return;
}
if (!types.isSameType(t, contained.type))
log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained);
}
private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym);
if (containerFor == null) {
log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym);
return;
}
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containerfor", container, contained);
return;
}
if (!types.isSameType(t, contained.type))
log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained);
}
private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) {
Attribute.RetentionPolicy containerRetention = types.getRetention(container);
Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
boolean error = false;
switch (containedRetention) {
case RUNTIME:
if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
error = true;
}
break;
case CLASS:
if (containerRetention == Attribute.RetentionPolicy.SOURCE) {
error = true;
}
}
if (error ) {
log.error(pos, "invalid.containedby.annotation.retention",
container, containerRetention,
contained, containedRetention);
}
}
private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
if (contained.attribute(syms.documentedType.tsym) != null) {
if (container.attribute(syms.documentedType.tsym) == null) {
log.error(pos, "invalid.containedby.annotation.not.documented", container, contained);
}
}
}
private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
if (contained.attribute(syms.inheritedType.tsym) != null) {
if (container.attribute(syms.inheritedType.tsym) == null) {
log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained);
}
}
}
private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) {
Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
// If contained has no Target, we are done
if (containedTarget == null) {
return;
}
// If contained has Target m1, container must have a Target
// annotation, m2, and m2 must be a subset of m1. (This is
// trivially true if contained has no target as per above).
// contained has target, but container has not, error
Attribute.Array containerTarget = getAttributeTargetAttribute(container);
if (containerTarget == null) {
log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
return;
}
Set<Name> containerTargets = new HashSet<Name>();
for (Attribute app : containerTarget.values) {
if (!(app instanceof Attribute.Enum)) {
continue; // recovery
}
Attribute.Enum e = (Attribute.Enum)app;
containerTargets.add(e.value.name);
}
Set<Name> containedTargets = new HashSet<Name>();
for (Attribute app : containedTarget.values) {
if (!(app instanceof Attribute.Enum)) {
continue; // recovery
}
Attribute.Enum e = (Attribute.Enum)app;
containedTargets.add(e.value.name);
}
if (!isTargetSubset(containedTargets, containerTargets)) {
log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
}
}
/** Checks that t is a subset of s, with respect to ElementType
* semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE}
*/
private boolean isTargetSubset(Set<Name> s, Set<Name> t) {
// Check that all elements in t are present in s
for (Name n2 : t) {
boolean currentElementOk = false;
for (Name n1 : s) {
if (n1 == n2) {
currentElementOk = true;
break;
} else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
currentElementOk = true;
break;
}
}
if (!currentElementOk)
return false;
}
return true;
}
/** Is s a method symbol that overrides a method in a superclass? */
boolean isOverrider(Symbol s) {
if (s.kind != MTH || s.isStatic())
@ -2461,12 +2667,10 @@ public class Check {
/** Is the annotation applicable to the symbol? */
boolean annotationApplicable(JCAnnotation a, Symbol s) {
Attribute.Compound atTarget =
a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
if (atTarget == null) return true;
Attribute atValue = atTarget.member(names.value);
if (!(atValue instanceof Attribute.Array)) return true; // error recovery
Attribute.Array arr = (Attribute.Array) atValue;
Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
if (arr == null) {
return true;
}
for (Attribute app : arr.values) {
if (!(app instanceof Attribute.Enum)) return true; // recovery
Attribute.Enum e = (Attribute.Enum) app;
@ -2508,6 +2712,16 @@ public class Check {
return false;
}
Attribute.Array getAttributeTargetAttribute(Symbol s) {
Attribute.Compound atTarget =
s.attribute(syms.annotationTargetType.tsym);
if (atTarget == null) return null; // ok, is applicable
Attribute atValue = atTarget.member(names.value);
if (!(atValue instanceof Attribute.Array)) return null; // error recovery
return (Attribute.Array) atValue;
}
/** Check an annotation value.
*/
public void validateAnnotation(JCAnnotation a) {

View file

@ -157,7 +157,7 @@ public class Enter extends JCTree.Visitor {
Env<AttrContext> lintEnv = localEnv;
while (lintEnv.info.lint == null)
lintEnv = lintEnv.next;
localEnv.info.lint = lintEnv.info.lint.augment(sym.attributes_field, sym.flags());
localEnv.info.lint = lintEnv.info.lint.augment(sym.annotations, sym.flags());
return localEnv;
}

View file

@ -406,7 +406,7 @@ public class Flow {
Lint lintPrev = lint;
pendingExits = new ListBuffer<PendingExit>();
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try {
// process all the static initializers
@ -442,7 +442,7 @@ public class Flow {
if (tree.body == null) return;
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
Assert.check(pendingExits.isEmpty());
@ -468,7 +468,7 @@ public class Flow {
public void visitVarDef(JCVariableDecl tree) {
if (tree.init != null) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try{
scan(tree.init);
} finally {
@ -783,7 +783,7 @@ public class Flow {
}
classDef = tree;
thrown = List.nil();
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try {
// process all the static initializers
@ -863,7 +863,7 @@ public class Flow {
List<Type> mthrown = tree.sym.type.getThrownTypes();
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
Assert.check(pendingExits.isEmpty());
@ -902,7 +902,7 @@ public class Flow {
public void visitVarDef(JCVariableDecl tree) {
if (tree.init != null) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try{
scan(tree.init);
} finally {
@ -1491,7 +1491,7 @@ public class Flow {
firstadr = nextadr;
}
classDef = tree;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try {
// define all the static fields
@ -1558,7 +1558,7 @@ public class Flow {
int firstadrPrev = firstadr;
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
Assert.check(pendingExits.isEmpty());
@ -1609,7 +1609,7 @@ public class Flow {
if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
if (tree.init != null) {
Lint lintPrev = lint;
lint = lint.augment(tree.sym.attributes_field);
lint = lint.augment(tree.sym.annotations);
try{
scanExpr(tree.init);
if (track) letInit(tree.pos(), tree.sym);

View file

@ -2257,7 +2257,7 @@ public class Lower extends TreeTranslator {
null, List.<JCExpression>nil(), List.<JCTree>nil());
ClassSymbol c = tree.packge.package_info;
c.flags_field |= flags;
c.attributes_field = tree.packge.attributes_field;
c.annotations.setAttributes(tree.packge.annotations);
ClassType ctype = (ClassType) c.type;
ctype.supertype_field = syms.objectType;
ctype.interfaces_field = List.nil();
@ -2274,7 +2274,8 @@ public class Lower extends TreeTranslator {
case LEGACY:
return tree.packageAnnotations.nonEmpty();
case NONEMPTY:
for (Attribute.Compound a: tree.packge.attributes_field) {
for (Attribute.Compound a :
tree.packge.annotations.getAttributes()) {
Attribute.RetentionPolicy p = types.getRetention(a);
if (p != Attribute.RetentionPolicy.SOURCE)
return true;

View file

@ -76,11 +76,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
private final Annotate annotate;
private final Types types;
private final JCDiagnostic.Factory diags;
private final Source source;
private final Target target;
private final DeferredLintHandler deferredLintHandler;
private final boolean skipAnnotations;
public static MemberEnter instance(Context context) {
MemberEnter instance = context.get(memberEnterKey);
if (instance == null)
@ -102,10 +101,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
annotate = Annotate.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
source = Source.instance(context);
target = Target.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
Options options = Options.instance(context);
skipAnnotations = options.isSet("skipAnnotations");
}
/** A queue for classes whose members still need to be entered into the
@ -690,7 +688,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) {
Env<AttrContext> mEnv = methodEnv(tree, env);
mEnv.info.lint = mEnv.info.lint.augment(tree.sym.attributes_field, tree.sym.flags());
mEnv.info.lint = mEnv.info.lint.augment(tree.sym.annotations, tree.sym.flags());
for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail)
mEnv.info.scope.enterIfAbsent(l.head.type.tsym);
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail)
@ -727,18 +725,24 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
void annotateLater(final List<JCAnnotation> annotations,
final Env<AttrContext> localEnv,
final Symbol s) {
if (annotations.isEmpty()) return;
if (s.kind != PCK) s.attributes_field = null; // mark it incomplete for now
annotate.later(new Annotate.Annotator() {
if (annotations.isEmpty()) {
return;
}
if (s.kind != PCK) {
s.annotations.reset(); // mark Annotations as incomplete for now
}
annotate.normal(new Annotate.Annotator() {
@Override
public String toString() {
return "annotate " + annotations + " onto " + s + " in " + s.owner;
}
@Override
public void enterAnnotation() {
Assert.check(s.kind == PCK || s.attributes_field == null);
Assert.check(s.kind == PCK || s.annotations.pendingCompletion());
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
try {
if (s.attributes_field != null &&
s.attributes_field.nonEmpty() &&
if (!s.annotations.isEmpty() &&
annotations.nonEmpty())
log.error(annotations.head.pos,
"already.annotated",
@ -756,7 +760,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
* java.lang.Deprecated.
**/
private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) {
for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty())
return true;
@ -764,42 +768,62 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
return false;
}
/** Enter a set of annotations. */
private void enterAnnotations(List<JCAnnotation> annotations,
Env<AttrContext> env,
Symbol s) {
ListBuffer<Attribute.Compound> buf =
new ListBuffer<Attribute.Compound>();
Set<TypeSymbol> annotated = new HashSet<TypeSymbol>();
if (!skipAnnotations)
for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
Map<TypeSymbol, ListBuffer<Attribute.Compound>> annotated =
new LinkedHashMap<TypeSymbol, ListBuffer<Attribute.Compound>>();
Map<Attribute.Compound, DiagnosticPosition> pos =
new HashMap<Attribute.Compound, DiagnosticPosition>();
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
Attribute.Compound c = annotate.enterAnnotation(a,
syms.annotationType,
env);
if (c == null) continue;
buf.append(c);
if (c == null) {
continue;
}
if (annotated.containsKey(a.type.tsym)) {
if (source.allowRepeatedAnnotations()) {
ListBuffer<Attribute.Compound> l = annotated.get(a.type.tsym);
l = l.append(c);
annotated.put(a.type.tsym, l);
pos.put(c, a.pos());
} else {
log.error(a.pos(), "duplicate.annotation");
}
} else {
annotated.put(a.type.tsym, ListBuffer.of(c));
pos.put(c, a.pos());
}
// Note: @Deprecated has no effect on local variables and parameters
if (!c.type.isErroneous()
&& s.owner.kind != MTH
&& types.isSameType(c.type, syms.deprecatedType))
&& types.isSameType(c.type, syms.deprecatedType)) {
s.flags_field |= Flags.DEPRECATED;
if (!annotated.add(a.type.tsym))
log.error(a.pos, "duplicate.annotation");
}
s.attributes_field = buf.toList();
}
s.annotations.setAttributesWithCompletion(
annotate.new AnnotateRepeatedContext(env, annotated, pos, log));
}
/** Queue processing of an attribute default value. */
void annotateDefaultValueLater(final JCExpression defaultValue,
final Env<AttrContext> localEnv,
final MethodSymbol m) {
annotate.later(new Annotate.Annotator() {
annotate.normal(new Annotate.Annotator() {
@Override
public String toString() {
return "annotate " + m.owner + "." +
m + " default " + defaultValue;
}
@Override
public void enterAnnotation() {
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
try {

View file

@ -1321,7 +1321,7 @@ public class ClassReader implements Completer {
else
proxies.append(proxy);
}
annotate.later(new AnnotationCompleter(sym, proxies.toList()));
annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
}
}
@ -1347,7 +1347,7 @@ public class ClassReader implements Completer {
void attachAnnotationDefault(final Symbol sym) {
final MethodSymbol meth = (MethodSymbol)sym; // only on methods
final Attribute value = readAttributeValue();
annotate.later(new AnnotationDefaultCompleter(meth, value));
annotate.normal(new AnnotationDefaultCompleter(meth, value));
}
Type readTypeOrClassSymbol(int i) {
@ -1693,10 +1693,13 @@ public class ClassReader implements Completer {
JavaFileObject previousClassFile = currentClassFile;
try {
currentClassFile = classFile;
Annotations annotations = sym.annotations;
List<Attribute.Compound> newList = deproxyCompoundList(l);
sym.attributes_field = ((sym.attributes_field == null)
? newList
: newList.prependList(sym.attributes_field));
if (annotations.pendingCompletion()) {
annotations.setAttributes(newList);
} else {
annotations.append(newList);
}
} finally {
currentClassFile = previousClassFile;
}

View file

@ -825,7 +825,7 @@ public class ClassWriter extends ClassFile {
}
public void visitClass(Attribute.Class clazz) {
databuf.appendByte('c');
databuf.appendChar(pool.put(typeSig(clazz.type)));
databuf.appendChar(pool.put(typeSig(clazz.classType)));
}
public void visitCompound(Attribute.Compound compound) {
databuf.appendByte('@');

View file

@ -157,7 +157,7 @@ public class JNIWriter {
if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
return false;
for (Attribute.Compound a: c.attributes_field) {
for (Attribute.Compound a: c.annotations.getAttributes()) {
if (a.type.tsym == syms.nativeHeaderType.tsym)
return true;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, 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
@ -177,7 +177,7 @@ public class AnnotationProxyMaker {
}
public void visitClass(Attribute.Class c) {
value = new MirroredTypeExceptionProxy(c.type);
value = new MirroredTypeExceptionProxy(c.classType);
}
public void visitArray(Attribute.Array a) {
@ -187,7 +187,7 @@ public class AnnotationProxyMaker {
// Construct a proxy for a MirroredTypesException
ListBuffer<TypeMirror> elems = new ListBuffer<TypeMirror>();
for (Attribute value : a.values) {
Type elem = ((Attribute.Class) value).type;
Type elem = ((Attribute.Class) value).classType;
elems.append(elem);
}
value = new MirroredTypesExceptionProxy(elems.toList());

View file

@ -250,6 +250,70 @@ compiler.err.duplicate.annotation=\
compiler.err.duplicate.annotation.member.value=\
duplicate annotation member value {0} in {1}
# 0: type
compiler.err.duplicate.annotation.missing.container=\
duplicate annotation, the declaration of {0} does not have a ContainedBy annotation
# 0: type, 1: type
compiler.err.invalid.container.no.containedby=\
invalid contained repeatable annotation, {0} is not annotated with {1}
# 0: type, 1: type
compiler.err.invalid.container.wrong.containedby=\
invalid contained repeatable annotation, {0} does not match {1}
# 0: type, 1: type
compiler.err.invalid.container.no.containerfor=\
invalid container for repeating annotations, {0} is not annotated with {1}
# 0: type, 1: type
compiler.err.invalid.container.wrong.containerfor=\
invalid container for repeating annotations, {0} does not match {1}
# 0: type
compiler.err.invalid.containedby.annotation=\
duplicate annotation, {0} is annotated with an invalid ContainedBy annotation
# 0: type
compiler.err.invalid.containedby.annotation.no.value=\
duplicate annotation, {0} is not a valid ContainedBy, no value element method declared
# 0: type, 1: number
compiler.err.invalid.containedby.annotation.multiple.values=\
duplicate annotation, {0} is not a valid ContainedBy, {1} value element methods declared
# 0: type
compiler.err.invalid.containedby.annotation.invalid.value=\
duplicate annotation, {0} is not a valid ContainedBy, invalid value element, need a method
# 0: type, 1: type, 2: type
compiler.err.invalid.containedby.annotation.value.return=\
duplicate annotation, value element of containing annotation {0} should have type {2}, found {1}
# 0: type, 1: symbol
compiler.err.invalid.containedby.annotation.elem.nondefault=\
duplicate annotation, element {1} in containing annotation {0} does not have a default value
# 0: symbol, 1: type, 2: symbol, 3: type
compiler.err.invalid.containedby.annotation.retention=\
containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3}
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.not.documented=\
containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.not.inherited=\
containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.incompatible.target=\
target of container annotation {0} is not a subset of target of repeated annotation {1}
# 0: symbol
compiler.err.invalid.containedby.annotation.repeated.and.container.present=\
container {0} must not be present at the same time as the element it contains
# 0: name
compiler.err.duplicate.class=\
duplicate class: {0}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2012, 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
@ -206,9 +206,7 @@ public class CreateSymbols extends AbstractProcessor {
}
ClassSymbol cs = (ClassSymbol) sym;
if (addLegacyAnnotation) {
cs.attributes_field = (cs.attributes_field == null)
? List.of(proprietary)
: cs.attributes_field.prepend(proprietary);
cs.annotations.prepend(List.of(proprietary));
}
writeClass(pool, cs, writer);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, 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
@ -740,7 +740,7 @@ public class TreeMaker implements JCTree.Factory {
result = Literal(v.value);
}
public void visitClass(Attribute.Class clazz) {
result = ClassLiteral(clazz.type).setType(syms.classType);
result = ClassLiteral(clazz.classType).setType(syms.classType);
}
public void visitEnum(Attribute.Enum e) {
result = QualIdent(e.value);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2012, 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
@ -83,7 +83,7 @@ public class AnnotationValueImpl implements AnnotationValue {
public void visitClass(Attribute.Class c) {
value = TypeMaker.getType(env,
env.types.erasure(c.type));
env.types.erasure(c.classType));
}
public void visitEnum(Attribute.Enum e) {

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean BasicRepeatingAnnotations BasicRepeatingAnnos BasicNonRepeatingAnno Foo Foos Bar
* @run compile BasicRepeatingAnnotations.java
* @run main BasicRepeatingAnnotations
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@ContainedBy(Foos.class)
@interface Foo {}
@ContainerFor(Foo.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Foos {
Foo[] value();
}
@interface Bar {}
@Foo @Foo
@Foo
@Bar
@Foo
@Foo
@Foo
@Foo
@Foo @Foo
@Foo
class BasicRepeatingAnnos {}
@Foo
class BasicNonRepeatingAnno {}
public class BasicRepeatingAnnotations {
public static void main(String[] args) throws Exception {
Annotation a = BasicRepeatingAnnos.class.getAnnotation(Foos.class);
if (a == null) {
throw new RuntimeException("Container annotation missing");
}
// verify that container not present on nonrepeating
a = BasicNonRepeatingAnno.class.getAnnotation(Foos.class);
if (a != null) {
throw new RuntimeException("Container annotation present");
}
a = BasicNonRepeatingAnno.class.getAnnotation(Foo.class);
if (a == null) {
throw new RuntimeException("Repeated annoation not directly present");
}
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean Foos Foo Bars Bar Baz Bazs CheckTargets
* @run compile CheckTargets.java
*/
import java.lang.annotation.*;
@ContainedBy(Foos.class)
@Target(ElementType.TYPE)
@interface Foo {}
@ContainerFor(Foo.class)
@Target(ElementType.ANNOTATION_TYPE)
@interface Foos {
Foo[] value();
}
@ContainedBy(Bars.class)
@Target(ElementType.TYPE)
@interface Bar {}
@ContainerFor(Bar.class)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE })
@interface Bars {
Bar[] value();
}
@ContainedBy(Bazs.class)
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@interface Baz {}
@ContainerFor(Baz.class)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE })
@interface Bazs {
Baz[] value();
}
public class CheckTargets {}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean Bar BarContainer ContainerHasRepeatedContained
* @run compile ContainerHasRepeatedContained.java
*/
import java.lang.annotation.ContainedBy;
import java.lang.annotation.ContainerFor;
@ContainedBy(BarContainer.class)
@interface Bar {}
@Bar
@Bar
@ContainerFor(Bar.class)
@interface BarContainer {
Bar[] value();
}
public class ContainerHasRepeatedContained {}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean DelayRepeatedContainer Bar BarContainer
* @run compile DelayRepeatedContainer.java
*/
import java.lang.annotation.*;
public class DelayRepeatedContainer {
@Bar("apa") @Bar("banan")
String meh() { return "meh"; }
}
@Bar("katt")
@Bar("lol")
@ContainedBy(BarContainer.class)
@interface Bar {
String value();
}
@ContainerFor(Bar.class)
@interface BarContainer {
Bar[] value();
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean Foos Foo
* @run compile/fail InvalidTarget.java
*/
import java.lang.annotation.*;
@ContainedBy(Foos.class)
@Target(ElementType.ANNOTATION_TYPE)
@interface Foo {}
@ContainerFor(Foo.class)
@Target(ElementType.TYPE)
@interface Foos {
Foo[] value();
}
public class InvalidTargets {}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail MissingContainedBy.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainerFor(MissingContainedBy.class)
@interface Foos {
MissingContainedBy[] value();
}
public @interface MissingContainedBy {}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail MissingContainerFor.java
* @bug 7151010
*/
import java.lang.annotation.*;
@interface Foos {
MissingContainerFor[] value();
}
@ContainedBy(Foos.class)
public @interface MissingContainerFor {}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean NestedContainers BasicRepeatingAnnos BasicRepeatingAnnos2 Foo Foos FoosFoos
* @run compile NestedContainers.java
* @run main NestedContainers
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@ContainedBy(Foos.class)
@interface Foo {}
@Retention(RetentionPolicy.RUNTIME)
@ContainedBy(FoosFoos.class)
@ContainerFor(Foo.class)
@interface Foos {
Foo[] value();
}
@ContainerFor(Foos.class)
@Retention(RetentionPolicy.RUNTIME)
@interface FoosFoos {
Foos[] value();
}
@Foo
@Foo
class BasicRepeatingAnnos {}
@Foos({})
@Foos({})
class BasicRepeatingAnnos2 {}
public class NestedContainers {
public static void main(String[] args) throws Exception {
Annotation a = BasicRepeatingAnnos.class.getAnnotation(Foos.class);
if (a == null) {
throw new RuntimeException("Container annotation missing");
}
// Check 2:nd level container
a = BasicRepeatingAnnos2.class.getAnnotation(FoosFoos.class);
if (a == null) {
throw new RuntimeException("Container annotation missing");
}
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean RepMemberAnno Bar BarContainer
* @run compile RepMemberAnno.java
*/
import java.lang.annotation.ContainedBy;
import java.lang.annotation.ContainerFor;
public class RepMemberAnno {
@Bar("Apa") @Bar("Banan")
public void meh() {}
}
@ContainedBy(BarContainer.class)
@interface Bar {
String value();
}
@ContainerFor(Bar.class)
@interface BarContainer {
Bar[] value();
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean RepSelfMemberAnno BarContainer BarContainerContainer
* @run compile RepSelfMemberAnno.java
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@ContainedBy(BarContainer.class)
public @interface RepSelfMemberAnno {
@RepSelfMemberAnno @RepSelfMemberAnno
String meh() default "banan";
}
@ContainedBy(BarContainerContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@ContainerFor(RepSelfMemberAnno.class)
@interface BarContainer {
RepSelfMemberAnno[] value();
}
@ContainerFor(BarContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@interface BarContainerContainer {
BarContainer[] value();
String meh() default "apa";
}
@BarContainer(value={})
@BarContainer(value={})
@interface Bar {}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail RepeatingAndContainerPresent.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainedBy(Foos.class)
@interface Foo {}
@interface Foos {
Foo[] value();
}
@Foo
@Foo
@Foos({})
public class RepeatingAndContainerPresent {}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @bug 7151010
*
* @run clean SelfRepeatingAnnotations Foos SelfRepeatingAnno
* @run compile SelfRepeatingAnnotations.java
* @run main SelfRepeatingAnnotations
*/
import java.lang.annotation.*;
@ContainerFor(SelfRepeatingAnno.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Foos {
SelfRepeatingAnno[] value();
}
@SelfRepeatingAnno
@Retention(RetentionPolicy.RUNTIME)
@SelfRepeatingAnno
@ContainedBy(Foos.class)
@interface SelfRepeatingAnno {}
public class SelfRepeatingAnnotations {
public static void main(String[] args) throws Exception {
Annotation a = SelfRepeatingAnno.class.getAnnotation(Foos.class);
if (a == null) {
throw new RuntimeException("Container annotation missing");
}
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile SingleRepeatingAndContainer.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainedBy(Foos.class)
@interface Foo {}
@ContainerFor(Foo.class)
@interface Foos {
Foo[] value();
}
@Foo
@Foos({})
public class SingleRepeatingAndContainer {}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail UseWrongContainedBy.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainerFor(UseWrongContainedBy.class)
@interface Foos {
UseWrongContainedBy[] value();
}
@ContainedBy(Target.class)
public @interface UseWrongContainedBy {}
@UseWrongContainedBy @UseWrongContainedBy
@interface Foo {}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail UseWrongContainerFor.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainerFor(Retention.class)
@interface Foos {
UseWrongContainerFor[] value();
}
@ContainedBy(Foos.class)
public @interface UseWrongContainerFor {}
@UseWrongContainerFor @UseWrongContainerFor
@interface Foo {}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail WrongContainedBy.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainerFor(WrongContainedBy.class)
@interface Foos {
WrongContainedBy[] value();
}
@ContainedBy(Target.class)
public @interface WrongContainedBy {}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, 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
* @summary Smoke test for repeating annotations
* @compile/fail WrongContainerFor.java
* @bug 7151010
*/
import java.lang.annotation.*;
@ContainerFor(Retention.class)
@interface Foos {
WrongContainerFor[] value();
}
@ContainedBy(Foos.class)
public @interface WrongContainerFor {}

View file

@ -5,6 +5,9 @@ compiler.err.cant.apply.symbol
compiler.err.cant.read.file # (apt.JavaCompiler?)
compiler.err.cant.select.static.class.from.param.type
compiler.err.illegal.char.for.encoding
compiler.err.invalid.containedby.annotation # should not happen
compiler.err.invalid.containedby.annotation.invalid.value # "can't" happen
compiler.err.invalid.containedby.annotation.multiple.values # can't happen
compiler.err.io.exception # (javah.JavahTask?)
compiler.err.limit.code # Code
compiler.err.limit.code.too.large.for.try.stmt # Gen

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.not.documented
import java.lang.annotation.*;
@Documented
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); }
@Anno
@Anno
class ContainedByDocumentedMismatch { }

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.not.inherited
import java.lang.annotation.*;
@Inherited
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); }
@Anno
@Anno
class ContainedByInheritedMismatch { }

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.no.value
import java.lang.annotation.*;
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos {}
@Anno
@Anno
class ContainedByNoValue { }

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.elem.nondefault
import java.lang.annotation.*;
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); String foo(); }
@Anno
@Anno
class ContainedByNonDefault { }

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.retention
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); }
@Anno
@Anno
class ContainedByRetentionMismatch { }

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.incompatible.target
import java.lang.annotation.*;
@ContainedBy(Annos.class)
@Target(ElementType.METHOD)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); }
class ContainedByTargetMismatch { }

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.value.return
import java.lang.annotation.*;
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { String value(); }
@Anno
@Anno
class ContainedByWrongValueType { }

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2012 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
@ -22,6 +22,8 @@
*/
// key: compiler.err.duplicate.annotation
// key: compiler.warn.source.no.bootclasspath
// options: -source 7
@interface Anno { }

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.duplicate.annotation.missing.container
@interface Anno { }
@Anno
@Anno
class DuplicateAnnotationJava8 { }

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.containedby.annotation.repeated.and.container.present
import java.lang.annotation.*;
@ContainedBy(Annos.class)
@interface Anno { }
@ContainerFor(Anno.class)
@interface Annos { Anno[] value(); }
@Anno
@Anno
@Annos(@Anno)
class RepeatingAnnotationAndContainer { }

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.container.no.containerfor
// key: compiler.err.invalid.container.wrong.containedby
import java.lang.annotation.*;
@ContainerFor(WrongContainedBy.class)
@interface Foos {
WrongContainedBy[] value();
}
@ContainedBy(Target.class)
public @interface WrongContainedBy {}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.invalid.container.wrong.containerfor
// key: compiler.err.invalid.container.no.containedby
import java.lang.annotation.*;
@ContainerFor(Retention.class)
@interface Foos {
WrongContainerFor[] value();
}
@ContainedBy(Foos.class)
public @interface WrongContainerFor {}