7151010: Add compiler support for repeating annotations
Reviewed-by: jjg, mcimadamore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java Fri Aug 31 10:37:46 2012 +0100
@@ -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;
+ }
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 @@
* 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 @@
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 @@
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();
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 @@
* 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);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Fri Aug 31 10:37:46 2012 +0100
@@ -203,6 +203,9 @@
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:
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Aug 31 10:37:46 2012 +0100
@@ -72,22 +72,24 @@
*/
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 @@
this.owner = owner;
this.completer = null;
this.erasure_field = null;
- this.attributes_field = List.nil();
this.name = name;
}
@@ -657,10 +658,11 @@
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 List<Attribute.Compound> getAnnotationMirrors() {
if (completer != null) complete();
- return Assert.checkNonNull(attributes_field);
+ return Assert.checkNonNull(annotations.getAttributes());
}
public Type erasure(Types types) {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Aug 31 10:37:46 2012 +0100
@@ -156,6 +156,10 @@
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 @@
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,
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Aug 31 10:37:46 2012 +0100
@@ -1358,6 +1358,20 @@
}
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 @@
// <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) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 @@
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 @@
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 @@
try {
while (q.nonEmpty())
q.next().enterAnnotation();
+
+ while (repeatedQ.nonEmpty()) {
+ repeatedQ.next().enterAnnotation();
+ }
} finally {
enterCount--;
}
@@ -124,6 +137,53 @@
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 @@
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;
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Aug 31 10:37:46 2012 +0100
@@ -662,10 +662,12 @@
// 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 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 @@
}
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 @@
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 @@
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 @@
}
}
// 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 {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Aug 31 10:37:46 2012 +0100
@@ -69,7 +69,6 @@
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 @@
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 @@
/** 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 @@
}
}
+ /**
+ * 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 @@
/** 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 @@
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) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java Fri Aug 31 10:37:46 2012 +0100
@@ -157,7 +157,7 @@
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;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Aug 31 10:37:46 2012 +0100
@@ -406,7 +406,7 @@
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 @@
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 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 @@
}
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 @@
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 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 @@
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 @@
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 @@
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);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Aug 31 10:37:46 2012 +0100
@@ -2257,7 +2257,7 @@
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 @@
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;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Aug 31 10:37:46 2012 +0100
@@ -76,11 +76,10 @@
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 @@
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 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 @@
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 @@
* 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 @@
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 {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Aug 31 10:37:46 2012 +0100
@@ -1321,7 +1321,7 @@
else
proxies.append(proxy);
}
- annotate.later(new AnnotationCompleter(sym, proxies.toList()));
+ annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
}
}
@@ -1347,7 +1347,7 @@
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 @@
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;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Aug 31 10:37:46 2012 +0100
@@ -825,7 +825,7 @@
}
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('@');
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java Fri Aug 31 10:37:46 2012 +0100
@@ -157,7 +157,7 @@
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;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 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 @@
// 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());
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Aug 31 10:37:46 2012 +0100
@@ -250,6 +250,70 @@
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}
--- a/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 @@
}
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);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 @@
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);
--- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java Fri Aug 31 10:37:46 2012 +0100
@@ -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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java Fri Aug 31 10:37:46 2012 +0100
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java Fri Aug 31 10:37:46 2012 +0100
@@ -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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java Fri Aug 31 10:37:46 2012 +0100
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java Fri Aug 31 10:37:46 2012 +0100
@@ -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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Aug 31 10:37:46 2012 +0100
@@ -5,6 +5,9 @@
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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- a/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java Mon Aug 27 10:59:13 2012 -0700
+++ b/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateAnnotationJava8.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/WrongContainedBy.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/WrongContainerFor.java Fri Aug 31 10:37:46 2012 +0100
@@ -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 {}