8013852: update reference impl for type-annotations
Co-authored-by: Steve Sides <steve.sides@oracle.com> Co-authored-by: Joel Borggren-Franck <joel.franck@oracle.com> Co-authored-by: Alex Buckley <alex.buckley@oracle.com> Reviewed-by: jjg
This commit is contained in:
parent
ac02470255
commit
54582cab82
@ -751,7 +751,7 @@ public class ClassWriter {
|
||||
break;
|
||||
// exception parameter
|
||||
case EXCEPTION_PARAMETER:
|
||||
out.writeByte(p.exception_index);
|
||||
out.writeShort(p.exception_index);
|
||||
break;
|
||||
// method receiver
|
||||
case METHOD_RECEIVER:
|
||||
@ -770,11 +770,11 @@ public class ClassWriter {
|
||||
break;
|
||||
// class extends or implements clause
|
||||
case CLASS_EXTENDS:
|
||||
out.writeByte(p.type_index);
|
||||
out.writeShort(p.type_index);
|
||||
break;
|
||||
// throws
|
||||
case THROWS:
|
||||
out.writeByte(p.type_index);
|
||||
out.writeShort(p.type_index);
|
||||
break;
|
||||
// method parameter
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
|
@ -111,7 +111,7 @@ public class TypeAnnotation {
|
||||
break;
|
||||
// exception parameter
|
||||
case EXCEPTION_PARAMETER:
|
||||
position.exception_index = cr.readUnsignedByte();
|
||||
position.exception_index = cr.readUnsignedShort();
|
||||
break;
|
||||
// method receiver
|
||||
case METHOD_RECEIVER:
|
||||
@ -198,7 +198,7 @@ public class TypeAnnotation {
|
||||
break;
|
||||
// exception parameter
|
||||
case EXCEPTION_PARAMETER:
|
||||
n += 1; // exception_index
|
||||
n += 2; // exception_index
|
||||
break;
|
||||
// method receiver
|
||||
case METHOD_RECEIVER:
|
||||
|
@ -1726,7 +1726,7 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
return text;
|
||||
}
|
||||
|
||||
static Set<String> blockTags = new HashSet<String>();
|
||||
static final Set<String> blockTags = new HashSet<String>();
|
||||
static {
|
||||
for (HtmlTag t: HtmlTag.values()) {
|
||||
if (t.blockType == HtmlTag.BlockType.BLOCK)
|
||||
@ -1771,7 +1771,7 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static final boolean isHtmlTagLetterOrDigit(char ch) {
|
||||
private static boolean isHtmlTagLetterOrDigit(char ch) {
|
||||
return ('a' <= ch && ch <= 'z') ||
|
||||
('A' <= ch && ch <= 'Z') ||
|
||||
('1' <= ch && ch <= '6');
|
||||
|
@ -76,10 +76,23 @@ public class Annotations {
|
||||
private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
|
||||
|
||||
/*
|
||||
* This field should never be null
|
||||
* Type attributes for this symbol.
|
||||
* This field should never be null.
|
||||
*/
|
||||
private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil();
|
||||
|
||||
/*
|
||||
* Type attributes of initializers in this class.
|
||||
* Unused if the current symbol is not a ClassSymbol.
|
||||
*/
|
||||
private List<Attribute.TypeCompound> init_type_attributes = List.<Attribute.TypeCompound>nil();
|
||||
|
||||
/*
|
||||
* Type attributes of class initializers in this class.
|
||||
* Unused if the current symbol is not a ClassSymbol.
|
||||
*/
|
||||
private List<Attribute.TypeCompound> clinit_type_attributes = List.<Attribute.TypeCompound>nil();
|
||||
|
||||
/*
|
||||
* The Symbol this Annotations instance belongs to
|
||||
*/
|
||||
@ -97,6 +110,14 @@ public class Annotations {
|
||||
return type_attributes;
|
||||
}
|
||||
|
||||
public List<Attribute.TypeCompound> getInitTypeAttributes() {
|
||||
return init_type_attributes;
|
||||
}
|
||||
|
||||
public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
|
||||
return clinit_type_attributes;
|
||||
}
|
||||
|
||||
public void setDeclarationAttributes(List<Attribute.Compound> a) {
|
||||
Assert.check(pendingCompletion() || !isStarted());
|
||||
if (a == null) {
|
||||
@ -112,12 +133,28 @@ public class Annotations {
|
||||
type_attributes = a;
|
||||
}
|
||||
|
||||
public void setInitTypeAttributes(List<Attribute.TypeCompound> a) {
|
||||
if (a == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
init_type_attributes = a;
|
||||
}
|
||||
|
||||
public void setClassInitTypeAttributes(List<Attribute.TypeCompound> a) {
|
||||
if (a == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
clinit_type_attributes = a;
|
||||
}
|
||||
|
||||
public void setAttributes(Annotations other) {
|
||||
if (other == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
setDeclarationAttributes(other.getDeclarationAttributes());
|
||||
setTypeAttributes(other.getTypeAttributes());
|
||||
setInitTypeAttributes(other.getInitTypeAttributes());
|
||||
setClassInitTypeAttributes(other.getClassInitTypeAttributes());
|
||||
}
|
||||
|
||||
public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) {
|
||||
@ -232,6 +269,28 @@ public class Annotations {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
if (l.isEmpty()) {
|
||||
; // no-op
|
||||
} else if (init_type_attributes.isEmpty()) {
|
||||
init_type_attributes = l;
|
||||
} else {
|
||||
init_type_attributes = init_type_attributes.appendList(l);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
if (l.isEmpty()) {
|
||||
; // no-op
|
||||
} else if (clinit_type_attributes.isEmpty()) {
|
||||
clinit_type_attributes = l;
|
||||
} else {
|
||||
clinit_type_attributes = clinit_type_attributes.appendList(l);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations prepend(List<Attribute.Compound> l) {
|
||||
attributes = filterDeclSentinels(attributes);
|
||||
|
||||
|
@ -230,6 +230,42 @@ public abstract class Attribute implements AnnotationValue {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public boolean hasUnknownPosition() {
|
||||
return position == null || position.type == TargetType.UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean isContainerTypeCompound() {
|
||||
if (isSynthesized() && values.size() == 1)
|
||||
return getFirstEmbeddedTC() != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private TypeCompound getFirstEmbeddedTC() {
|
||||
if (values.size() == 1) {
|
||||
Pair<MethodSymbol, Attribute> val = values.get(0);
|
||||
if (val.fst.getSimpleName().contentEquals("value")
|
||||
&& val.snd instanceof Array) {
|
||||
Array arr = (Array) val.snd;
|
||||
if (arr.values.length != 0
|
||||
&& arr.values[0] instanceof Attribute.TypeCompound)
|
||||
return (Attribute.TypeCompound) arr.values[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean tryFixPosition() {
|
||||
if (!isContainerTypeCompound())
|
||||
return false;
|
||||
|
||||
TypeCompound from = getFirstEmbeddedTC();
|
||||
if (from != null && from.position != null &&
|
||||
from.position.type != TargetType.UNKNOWN) {
|
||||
position = from.position;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** The value for an annotation element of an array type.
|
||||
|
@ -31,6 +31,7 @@ import javax.lang.model.type.TypeKind;
|
||||
|
||||
import com.sun.tools.javac.api.Messages;
|
||||
import com.sun.tools.javac.code.Type.AnnotatedType;
|
||||
import com.sun.tools.javac.code.Type.ArrayType;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.util.List;
|
||||
@ -127,7 +128,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a localized string represenation for a given type.
|
||||
* Get a localized string representation for a given type.
|
||||
*
|
||||
* @param t type to be displayed
|
||||
* @param locale the locale in which the string is to be rendered
|
||||
@ -138,7 +139,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a localized string represenation for a given symbol.
|
||||
* Get a localized string representation for a given symbol.
|
||||
*
|
||||
* @param s symbol to be displayed
|
||||
* @param locale the locale in which the string is to be rendered
|
||||
@ -182,7 +183,33 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
|
||||
@Override
|
||||
public String visitArrayType(ArrayType t, Locale locale) {
|
||||
return visit(t.elemtype, locale) + "[]";
|
||||
StringBuilder res = new StringBuilder();
|
||||
printBaseElementType(t, res, locale);
|
||||
printBrackets(t, res, locale);
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
void printBaseElementType(Type t, StringBuilder sb, Locale locale) {
|
||||
Type arrel = t;
|
||||
while (arrel.getKind() == TypeKind.ARRAY) {
|
||||
arrel = arrel.unannotatedType();
|
||||
arrel = ((ArrayType) arrel).elemtype;
|
||||
}
|
||||
sb.append(visit(arrel, locale));
|
||||
}
|
||||
|
||||
void printBrackets(Type t, StringBuilder sb, Locale locale) {
|
||||
Type arrel = t;
|
||||
while (arrel.getKind() == TypeKind.ARRAY) {
|
||||
if (arrel.isAnnotated()) {
|
||||
sb.append(' ');
|
||||
sb.append(arrel.getAnnotationMirrors());
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append("[]");
|
||||
arrel = arrel.unannotatedType();
|
||||
arrel = ((ArrayType) arrel).elemtype;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -237,10 +264,22 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
public String visitAnnotatedType(AnnotatedType t, Locale locale) {
|
||||
if (t.typeAnnotations != null &&
|
||||
t.typeAnnotations.nonEmpty()) {
|
||||
// TODO: better logic for arrays, ...
|
||||
return "(" + t.typeAnnotations + " :: " + visit(t.underlyingType, locale) + ")";
|
||||
if (t.underlyingType.getKind() == TypeKind.ARRAY) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
printBaseElementType(t, res, locale);
|
||||
printBrackets(t, res, locale);
|
||||
return res.toString();
|
||||
} else if (t.underlyingType.getKind() == TypeKind.DECLARED &&
|
||||
t.underlyingType.getEnclosingType() != Type.noType) {
|
||||
return visit(t.underlyingType.getEnclosingType(), locale) +
|
||||
". " +
|
||||
t.typeAnnotations +
|
||||
" " + className((ClassType)t.underlyingType, false, locale);
|
||||
} else {
|
||||
return t.typeAnnotations + " " + visit(t.underlyingType, locale);
|
||||
}
|
||||
} else {
|
||||
return "({} :: " + visit(t.underlyingType, locale) + ")";
|
||||
return visit(t.underlyingType, locale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +292,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
|
||||
/**
|
||||
* Converts a class name into a (possibly localized) string. Anonymous
|
||||
* inner classes gets converted into a localized string.
|
||||
* inner classes get converted into a localized string.
|
||||
*
|
||||
* @param t the type of the class whose name is to be rendered
|
||||
* @param longform if set, the class' fullname is displayed - if unset the
|
||||
@ -266,7 +305,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
|
||||
if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
|
||||
StringBuilder s = new StringBuilder(visit(t.supertype_field, locale));
|
||||
for (List<Type> is = t.interfaces_field; is.nonEmpty(); is = is.tail) {
|
||||
s.append("&");
|
||||
s.append('&');
|
||||
s.append(visit(is.head, locale));
|
||||
}
|
||||
return s.toString();
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package com.sun.tools.javac.code;
|
||||
|
||||
import com.sun.tools.javac.model.JavacAnnoConstructs;
|
||||
import com.sun.tools.javac.model.JavacTypes;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
@ -34,10 +32,10 @@ import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.type.*;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.model.JavacAnnoConstructs;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import static com.sun.tools.javac.code.BoundKind.*;
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
@ -729,7 +727,7 @@ public class Type implements PrimitiveType {
|
||||
return s.toString();
|
||||
} else if (sym.name.isEmpty()) {
|
||||
String s;
|
||||
ClassType norm = (ClassType) tsym.type;
|
||||
ClassType norm = (ClassType) tsym.type.unannotatedType();
|
||||
if (norm == null) {
|
||||
s = Log.getLocalizedString("anonymous.class", (Object)null);
|
||||
} else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
|
||||
@ -781,7 +779,7 @@ public class Type implements PrimitiveType {
|
||||
return
|
||||
getEnclosingType().isErroneous() ||
|
||||
isErroneous(getTypeArguments()) ||
|
||||
this != tsym.type && tsym.type.isErroneous();
|
||||
this != tsym.type.unannotatedType() && tsym.type.isErroneous();
|
||||
}
|
||||
|
||||
public boolean isParameterized() {
|
||||
@ -1693,7 +1691,10 @@ public class Type implements PrimitiveType {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO more logic for arrays, etc.
|
||||
// This method is only used for internal debugging output.
|
||||
// See
|
||||
// com.sun.tools.javac.code.Printer.visitAnnotatedType(AnnotatedType, Locale)
|
||||
// for the user-visible logic.
|
||||
if (typeAnnotations != null &&
|
||||
!typeAnnotations.isEmpty()) {
|
||||
return "(" + typeAnnotations.toString() + " :: " + underlyingType.toString() + ")";
|
||||
@ -1705,9 +1706,13 @@ public class Type implements PrimitiveType {
|
||||
@Override
|
||||
public boolean contains(Type t) { return underlyingType.contains(t); }
|
||||
|
||||
// TODO: attach annotations?
|
||||
@Override
|
||||
public Type withTypeVar(Type t) { return underlyingType.withTypeVar(t); }
|
||||
public Type withTypeVar(Type t) {
|
||||
// Don't create a new AnnotatedType, as 'this' will
|
||||
// get its annotations set later.
|
||||
underlyingType = underlyingType.withTypeVar(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO: attach annotations?
|
||||
@Override
|
||||
|
@ -27,6 +27,7 @@ package com.sun.tools.javac.code;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
||||
import com.sun.tools.javac.util.*;
|
||||
|
||||
/** A type annotation position.
|
||||
@ -145,9 +146,18 @@ public class TypeAnnotationPosition {
|
||||
// For class extends, implements, and throws clauses
|
||||
public int type_index = Integer.MIN_VALUE;
|
||||
|
||||
// For exception parameters, index into exception table
|
||||
// For exception parameters, index into exception table.
|
||||
// In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index
|
||||
// to the catch type index - that value is only temporary.
|
||||
// Then in com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions
|
||||
// we use that value to determine the exception table index.
|
||||
public int exception_index = Integer.MIN_VALUE;
|
||||
|
||||
// If this type annotation is within a lambda expression,
|
||||
// store a pointer to the lambda expression tree in order
|
||||
// to allow a later translation to the right method.
|
||||
public JCLambda onLambda = null;
|
||||
|
||||
public TypeAnnotationPosition() {}
|
||||
|
||||
@Override
|
||||
@ -258,6 +268,11 @@ public class TypeAnnotationPosition {
|
||||
sb.append(", pos = ");
|
||||
sb.append(pos);
|
||||
|
||||
if (onLambda != null) {
|
||||
sb.append(", onLambda hash = ");
|
||||
sb.append(onLambda.hashCode());
|
||||
}
|
||||
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
@ -271,6 +286,17 @@ public class TypeAnnotationPosition {
|
||||
return !type.isLocal() || isValidOffset;
|
||||
}
|
||||
|
||||
|
||||
public boolean matchesPos(int pos) {
|
||||
return this.pos == pos;
|
||||
}
|
||||
|
||||
public void updatePosOffset(int to) {
|
||||
offset = to;
|
||||
lvarOffset = new int[]{to};
|
||||
isValidOffset = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the binary representation for a type path and set
|
||||
* the {@code location} field.
|
||||
|
@ -49,12 +49,16 @@ import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry;
|
||||
import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
|
||||
import com.sun.tools.javac.code.TypeTag;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.comp.Annotate;
|
||||
import com.sun.tools.javac.comp.Annotate.Annotator;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCNewClass;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.tree.TreeScanner;
|
||||
@ -81,17 +85,18 @@ public class TypeAnnotations {
|
||||
* determine the correct positions for type annotations.
|
||||
* This version only visits types in signatures and should be
|
||||
* called from MemberEnter.
|
||||
* The method returns the Annotator object that should be added
|
||||
* to the correct Annotate queue for later processing.
|
||||
* The method takes the Annotate object as parameter and
|
||||
* adds an Annotator to the correct Annotate queue for
|
||||
* later processing.
|
||||
*/
|
||||
public static Annotator organizeTypeAnnotationsSignatures(final Symtab syms, final Names names,
|
||||
final Log log, final JCClassDecl tree) {
|
||||
return new Annotator() {
|
||||
public static void organizeTypeAnnotationsSignatures(final Symtab syms, final Names names,
|
||||
final Log log, final JCClassDecl tree, Annotate annotate) {
|
||||
annotate.afterRepeated( new Annotator() {
|
||||
@Override
|
||||
public void enterAnnotation() {
|
||||
new TypeAnnotationPositions(syms, names, log, true).scan(tree);
|
||||
}
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,9 +107,103 @@ public class TypeAnnotations {
|
||||
new TypeAnnotationPositions(syms, names, log, false).scan(tree);
|
||||
}
|
||||
|
||||
private static class TypeAnnotationPositions extends TreeScanner {
|
||||
public enum AnnotationType { DECLARATION, TYPE, BOTH };
|
||||
|
||||
private enum AnnotationType { DECLARATION, TYPE, BOTH };
|
||||
/**
|
||||
* Determine whether an annotation is a declaration annotation,
|
||||
* a type annotation, or both.
|
||||
*/
|
||||
public static AnnotationType annotationType(Symtab syms, Names names,
|
||||
Attribute.Compound a, Symbol s) {
|
||||
Attribute.Compound atTarget =
|
||||
a.type.tsym.attribute(syms.annotationTargetType.tsym);
|
||||
if (atTarget == null) {
|
||||
return inferTargetMetaInfo(a, s);
|
||||
}
|
||||
Attribute atValue = atTarget.member(names.value);
|
||||
if (!(atValue instanceof Attribute.Array)) {
|
||||
Assert.error("annotationType(): bad @Target argument " + atValue +
|
||||
" (" + atValue.getClass() + ")");
|
||||
return AnnotationType.DECLARATION; // error recovery
|
||||
}
|
||||
Attribute.Array arr = (Attribute.Array) atValue;
|
||||
boolean isDecl = false, isType = false;
|
||||
for (Attribute app : arr.values) {
|
||||
if (!(app instanceof Attribute.Enum)) {
|
||||
Assert.error("annotationType(): unrecognized Attribute kind " + app +
|
||||
" (" + app.getClass() + ")");
|
||||
isDecl = true;
|
||||
continue;
|
||||
}
|
||||
Attribute.Enum e = (Attribute.Enum) app;
|
||||
if (e.value.name == names.TYPE) {
|
||||
if (s.kind == Kinds.TYP)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.FIELD) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind != Kinds.MTH)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.METHOD) {
|
||||
if (s.kind == Kinds.MTH &&
|
||||
!s.isConstructor())
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.PARAMETER) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind == Kinds.MTH &&
|
||||
(s.flags() & Flags.PARAMETER) != 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.CONSTRUCTOR) {
|
||||
if (s.kind == Kinds.MTH &&
|
||||
s.isConstructor())
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.LOCAL_VARIABLE) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind == Kinds.MTH &&
|
||||
(s.flags() & Flags.PARAMETER) == 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.ANNOTATION_TYPE) {
|
||||
if (s.kind == Kinds.TYP &&
|
||||
(s.flags() & Flags.ANNOTATION) != 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.PACKAGE) {
|
||||
if (s.kind == Kinds.PCK)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.TYPE_USE) {
|
||||
if (s.kind == Kinds.TYP ||
|
||||
s.kind == Kinds.VAR ||
|
||||
(s.kind == Kinds.MTH && !s.isConstructor() &&
|
||||
!s.type.getReturnType().hasTag(TypeTag.VOID)) ||
|
||||
(s.kind == Kinds.MTH && s.isConstructor()))
|
||||
isType = true;
|
||||
} else if (e.value.name == names.TYPE_PARAMETER) {
|
||||
/* Irrelevant in this case */
|
||||
// TYPE_PARAMETER doesn't aid in distinguishing between
|
||||
// Type annotations and declaration annotations on an
|
||||
// Element
|
||||
} else {
|
||||
Assert.error("annotationType(): unrecognized Attribute name " + e.value.name +
|
||||
" (" + e.value.name.getClass() + ")");
|
||||
isDecl = true;
|
||||
}
|
||||
}
|
||||
if (isDecl && isType) {
|
||||
return AnnotationType.BOTH;
|
||||
} else if (isType) {
|
||||
return AnnotationType.TYPE;
|
||||
} else {
|
||||
return AnnotationType.DECLARATION;
|
||||
}
|
||||
}
|
||||
|
||||
/** Infer the target annotation kind, if none is give.
|
||||
* We only infer declaration annotations.
|
||||
*/
|
||||
private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) {
|
||||
return AnnotationType.DECLARATION;
|
||||
}
|
||||
|
||||
|
||||
private static class TypeAnnotationPositions extends TreeScanner {
|
||||
|
||||
private final Symtab syms;
|
||||
private final Names names;
|
||||
@ -154,7 +253,7 @@ public class TypeAnnotations {
|
||||
ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>();
|
||||
|
||||
for (Attribute.Compound a : annotations) {
|
||||
switch (annotationType(a, sym)) {
|
||||
switch (annotationType(syms, names, a, sym)) {
|
||||
case DECLARATION:
|
||||
declAnnos.append(a);
|
||||
break;
|
||||
@ -175,6 +274,10 @@ public class TypeAnnotations {
|
||||
sym.annotations.reset();
|
||||
sym.annotations.setDeclarationAttributes(declAnnos.toList());
|
||||
|
||||
if (typeAnnos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Attribute.TypeCompound> typeAnnotations = typeAnnos.toList();
|
||||
|
||||
if (type == null) {
|
||||
@ -190,16 +293,33 @@ public class TypeAnnotations {
|
||||
|
||||
if (sym.getKind() == ElementKind.METHOD) {
|
||||
sym.type.asMethodType().restype = type;
|
||||
} else if (sym.getKind() == ElementKind.PARAMETER) {
|
||||
sym.type = type;
|
||||
if (sym.getQualifiedName().equals(names._this)) {
|
||||
sym.owner.type.asMethodType().recvtype = type;
|
||||
// note that the typeAnnotations will also be added to the owner below.
|
||||
} else {
|
||||
MethodType methType = sym.owner.type.asMethodType();
|
||||
List<VarSymbol> params = ((MethodSymbol)sym.owner).params;
|
||||
List<Type> oldArgs = methType.argtypes;
|
||||
ListBuffer<Type> newArgs = new ListBuffer<Type>();
|
||||
while (params.nonEmpty()) {
|
||||
if (params.head == sym) {
|
||||
newArgs.add(type);
|
||||
} else {
|
||||
newArgs.add(oldArgs.head);
|
||||
}
|
||||
oldArgs = oldArgs.tail;
|
||||
params = params.tail;
|
||||
}
|
||||
methType.argtypes = newArgs.toList();
|
||||
}
|
||||
} else {
|
||||
sym.type = type;
|
||||
}
|
||||
|
||||
sym.annotations.appendUniqueTypes(typeAnnotations);
|
||||
if (sym.getKind() == ElementKind.PARAMETER &&
|
||||
sym.getQualifiedName().equals(names._this)) {
|
||||
sym.owner.type.asMethodType().recvtype = type;
|
||||
// note that the typeAnnotations will also be added to the owner below.
|
||||
}
|
||||
|
||||
if (sym.getKind() == ElementKind.PARAMETER ||
|
||||
sym.getKind() == ElementKind.LOCAL_VARIABLE ||
|
||||
sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
|
||||
@ -276,10 +396,21 @@ public class TypeAnnotations {
|
||||
TypeAnnotationPosition p = a.position;
|
||||
p.location = p.location.prependList(depth.toList());
|
||||
}
|
||||
typetree.type = toreturn;
|
||||
return toreturn;
|
||||
} else if (type.hasTag(TypeTag.TYPEVAR)) {
|
||||
// Nothing to do for type variables.
|
||||
return type;
|
||||
} else if (type.getKind() == TypeKind.UNION) {
|
||||
// There is a TypeKind, but no TypeTag.
|
||||
JCTypeUnion tutree = (JCTypeUnion) typetree;
|
||||
JCExpression fst = tutree.alternatives.get(0);
|
||||
Type res = typeWithAnnotations(fst, fst.type, annotations, log);
|
||||
fst.type = res;
|
||||
// TODO: do we want to set res as first element in uct.alternatives?
|
||||
// UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type;
|
||||
// Return the un-annotated union-type.
|
||||
return type;
|
||||
} else {
|
||||
Type enclTy = type;
|
||||
Element enclEl = type.asElement();
|
||||
@ -357,6 +488,7 @@ public class TypeAnnotations {
|
||||
}
|
||||
|
||||
Type ret = typeWithAnnotations(type, enclTy, annotations);
|
||||
typetree.type = ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -480,94 +612,6 @@ public class TypeAnnotations {
|
||||
return new Attribute.TypeCompound(a, p);
|
||||
}
|
||||
|
||||
private AnnotationType annotationType(Attribute.Compound a, Symbol s) {
|
||||
Attribute.Compound atTarget =
|
||||
a.type.tsym.attribute(syms.annotationTargetType.tsym);
|
||||
if (atTarget == null) {
|
||||
return inferTargetMetaInfo(a, s);
|
||||
}
|
||||
Attribute atValue = atTarget.member(names.value);
|
||||
if (!(atValue instanceof Attribute.Array)) {
|
||||
Assert.error("annotationType(): bad @Target argument " + atValue +
|
||||
" (" + atValue.getClass() + ")");
|
||||
return AnnotationType.DECLARATION; // error recovery
|
||||
}
|
||||
Attribute.Array arr = (Attribute.Array) atValue;
|
||||
boolean isDecl = false, isType = false;
|
||||
for (Attribute app : arr.values) {
|
||||
if (!(app instanceof Attribute.Enum)) {
|
||||
Assert.error("annotationType(): unrecognized Attribute kind " + app +
|
||||
" (" + app.getClass() + ")");
|
||||
isDecl = true;
|
||||
continue;
|
||||
}
|
||||
Attribute.Enum e = (Attribute.Enum) app;
|
||||
if (e.value.name == names.TYPE) {
|
||||
if (s.kind == Kinds.TYP)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.FIELD) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind != Kinds.MTH)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.METHOD) {
|
||||
if (s.kind == Kinds.MTH &&
|
||||
!s.isConstructor())
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.PARAMETER) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind == Kinds.MTH &&
|
||||
(s.flags() & Flags.PARAMETER) != 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.CONSTRUCTOR) {
|
||||
if (s.kind == Kinds.MTH &&
|
||||
s.isConstructor())
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.LOCAL_VARIABLE) {
|
||||
if (s.kind == Kinds.VAR &&
|
||||
s.owner.kind == Kinds.MTH &&
|
||||
(s.flags() & Flags.PARAMETER) == 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.ANNOTATION_TYPE) {
|
||||
if (s.kind == Kinds.TYP &&
|
||||
(s.flags() & Flags.ANNOTATION) != 0)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.PACKAGE) {
|
||||
if (s.kind == Kinds.PCK)
|
||||
isDecl = true;
|
||||
} else if (e.value.name == names.TYPE_USE) {
|
||||
if (s.kind == Kinds.TYP ||
|
||||
s.kind == Kinds.VAR ||
|
||||
(s.kind == Kinds.MTH && !s.isConstructor() &&
|
||||
!s.type.getReturnType().hasTag(TypeTag.VOID)) ||
|
||||
(s.kind == Kinds.MTH && s.isConstructor()))
|
||||
isType = true;
|
||||
} else if (e.value.name == names.TYPE_PARAMETER) {
|
||||
/* Irrelevant in this case */
|
||||
// TYPE_PARAMETER doesn't aid in distinguishing between
|
||||
// Type annotations and declaration annotations on an
|
||||
// Element
|
||||
} else {
|
||||
Assert.error("annotationType(): unrecognized Attribute name " + e.value.name +
|
||||
" (" + e.value.name.getClass() + ")");
|
||||
isDecl = true;
|
||||
}
|
||||
}
|
||||
if (isDecl && isType) {
|
||||
return AnnotationType.BOTH;
|
||||
} else if (isType) {
|
||||
return AnnotationType.TYPE;
|
||||
} else {
|
||||
return AnnotationType.DECLARATION;
|
||||
}
|
||||
}
|
||||
|
||||
/** Infer the target annotation kind, if none is give.
|
||||
* We only infer declaration annotations.
|
||||
*/
|
||||
private static AnnotationType inferTargetMetaInfo(Attribute.Compound a, Symbol s) {
|
||||
return AnnotationType.DECLARATION;
|
||||
}
|
||||
|
||||
|
||||
/* This is the beginning of the second part of organizing
|
||||
* type annotations: determine the type annotation positions.
|
||||
@ -585,7 +629,13 @@ public class TypeAnnotations {
|
||||
|
||||
switch (frame.getKind()) {
|
||||
case TYPE_CAST:
|
||||
JCTypeCast frameTC = (JCTypeCast) frame;
|
||||
p.type = TargetType.CAST;
|
||||
if (frameTC.clazz.hasTag(Tag.TYPEINTERSECTION)) {
|
||||
// This case was already handled by INTERSECTION_TYPE
|
||||
} else {
|
||||
p.type_index = 0;
|
||||
}
|
||||
p.pos = frame.pos;
|
||||
return;
|
||||
|
||||
@ -595,8 +645,22 @@ public class TypeAnnotations {
|
||||
return;
|
||||
|
||||
case NEW_CLASS:
|
||||
JCNewClass frameNewClass = (JCNewClass)frame;
|
||||
if (frameNewClass.typeargs.contains(tree)) {
|
||||
JCNewClass frameNewClass = (JCNewClass) frame;
|
||||
if (frameNewClass.def != null) {
|
||||
// Special handling for anonymous class instantiations
|
||||
JCClassDecl frameClassDecl = frameNewClass.def;
|
||||
if (frameClassDecl.extending == tree) {
|
||||
p.type = TargetType.CLASS_EXTENDS;
|
||||
p.type_index = -1;
|
||||
} else if (frameClassDecl.implementing.contains(tree)) {
|
||||
p.type = TargetType.CLASS_EXTENDS;
|
||||
p.type_index = frameClassDecl.implementing.indexOf(tree);
|
||||
} else {
|
||||
// In contrast to CLASS below, typarams cannot occur here.
|
||||
Assert.error("Could not determine position of tree " + tree +
|
||||
" within frame " + frame);
|
||||
}
|
||||
} else if (frameNewClass.typeargs.contains(tree)) {
|
||||
p.type = TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
|
||||
p.type_index = frameNewClass.typeargs.indexOf(tree);
|
||||
} else {
|
||||
@ -649,6 +713,8 @@ public class TypeAnnotations {
|
||||
}
|
||||
|
||||
case PARAMETERIZED_TYPE: {
|
||||
List<JCTree> newPath = path.tail;
|
||||
|
||||
if (((JCTypeApply)frame).clazz == tree) {
|
||||
// generic: RAW; noop
|
||||
} else if (((JCTypeApply)frame).arguments.contains(tree)) {
|
||||
@ -656,13 +722,21 @@ public class TypeAnnotations {
|
||||
int arg = taframe.arguments.indexOf(tree);
|
||||
p.location = p.location.prepend(new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg));
|
||||
|
||||
locateNestedTypes(taframe.type, p);
|
||||
Type typeToUse;
|
||||
if (newPath.tail != null && newPath.tail.head.hasTag(Tag.NEWCLASS)) {
|
||||
// If we are within an anonymous class instantiation, use its type,
|
||||
// because it contains a correctly nested type.
|
||||
typeToUse = newPath.tail.head.type;
|
||||
} else {
|
||||
typeToUse = taframe.type;
|
||||
}
|
||||
|
||||
locateNestedTypes(typeToUse, p);
|
||||
} else {
|
||||
Assert.error("Could not determine type argument position of tree " + tree +
|
||||
" within frame " + frame);
|
||||
}
|
||||
|
||||
List<JCTree> newPath = path.tail;
|
||||
resolveFrame(newPath.head, newPath.tail.head, newPath, p);
|
||||
return;
|
||||
}
|
||||
@ -780,6 +854,9 @@ public class TypeAnnotations {
|
||||
default:
|
||||
Assert.error("Found unexpected type annotation for variable: " + v + " with kind: " + v.getKind());
|
||||
}
|
||||
if (v.getKind() != ElementKind.FIELD) {
|
||||
v.owner.annotations.appendUniqueTypes(v.getRawTypeAttributes());
|
||||
}
|
||||
return;
|
||||
|
||||
case ANNOTATED_TYPE: {
|
||||
@ -789,6 +866,11 @@ public class TypeAnnotations {
|
||||
// not care about inner types.
|
||||
JCAnnotatedType atypetree = (JCAnnotatedType) frame;
|
||||
final Type utype = atypetree.underlyingType.type;
|
||||
if (utype == null) {
|
||||
// This might happen during DeferredAttr;
|
||||
// we will be back later.
|
||||
return;
|
||||
}
|
||||
Symbol tsym = utype.tsym;
|
||||
if (tsym.getKind().equals(ElementKind.TYPE_PARAMETER) ||
|
||||
utype.getKind().equals(TypeKind.WILDCARD) ||
|
||||
@ -806,8 +888,6 @@ public class TypeAnnotations {
|
||||
}
|
||||
|
||||
case UNION_TYPE: {
|
||||
// TODO: can we store any information here to help in
|
||||
// determining the final position?
|
||||
List<JCTree> newPath = path.tail;
|
||||
resolveFrame(newPath.head, newPath.tail.head, newPath, p);
|
||||
return;
|
||||
@ -873,11 +953,20 @@ public class TypeAnnotations {
|
||||
|
||||
private static int methodParamIndex(List<JCTree> path, JCTree param) {
|
||||
List<JCTree> curr = path;
|
||||
while (curr.head.getTag() != Tag.METHODDEF) {
|
||||
while (curr.head.getTag() != Tag.METHODDEF &&
|
||||
curr.head.getTag() != Tag.LAMBDA) {
|
||||
curr = curr.tail;
|
||||
}
|
||||
JCMethodDecl method = (JCMethodDecl)curr.head;
|
||||
return method.params.indexOf(param);
|
||||
if (curr.head.getTag() == Tag.METHODDEF) {
|
||||
JCMethodDecl method = (JCMethodDecl)curr.head;
|
||||
return method.params.indexOf(param);
|
||||
} else if (curr.head.getTag() == Tag.LAMBDA) {
|
||||
JCLambda lambda = (JCLambda)curr.head;
|
||||
return lambda.params.indexOf(param);
|
||||
} else {
|
||||
Assert.error("methodParamIndex expected to find method or lambda for param: " + param);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Each class (including enclosed inner classes) is visited separately.
|
||||
@ -889,6 +978,7 @@ public class TypeAnnotations {
|
||||
if (isInClass)
|
||||
return;
|
||||
isInClass = true;
|
||||
|
||||
if (sigOnly) {
|
||||
scan(tree.mods);
|
||||
scan(tree.typarams);
|
||||
@ -910,7 +1000,9 @@ public class TypeAnnotations {
|
||||
return;
|
||||
}
|
||||
if (sigOnly) {
|
||||
{
|
||||
if (!tree.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.METHOD_RETURN;
|
||||
if (tree.sym.isConstructor()) {
|
||||
@ -923,7 +1015,10 @@ public class TypeAnnotations {
|
||||
tree.sym, pos);
|
||||
}
|
||||
}
|
||||
if (tree.recvparam != null && tree.recvparam.sym != null) {
|
||||
if (tree.recvparam != null && tree.recvparam.sym != null &&
|
||||
!tree.recvparam.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
// TODO: make sure there are no declaration annotations.
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.METHOD_RECEIVER;
|
||||
@ -933,11 +1028,15 @@ public class TypeAnnotations {
|
||||
}
|
||||
int i = 0;
|
||||
for (JCVariableDecl param : tree.params) {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.METHOD_FORMAL_PARAMETER;
|
||||
pos.parameter_index = i;
|
||||
pos.pos = param.vartype.pos;
|
||||
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
|
||||
if (!param.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.METHOD_FORMAL_PARAMETER;
|
||||
pos.parameter_index = i;
|
||||
pos.pos = param.vartype.pos;
|
||||
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@ -958,16 +1057,53 @@ public class TypeAnnotations {
|
||||
pop();
|
||||
}
|
||||
|
||||
/* Store a reference to the current lambda expression, to
|
||||
* be used by all type annotations within this expression.
|
||||
*/
|
||||
private JCLambda currentLambda = null;
|
||||
|
||||
public void visitLambda(JCLambda tree) {
|
||||
JCLambda prevLambda = currentLambda;
|
||||
try {
|
||||
currentLambda = tree;
|
||||
|
||||
int i = 0;
|
||||
for (JCVariableDecl param : tree.params) {
|
||||
if (!param.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.METHOD_FORMAL_PARAMETER;
|
||||
pos.parameter_index = i;
|
||||
pos.pos = param.vartype.pos;
|
||||
pos.onLambda = tree;
|
||||
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
push(tree);
|
||||
scan(tree.body);
|
||||
scan(tree.params);
|
||||
pop();
|
||||
} finally {
|
||||
currentLambda = prevLambda;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve declaration vs. type annotations in variable declarations and
|
||||
* then determine the positions.
|
||||
*/
|
||||
@Override
|
||||
public void visitVarDef(final JCVariableDecl tree) {
|
||||
if (tree.sym == null) {
|
||||
if (tree.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
} else if (tree.sym == null) {
|
||||
// Something is wrong already. Quietly ignore.
|
||||
} else if (tree.sym.getKind() == ElementKind.PARAMETER) {
|
||||
// Parameters are handled in visitMethodDef above.
|
||||
// Parameters are handled in visitMethodDef or visitLambda.
|
||||
} else if (tree.sym.getKind() == ElementKind.FIELD) {
|
||||
if (sigOnly) {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
@ -979,16 +1115,19 @@ public class TypeAnnotations {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.LOCAL_VARIABLE;
|
||||
pos.pos = tree.pos;
|
||||
pos.onLambda = currentLambda;
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.EXCEPTION_PARAMETER;
|
||||
pos.pos = tree.pos;
|
||||
pos.onLambda = currentLambda;
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.RESOURCE_VARIABLE;
|
||||
pos.pos = tree.pos;
|
||||
pos.onLambda = currentLambda;
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
|
||||
// No type annotations can occur here.
|
||||
@ -1030,6 +1169,40 @@ public class TypeAnnotations {
|
||||
super.visitTypeParameter(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewClass(JCNewClass tree) {
|
||||
if (tree.def != null &&
|
||||
!tree.def.mods.annotations.isEmpty()) {
|
||||
JCClassDecl classdecl = tree.def;
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.CLASS_EXTENDS;
|
||||
pos.pos = tree.pos;
|
||||
if (classdecl.extending == tree.clazz) {
|
||||
pos.type_index = -1;
|
||||
} else if (classdecl.implementing.contains(tree.clazz)) {
|
||||
pos.type_index = classdecl.implementing.indexOf(tree.clazz);
|
||||
} else {
|
||||
// In contrast to CLASS elsewhere, typarams cannot occur here.
|
||||
Assert.error("Could not determine position of tree " + tree);
|
||||
}
|
||||
Type before = classdecl.sym.type;
|
||||
separateAnnotationsKinds(classdecl, tree.clazz.type, classdecl.sym, pos);
|
||||
|
||||
// classdecl.sym.type now contains an annotated type, which
|
||||
// is not what we want there.
|
||||
// TODO: should we put this type somewhere in the superclass/interface?
|
||||
classdecl.sym.type = before;
|
||||
}
|
||||
|
||||
scan(tree.encl);
|
||||
scan(tree.typeargs);
|
||||
scan(tree.clazz);
|
||||
scan(tree.args);
|
||||
|
||||
// The class body will already be scanned.
|
||||
// scan(tree.def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewArray(JCNewArray tree) {
|
||||
findPosition(tree, tree, tree.annotations);
|
||||
@ -1040,6 +1213,7 @@ public class TypeAnnotations {
|
||||
for (int i = 0; i < dimAnnosCount; ++i) {
|
||||
TypeAnnotationPosition p = new TypeAnnotationPosition();
|
||||
p.pos = tree.pos;
|
||||
p.onLambda = currentLambda;
|
||||
p.type = TargetType.NEW;
|
||||
if (i != 0) {
|
||||
depth = depth.append(TypePathEntry.ARRAY);
|
||||
@ -1053,18 +1227,23 @@ public class TypeAnnotations {
|
||||
// int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
|
||||
// TODO: is depth.size == i here?
|
||||
JCExpression elemType = tree.elemtype;
|
||||
depth = depth.append(TypePathEntry.ARRAY);
|
||||
while (elemType != null) {
|
||||
if (elemType.hasTag(JCTree.Tag.ANNOTATED_TYPE)) {
|
||||
JCAnnotatedType at = (JCAnnotatedType)elemType;
|
||||
TypeAnnotationPosition p = new TypeAnnotationPosition();
|
||||
p.type = TargetType.NEW;
|
||||
p.pos = tree.pos;
|
||||
p.location = p.location.appendList(depth.toList());
|
||||
p.onLambda = currentLambda;
|
||||
locateNestedTypes(elemType.type, p);
|
||||
p.location = p.location.prependList(depth.toList());
|
||||
setTypeAnnotationPos(at.annotations, p);
|
||||
elemType = at.underlyingType;
|
||||
} else if (elemType.hasTag(JCTree.Tag.TYPEARRAY)) {
|
||||
depth = depth.append(TypePathEntry.ARRAY);
|
||||
elemType = ((JCArrayTypeTree)elemType).elemtype;
|
||||
} else if (elemType.hasTag(JCTree.Tag.SELECT)) {
|
||||
elemType = ((JCFieldAccess)elemType).selected;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -1076,10 +1255,11 @@ public class TypeAnnotations {
|
||||
if (!annotations.isEmpty()) {
|
||||
/*
|
||||
System.out.println("Finding pos for: " + annotations);
|
||||
System.out.println(" tree: " + tree);
|
||||
System.out.println(" frame: " + frame);
|
||||
System.out.println(" tree: " + tree + " kind: " + tree.getKind());
|
||||
System.out.println(" frame: " + frame + " kind: " + frame.getKind());
|
||||
*/
|
||||
TypeAnnotationPosition p = new TypeAnnotationPosition();
|
||||
p.onLambda = currentLambda;
|
||||
resolveFrame(tree, frame, frames.toList(), p);
|
||||
setTypeAnnotationPos(annotations, p);
|
||||
}
|
||||
@ -1088,8 +1268,17 @@ public class TypeAnnotations {
|
||||
private static void setTypeAnnotationPos(List<JCAnnotation> annotations,
|
||||
TypeAnnotationPosition position) {
|
||||
for (JCAnnotation anno : annotations) {
|
||||
((Attribute.TypeCompound) anno.attribute).position = position;
|
||||
// attribute might be null during DeferredAttr;
|
||||
// we will be back later.
|
||||
if (anno.attribute != null) {
|
||||
((Attribute.TypeCompound) anno.attribute).position = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ": sigOnly: " + sigOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package com.sun.tools.javac.code;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
@ -34,8 +33,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
|
||||
@ -204,7 +201,7 @@ public class Types {
|
||||
WildcardType unb = new WildcardType(syms.objectType,
|
||||
BoundKind.UNBOUND,
|
||||
syms.boundClass,
|
||||
(TypeVar)parms.head);
|
||||
(TypeVar)parms.head.unannotatedType());
|
||||
if (!containsType(args.head, unb))
|
||||
return false;
|
||||
parms = parms.tail;
|
||||
@ -268,7 +265,7 @@ public class Types {
|
||||
List<Type> opens = openVars.toList();
|
||||
ListBuffer<Type> qs = new ListBuffer<Type>();
|
||||
for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) {
|
||||
qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head));
|
||||
qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head.unannotatedType()));
|
||||
}
|
||||
res = subst(res, opens, qs.toList());
|
||||
}
|
||||
@ -581,12 +578,12 @@ public class Types {
|
||||
//simply replace the wildcards with its bound
|
||||
for (Type t : formalInterface.getTypeArguments()) {
|
||||
if (actualTypeargs.head.hasTag(WILDCARD)) {
|
||||
WildcardType wt = (WildcardType)actualTypeargs.head;
|
||||
WildcardType wt = (WildcardType)actualTypeargs.head.unannotatedType();
|
||||
Type bound;
|
||||
switch (wt.kind) {
|
||||
case EXTENDS:
|
||||
case UNBOUND:
|
||||
CapturedType capVar = (CapturedType)capturedTypeargs.head;
|
||||
CapturedType capVar = (CapturedType)capturedTypeargs.head.unannotatedType();
|
||||
//use declared bound if it doesn't depend on formal type-args
|
||||
bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ?
|
||||
wt.type : capVar.bound;
|
||||
@ -964,6 +961,9 @@ public class Types {
|
||||
isSameTypeStrict.visit(t, s) :
|
||||
isSameTypeLoose.visit(t, s);
|
||||
}
|
||||
public boolean isSameAnnotatedType(Type t, Type s) {
|
||||
return isSameAnnotatedType.visit(t, s);
|
||||
}
|
||||
// where
|
||||
abstract class SameTypeVisitor extends TypeRelation {
|
||||
|
||||
@ -982,7 +982,7 @@ public class Types {
|
||||
if (s.tag == TYPEVAR) {
|
||||
//type-substitution does not preserve type-var types
|
||||
//check that type var symbols and bounds are indeed the same
|
||||
return sameTypeVars((TypeVar)t, (TypeVar)s);
|
||||
return sameTypeVars((TypeVar)t.unannotatedType(), (TypeVar)s.unannotatedType());
|
||||
}
|
||||
else {
|
||||
//special case for s == ? super X, where upper(s) = u
|
||||
@ -1096,7 +1096,9 @@ public class Types {
|
||||
* Standard type-equality relation - type variables are considered
|
||||
* equals if they share the same type symbol.
|
||||
*/
|
||||
TypeRelation isSameTypeLoose = new SameTypeVisitor() {
|
||||
TypeRelation isSameTypeLoose = new LooseSameTypeVisitor();
|
||||
|
||||
private class LooseSameTypeVisitor extends SameTypeVisitor {
|
||||
@Override
|
||||
boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
|
||||
return tv1.tsym == tv2.tsym && visit(tv1.getUpperBound(), tv2.getUpperBound());
|
||||
@ -1126,12 +1128,29 @@ public class Types {
|
||||
if (!s.hasTag(WILDCARD)) {
|
||||
return false;
|
||||
} else {
|
||||
WildcardType t2 = (WildcardType)s;
|
||||
WildcardType t2 = (WildcardType)s.unannotatedType();
|
||||
return t.kind == t2.kind &&
|
||||
isSameType(t.type, t2.type, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A version of LooseSameTypeVisitor that takes AnnotatedTypes
|
||||
* into account.
|
||||
*/
|
||||
TypeRelation isSameAnnotatedType = new LooseSameTypeVisitor() {
|
||||
@Override
|
||||
public Boolean visitAnnotatedType(AnnotatedType t, Type s) {
|
||||
if (!s.isAnnotated())
|
||||
return false;
|
||||
if (!t.getAnnotationMirrors().containsAll(s.getAnnotationMirrors()))
|
||||
return false;
|
||||
if (!s.getAnnotationMirrors().containsAll(t.getAnnotationMirrors()))
|
||||
return false;
|
||||
return visit(t.underlyingType, s);
|
||||
}
|
||||
};
|
||||
// </editor-fold>
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Contains Type">
|
||||
@ -1140,7 +1159,7 @@ public class Types {
|
||||
case UNDETVAR:
|
||||
if (s.tag == WILDCARD) {
|
||||
UndetVar undetvar = (UndetVar)t;
|
||||
WildcardType wt = (WildcardType)s;
|
||||
WildcardType wt = (WildcardType)s.unannotatedType();
|
||||
switch(wt.kind) {
|
||||
case UNBOUND: //similar to ? extends Object
|
||||
case EXTENDS: {
|
||||
@ -1207,7 +1226,7 @@ public class Types {
|
||||
|
||||
private Type U(Type t) {
|
||||
while (t.tag == WILDCARD) {
|
||||
WildcardType w = (WildcardType)t;
|
||||
WildcardType w = (WildcardType)t.unannotatedType();
|
||||
if (w.isSuperBound())
|
||||
return w.bound == null ? syms.objectType : w.bound.bound;
|
||||
else
|
||||
@ -1218,7 +1237,7 @@ public class Types {
|
||||
|
||||
private Type L(Type t) {
|
||||
while (t.tag == WILDCARD) {
|
||||
WildcardType w = (WildcardType)t;
|
||||
WildcardType w = (WildcardType)t.unannotatedType();
|
||||
if (w.isExtendsBound())
|
||||
return syms.botType;
|
||||
else
|
||||
@ -1276,15 +1295,15 @@ public class Types {
|
||||
};
|
||||
|
||||
public boolean isCaptureOf(Type s, WildcardType t) {
|
||||
if (s.tag != TYPEVAR || !((TypeVar)s).isCaptured())
|
||||
if (s.tag != TYPEVAR || !((TypeVar)s.unannotatedType()).isCaptured())
|
||||
return false;
|
||||
return isSameWildcard(t, ((CapturedType)s).wildcard);
|
||||
return isSameWildcard(t, ((CapturedType)s.unannotatedType()).wildcard);
|
||||
}
|
||||
|
||||
public boolean isSameWildcard(WildcardType t, Type s) {
|
||||
if (s.tag != WILDCARD)
|
||||
return false;
|
||||
WildcardType w = (WildcardType)s;
|
||||
WildcardType w = (WildcardType)s.unannotatedType();
|
||||
return w.kind == t.kind && w.type == t.type;
|
||||
}
|
||||
|
||||
@ -1373,8 +1392,8 @@ public class Types {
|
||||
|
||||
if (t.isCompound() || s.isCompound()) {
|
||||
return !t.isCompound() ?
|
||||
visitIntersectionType((IntersectionClassType)s, t, true) :
|
||||
visitIntersectionType((IntersectionClassType)t, s, false);
|
||||
visitIntersectionType((IntersectionClassType)s.unannotatedType(), t, true) :
|
||||
visitIntersectionType((IntersectionClassType)t.unannotatedType(), s, false);
|
||||
}
|
||||
|
||||
if (s.tag == CLASS || s.tag == ARRAY) {
|
||||
@ -3070,7 +3089,7 @@ public class Types {
|
||||
for (Type t : tvars) {
|
||||
if (!first) s.append(", ");
|
||||
first = false;
|
||||
appendTyparamString(((TypeVar)t), s);
|
||||
appendTyparamString(((TypeVar)t.unannotatedType()), s);
|
||||
}
|
||||
s.append('>');
|
||||
return s.toString();
|
||||
@ -3710,9 +3729,9 @@ public class Types {
|
||||
!currentS.isEmpty()) {
|
||||
if (currentS.head != currentT.head) {
|
||||
captured = true;
|
||||
WildcardType Ti = (WildcardType)currentT.head;
|
||||
WildcardType Ti = (WildcardType)currentT.head.unannotatedType();
|
||||
Type Ui = currentA.head.getUpperBound();
|
||||
CapturedType Si = (CapturedType)currentS.head;
|
||||
CapturedType Si = (CapturedType)currentS.head.unannotatedType();
|
||||
if (Ui == null)
|
||||
Ui = syms.objectType;
|
||||
switch (Ti.kind) {
|
||||
@ -3749,6 +3768,7 @@ public class Types {
|
||||
ListBuffer<Type> result = lb();
|
||||
for (Type t : types) {
|
||||
if (t.tag == WILDCARD) {
|
||||
t = t.unannotatedType();
|
||||
Type bound = ((WildcardType)t).getExtendsBound();
|
||||
if (bound == null)
|
||||
bound = syms.objectType;
|
||||
@ -3842,7 +3862,7 @@ public class Types {
|
||||
|
||||
private boolean giveWarning(Type from, Type to) {
|
||||
List<Type> bounds = to.isCompound() ?
|
||||
((IntersectionClassType)to).getComponents() : List.of(to);
|
||||
((IntersectionClassType)to.unannotatedType()).getComponents() : List.of(to);
|
||||
for (Type b : bounds) {
|
||||
Type subFrom = asSub(from, b.tsym);
|
||||
if (b.isParameterized() &&
|
||||
@ -4107,7 +4127,7 @@ public class Types {
|
||||
|
||||
Type B(Type t) {
|
||||
while (t.tag == WILDCARD) {
|
||||
WildcardType w = (WildcardType)t;
|
||||
WildcardType w = (WildcardType)t.unannotatedType();
|
||||
t = high ?
|
||||
w.getExtendsBound() :
|
||||
w.getSuperBound();
|
||||
@ -4182,7 +4202,7 @@ public class Types {
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof UniqueType) &&
|
||||
types.isSameType(type, ((UniqueType)obj).type);
|
||||
types.isSameAnnotatedType(type, ((UniqueType)obj).type);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -216,18 +216,42 @@ public class Annotate {
|
||||
Attribute.Compound enterAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env) {
|
||||
return enterAnnotation(a, expected, env, false);
|
||||
}
|
||||
|
||||
Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env) {
|
||||
return (Attribute.TypeCompound) enterAnnotation(a, expected, env, true);
|
||||
}
|
||||
|
||||
// boolean typeAnnotation determines whether the method returns
|
||||
// a Compound (false) or TypeCompound (true).
|
||||
Attribute.Compound enterAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env,
|
||||
boolean typeAnnotation) {
|
||||
// The annotation might have had its type attributed (but not checked)
|
||||
// by attr.attribAnnotationTypes during MemberEnter, in which case we do not
|
||||
// need to do it again.
|
||||
Type at = (a.annotationType.type != null ? a.annotationType.type
|
||||
: attr.attribType(a.annotationType, env));
|
||||
a.type = chk.checkType(a.annotationType.pos(), at, expected);
|
||||
if (a.type.isErroneous())
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
if (a.type.isErroneous()) {
|
||||
if (typeAnnotation) {
|
||||
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(), null);
|
||||
} else {
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
}
|
||||
}
|
||||
if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
|
||||
log.error(a.annotationType.pos(),
|
||||
"not.annotation.type", a.type.toString());
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
if (typeAnnotation) {
|
||||
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(), null);
|
||||
} else {
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
}
|
||||
}
|
||||
List<JCExpression> args = a.args;
|
||||
if (args.length() == 1 && !args.head.hasTag(ASSIGN)) {
|
||||
@ -266,12 +290,21 @@ public class Annotate {
|
||||
((MethodSymbol)method, value));
|
||||
t.type = result;
|
||||
}
|
||||
// TODO: this should be a TypeCompound if "a" is a JCTypeAnnotation.
|
||||
// However, how do we find the correct position?
|
||||
Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList());
|
||||
// TODO: is this something we want? Who would use it?
|
||||
// a.attribute = ac;
|
||||
return ac;
|
||||
if (typeAnnotation) {
|
||||
if (a.attribute == null || !(a.attribute instanceof Attribute.TypeCompound)) {
|
||||
// Create a new TypeCompound
|
||||
Attribute.TypeCompound tc = new Attribute.TypeCompound(a.type, buf.toList(), new TypeAnnotationPosition());
|
||||
a.attribute = tc;
|
||||
return tc;
|
||||
} else {
|
||||
// Use an existing TypeCompound
|
||||
return a.attribute;
|
||||
}
|
||||
} else {
|
||||
Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList());
|
||||
a.attribute = ac;
|
||||
return ac;
|
||||
}
|
||||
}
|
||||
|
||||
Attribute enterAttributeValue(Type expected,
|
||||
@ -354,15 +387,6 @@ public class Annotate {
|
||||
return new Attribute.Error(attr.attribExpr(tree, env, expected));
|
||||
}
|
||||
|
||||
Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env) {
|
||||
Attribute.Compound c = enterAnnotation(a, expected, env);
|
||||
Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, new TypeAnnotationPosition());
|
||||
a.attribute = tc;
|
||||
return tc;
|
||||
}
|
||||
|
||||
/* *********************************
|
||||
* Support for repeating annotations
|
||||
***********************************/
|
||||
|
@ -768,7 +768,12 @@ public class Attr extends JCTree.Visitor {
|
||||
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
|
||||
|
||||
try {
|
||||
memberEnter.typeAnnotate(initializer, env, env.info.enclVar);
|
||||
// Use null as symbol to not attach the type annotation to any symbol.
|
||||
// The initializer will later also be visited and then we'll attach
|
||||
// to the symbol.
|
||||
// This prevents having multiple type annotations, just because of
|
||||
// lazy constant value evaluation.
|
||||
memberEnter.typeAnnotate(initializer, env, null);
|
||||
annotate.flush();
|
||||
Type itype = attribExpr(initializer, env, type);
|
||||
if (itype.constValue() != null)
|
||||
@ -935,11 +940,6 @@ public class Attr extends JCTree.Visitor {
|
||||
Env<AttrContext> newEnv = memberEnter.methodEnv(tree, env);
|
||||
attribType(tree.recvparam, newEnv);
|
||||
chk.validate(tree.recvparam, newEnv);
|
||||
if (!(tree.recvparam.type == m.owner.type || types.isSameType(tree.recvparam.type, m.owner.type))) {
|
||||
// The == covers the common non-generic case, but for generic classes we need isSameType;
|
||||
// note that equals didn't work.
|
||||
log.error(tree.recvparam.pos(), "incorrect.receiver.type");
|
||||
}
|
||||
}
|
||||
|
||||
// annotation method checks
|
||||
@ -1112,6 +1112,18 @@ public class Attr extends JCTree.Visitor {
|
||||
memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner);
|
||||
annotate.flush();
|
||||
|
||||
{
|
||||
// Store init and clinit type annotations with the ClassSymbol
|
||||
// to allow output in Gen.normalizeDefs.
|
||||
ClassSymbol cs = (ClassSymbol)env.info.scope.owner;
|
||||
List<Attribute.TypeCompound> tas = localEnv.info.scope.owner.getRawTypeAttributes();
|
||||
if ((tree.flags & STATIC) != 0) {
|
||||
cs.annotations.appendClassInitTypeAttributes(tas);
|
||||
} else {
|
||||
cs.annotations.appendInitTypeAttributes(tas);
|
||||
}
|
||||
}
|
||||
|
||||
attribStats(tree.stats, localEnv);
|
||||
} else {
|
||||
// Create a new local environment with a local scope.
|
||||
@ -2131,6 +2143,11 @@ public class Attr extends JCTree.Visitor {
|
||||
tree.constructor,
|
||||
localEnv,
|
||||
new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes)));
|
||||
} else {
|
||||
if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
|
||||
checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations,
|
||||
tree.clazz.type.tsym);
|
||||
}
|
||||
}
|
||||
|
||||
if (tree.constructor != null && tree.constructor.kind == MTH)
|
||||
@ -2195,6 +2212,20 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForDeclarationAnnotations(List<? extends JCAnnotation> annotations,
|
||||
Symbol sym) {
|
||||
// Ensure that no declaration annotations are present.
|
||||
// Note that a tree type might be an AnnotatedType with
|
||||
// empty annotations, if only declaration annotations were given.
|
||||
// This method will raise an error for such a type.
|
||||
for (JCAnnotation ai : annotations) {
|
||||
if (TypeAnnotations.annotationType(syms, names, ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) {
|
||||
log.error(ai.pos(), "annotation.type.not.applicable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Make an attributed null check tree.
|
||||
*/
|
||||
public JCExpression makeNullCheck(JCExpression arg) {
|
||||
@ -2221,6 +2252,10 @@ public class Attr extends JCTree.Visitor {
|
||||
attribExpr(l.head, localEnv, syms.intType);
|
||||
owntype = new ArrayType(owntype, syms.arrayClass);
|
||||
}
|
||||
if (tree.elemtype.hasTag(ANNOTATED_TYPE)) {
|
||||
checkForDeclarationAnnotations(((JCAnnotatedType) tree.elemtype).annotations,
|
||||
tree.elemtype.type.tsym);
|
||||
}
|
||||
} else {
|
||||
// we are seeing an untyped aggregate { ... }
|
||||
// this is allowed only if the prototype is an array
|
||||
@ -3763,6 +3798,12 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
owntype = new ClassType(clazzOuter, actuals, clazztype.tsym);
|
||||
if (clazztype.isAnnotated()) {
|
||||
// Use the same AnnotatedType, because it will have
|
||||
// its annotations set later.
|
||||
((AnnotatedType)clazztype).underlyingType = owntype;
|
||||
owntype = clazztype;
|
||||
}
|
||||
} else {
|
||||
if (formals.length() != 0) {
|
||||
log.error(tree.pos(), "wrong.number.type.args",
|
||||
@ -3961,7 +4002,14 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
ListBuffer<Attribute.TypeCompound> buf = ListBuffer.lb();
|
||||
for (JCAnnotation anno : annotations) {
|
||||
buf.append((Attribute.TypeCompound) anno.attribute);
|
||||
if (anno.attribute != null) {
|
||||
// TODO: this null-check is only needed for an obscure
|
||||
// ordering issue, where annotate.flush is called when
|
||||
// the attribute is not set yet. For an example failure
|
||||
// try the referenceinfos/NestedTypes.java test.
|
||||
// Any better solutions?
|
||||
buf.append((Attribute.TypeCompound) anno.attribute);
|
||||
}
|
||||
}
|
||||
return buf.toList();
|
||||
}
|
||||
@ -4266,15 +4314,12 @@ public class Attr extends JCTree.Visitor {
|
||||
tree.accept(typeAnnotationsValidator);
|
||||
}
|
||||
//where
|
||||
private final JCTree.Visitor typeAnnotationsValidator =
|
||||
new TreeScanner() {
|
||||
private final JCTree.Visitor typeAnnotationsValidator = new TreeScanner() {
|
||||
|
||||
private boolean checkAllAnnotations = false;
|
||||
|
||||
public void visitAnnotation(JCAnnotation tree) {
|
||||
if (tree.hasTag(TYPE_ANNOTATION)) {
|
||||
// TODO: It seems to WMD as if the annotation in
|
||||
// parameters, in particular also the recvparam, are never
|
||||
// of type JCTypeAnnotation and therefore never checked!
|
||||
// Luckily this check doesn't really do anything that isn't
|
||||
// also done elsewhere.
|
||||
if (tree.hasTag(TYPE_ANNOTATION) || checkAllAnnotations) {
|
||||
chk.validateTypeAnnotation(tree, false);
|
||||
}
|
||||
super.visitAnnotation(tree);
|
||||
@ -4288,15 +4333,10 @@ public class Attr extends JCTree.Visitor {
|
||||
// super.visitTypeParameter(tree);
|
||||
}
|
||||
public void visitMethodDef(JCMethodDecl tree) {
|
||||
// Static methods cannot have receiver type annotations.
|
||||
// In test case FailOver15.java, the nested method getString has
|
||||
// a null sym, because an unknown class is instantiated.
|
||||
// I would say it's safe to skip.
|
||||
if (tree.sym != null && (tree.sym.flags() & Flags.STATIC) != 0) {
|
||||
if (tree.recvparam != null) {
|
||||
// TODO: better error message. Is the pos good?
|
||||
log.error(tree.recvparam.pos(), "annotation.type.not.applicable");
|
||||
}
|
||||
if (tree.recvparam != null &&
|
||||
tree.recvparam.vartype.type.getKind() != TypeKind.ERROR) {
|
||||
checkForDeclarationAnnotations(tree.recvparam.mods.annotations,
|
||||
tree.recvparam.vartype.type.tsym);
|
||||
}
|
||||
if (tree.restype != null && tree.restype.type != null) {
|
||||
validateAnnotatedType(tree.restype, tree.restype.type);
|
||||
@ -4318,9 +4358,30 @@ public class Attr extends JCTree.Visitor {
|
||||
validateAnnotatedType(tree.clazz, tree.clazz.type);
|
||||
super.visitTypeTest(tree);
|
||||
}
|
||||
// TODO: what else do we need?
|
||||
// public void visitNewClass(JCNewClass tree) {
|
||||
// public void visitNewArray(JCNewArray tree) {
|
||||
public void visitNewClass(JCNewClass tree) {
|
||||
if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
|
||||
boolean prevCheck = this.checkAllAnnotations;
|
||||
try {
|
||||
this.checkAllAnnotations = true;
|
||||
scan(((JCAnnotatedType)tree.clazz).annotations);
|
||||
} finally {
|
||||
this.checkAllAnnotations = prevCheck;
|
||||
}
|
||||
}
|
||||
super.visitNewClass(tree);
|
||||
}
|
||||
public void visitNewArray(JCNewArray tree) {
|
||||
if (tree.elemtype != null && tree.elemtype.hasTag(ANNOTATED_TYPE)) {
|
||||
boolean prevCheck = this.checkAllAnnotations;
|
||||
try {
|
||||
this.checkAllAnnotations = true;
|
||||
scan(((JCAnnotatedType)tree.elemtype).annotations);
|
||||
} finally {
|
||||
this.checkAllAnnotations = prevCheck;
|
||||
}
|
||||
}
|
||||
super.visitNewArray(tree);
|
||||
}
|
||||
|
||||
/* I would want to model this after
|
||||
* com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess)
|
||||
|
@ -1213,7 +1213,7 @@ public class Check {
|
||||
|
||||
/** Validate a type expression. That is,
|
||||
* check that all type arguments of a parametric type are within
|
||||
* their bounds. This must be done in a second phase after type attributon
|
||||
* their bounds. This must be done in a second phase after type attribution
|
||||
* since a class might have a subclass as type parameter bound. E.g:
|
||||
*
|
||||
* <pre>{@code
|
||||
|
@ -25,12 +25,12 @@
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
import com.sun.tools.javac.tree.TreeScanner;
|
||||
import com.sun.tools.javac.tree.TreeTranslator;
|
||||
import com.sun.tools.javac.code.Attribute;
|
||||
import com.sun.tools.javac.code.Kinds;
|
||||
import com.sun.tools.javac.code.Scope;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
@ -46,7 +46,6 @@ import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
|
||||
import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
|
||||
import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
|
||||
|
||||
@ -238,6 +237,24 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
MethodSymbol sym = (MethodSymbol)localContext.translatedSym;
|
||||
MethodType lambdaType = (MethodType) sym.type;
|
||||
|
||||
{
|
||||
MethodSymbol owner = (MethodSymbol) localContext.owner;
|
||||
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
|
||||
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
|
||||
|
||||
for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
|
||||
if (tc.position.onLambda == tree) {
|
||||
lambdaTypeAnnos.append(tc);
|
||||
} else {
|
||||
ownerTypeAnnos.append(tc);
|
||||
}
|
||||
}
|
||||
if (lambdaTypeAnnos.nonEmpty()) {
|
||||
owner.annotations.setTypeAttributes(ownerTypeAnnos.toList());
|
||||
sym.annotations.setTypeAttributes(lambdaTypeAnnos.toList());
|
||||
}
|
||||
}
|
||||
|
||||
//create the method declaration hoisting the lambda body
|
||||
JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
|
||||
sym.name,
|
||||
@ -373,12 +390,15 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) {
|
||||
Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym);
|
||||
result = make.Ident(translatedSym).setType(tree.type);
|
||||
translatedSym.annotations.setTypeAttributes(tree.sym.getRawTypeAttributes());
|
||||
} else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
|
||||
Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
|
||||
result = make.Ident(translatedSym).setType(tree.type);
|
||||
translatedSym.annotations.setTypeAttributes(tree.sym.getRawTypeAttributes());
|
||||
} else if (lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
|
||||
Symbol translatedSym = lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
|
||||
result = make.Ident(translatedSym).setType(translatedSym.type);
|
||||
translatedSym.annotations.setTypeAttributes(tree.sym.getRawTypeAttributes());
|
||||
} else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) {
|
||||
Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
|
||||
result = make.Ident(translatedSym).setType(tree.type);
|
||||
@ -1676,24 +1696,33 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
* synthetic lambda body
|
||||
*/
|
||||
Symbol translate(Name name, final Symbol sym, LambdaSymbolKind skind) {
|
||||
Symbol ret;
|
||||
switch (skind) {
|
||||
case CAPTURED_THIS:
|
||||
return sym; // self represented
|
||||
ret = sym; // self represented
|
||||
break;
|
||||
case TYPE_VAR:
|
||||
// Just erase the type var
|
||||
return new VarSymbol(sym.flags(), name,
|
||||
ret = new VarSymbol(sym.flags(), name,
|
||||
types.erasure(sym.type), sym.owner);
|
||||
break;
|
||||
case CAPTURED_VAR:
|
||||
return new VarSymbol(SYNTHETIC | FINAL, name, types.erasure(sym.type), translatedSym) {
|
||||
ret = new VarSymbol(SYNTHETIC | FINAL, name, types.erasure(sym.type), translatedSym) {
|
||||
@Override
|
||||
public Symbol baseSymbol() {
|
||||
//keep mapping with original captured symbol
|
||||
return sym;
|
||||
}
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
|
||||
ret = makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
|
||||
}
|
||||
if (ret != sym) {
|
||||
ret.annotations.setDeclarationAttributes(sym.getRawAttributes());
|
||||
ret.annotations.setTypeAttributes(sym.getRawTypeAttributes());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void addSymbol(Symbol sym, LambdaSymbolKind skind) {
|
||||
|
@ -28,6 +28,7 @@ package com.sun.tools.javac.comp;
|
||||
import java.util.*;
|
||||
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Type.AnnotatedType;
|
||||
import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.main.Option.PkgInfo;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
@ -2767,10 +2768,28 @@ public class Lower extends TreeTranslator {
|
||||
}
|
||||
|
||||
public void visitAnnotatedType(JCAnnotatedType tree) {
|
||||
// No need to retain type annotations any longer.
|
||||
// No need to retain type annotations in the tree
|
||||
// tree.annotations = translate(tree.annotations);
|
||||
tree.annotations = List.nil();
|
||||
tree.underlyingType = translate(tree.underlyingType);
|
||||
result = tree.underlyingType;
|
||||
// but maintain type annotations in the type.
|
||||
if (tree.type.isAnnotated()) {
|
||||
if (tree.underlyingType.type.isAnnotated()) {
|
||||
// The erasure of a type variable might be annotated.
|
||||
// Merge all annotations.
|
||||
AnnotatedType newat = (AnnotatedType) tree.underlyingType.type;
|
||||
AnnotatedType at = (AnnotatedType) tree.type;
|
||||
at.underlyingType = newat.underlyingType;
|
||||
newat.typeAnnotations = at.typeAnnotations.appendList(newat.typeAnnotations);
|
||||
tree.type = newat;
|
||||
} else {
|
||||
// Create a new AnnotatedType to have the correct tag.
|
||||
AnnotatedType oldat = (AnnotatedType) tree.type;
|
||||
tree.type = new AnnotatedType(tree.underlyingType.type);
|
||||
((AnnotatedType) tree.type).typeAnnotations = oldat.typeAnnotations;
|
||||
}
|
||||
}
|
||||
result = tree;
|
||||
}
|
||||
|
||||
public void visitTypeCast(JCTypeCast tree) {
|
||||
|
@ -31,7 +31,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.code.*;
|
||||
@ -617,7 +616,26 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
if (TreeInfo.isEnumInit(tree)) {
|
||||
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
||||
} else {
|
||||
// Make sure type annotations are processed.
|
||||
// But we don't have a symbol to attach them to yet - use null.
|
||||
typeAnnotate(tree.vartype, env, null);
|
||||
attr.attribType(tree.vartype, localEnv);
|
||||
if (tree.nameexpr != null) {
|
||||
attr.attribExpr(tree.nameexpr, localEnv);
|
||||
MethodSymbol m = localEnv.enclMethod.sym;
|
||||
if (m.isConstructor()) {
|
||||
Type outertype = m.owner.owner.type;
|
||||
if (outertype.hasTag(TypeTag.CLASS)) {
|
||||
checkType(tree.vartype, outertype, "incorrect.constructor.receiver.type");
|
||||
checkType(tree.nameexpr, outertype, "incorrect.constructor.receiver.name");
|
||||
} else {
|
||||
log.error(tree, "receiver.parameter.not.applicable.constructor.toplevel.class");
|
||||
}
|
||||
} else {
|
||||
checkType(tree.vartype, m.owner.type, "incorrect.receiver.type");
|
||||
checkType(tree.nameexpr, m.owner.type, "incorrect.receiver.name");
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
chk.setDeferredLintHandler(prevLintHandler);
|
||||
@ -651,10 +669,16 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
enclScope.enter(v);
|
||||
}
|
||||
annotateLater(tree.mods.annotations, localEnv, v);
|
||||
typeAnnotate(tree.vartype, env, tree.sym);
|
||||
typeAnnotate(tree.vartype, env, v);
|
||||
annotate.flush();
|
||||
v.pos = tree.pos;
|
||||
}
|
||||
// where
|
||||
void checkType(JCTree tree, Type type, String diag) {
|
||||
if (!tree.type.isErroneous() && !types.isSameType(tree.type, type)) {
|
||||
log.error(tree, diag, type, tree.type);
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a fresh environment for a variable's initializer.
|
||||
* If the variable is a field, the owner of the environment's scope
|
||||
@ -1040,9 +1064,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
isFirst = true;
|
||||
}
|
||||
}
|
||||
annotate.afterRepeated(TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree));
|
||||
TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree, annotate);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the symbol is non-null, attach the type annotation to it.
|
||||
*/
|
||||
private void actualEnterTypeAnnotations(final List<JCAnnotation> annotations,
|
||||
final Env<AttrContext> env,
|
||||
final Symbol s) {
|
||||
@ -1075,8 +1102,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
}
|
||||
}
|
||||
|
||||
s.annotations.appendTypeAttributesWithCompletion(
|
||||
annotate.new AnnotateRepeatedContext<Attribute.TypeCompound>(env, annotated, pos, log, true));
|
||||
if (s != null) {
|
||||
s.annotations.appendTypeAttributesWithCompletion(
|
||||
annotate.new AnnotateRepeatedContext<Attribute.TypeCompound>(env, annotated, pos, log, true));
|
||||
}
|
||||
}
|
||||
|
||||
public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym) {
|
||||
@ -1150,6 +1179,33 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
// Do not annotate the body, just the signature.
|
||||
// scan(tree.body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVarDef(final JCVariableDecl tree) {
|
||||
if (sym != null && sym.kind == Kinds.VAR) {
|
||||
// Don't visit a parameter once when the sym is the method
|
||||
// and once when the sym is the parameter.
|
||||
scan(tree.mods);
|
||||
scan(tree.vartype);
|
||||
}
|
||||
scan(tree.init);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
// We can only hit a classdef if it is declared within
|
||||
// a method. Ignore it - the class will be visited
|
||||
// separately later.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewClass(JCNewClass tree) {
|
||||
if (tree.def == null) {
|
||||
// For an anonymous class instantiation the class
|
||||
// will be visited separately.
|
||||
super.visitNewClass(tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1518,7 +1518,7 @@ public class ClassReader implements Completer {
|
||||
break;
|
||||
// exception parameter
|
||||
case EXCEPTION_PARAMETER:
|
||||
position.exception_index = nextByte();
|
||||
position.exception_index = nextChar();
|
||||
break;
|
||||
// method receiver
|
||||
case METHOD_RECEIVER:
|
||||
|
@ -632,7 +632,7 @@ public class ClassWriter extends ClassFile {
|
||||
acount++;
|
||||
}
|
||||
acount += writeJavaAnnotations(sym.getRawAttributes());
|
||||
acount += writeTypeAnnotations(sym.getRawTypeAttributes());
|
||||
acount += writeTypeAnnotations(sym.getRawTypeAttributes(), false);
|
||||
return acount;
|
||||
}
|
||||
|
||||
@ -759,44 +759,30 @@ public class ClassWriter extends ClassFile {
|
||||
return attrCount;
|
||||
}
|
||||
|
||||
int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos) {
|
||||
int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos, boolean inCode) {
|
||||
if (typeAnnos.isEmpty()) return 0;
|
||||
|
||||
ListBuffer<Attribute.TypeCompound> visibles = ListBuffer.lb();
|
||||
ListBuffer<Attribute.TypeCompound> invisibles = ListBuffer.lb();
|
||||
|
||||
for (Attribute.TypeCompound tc : typeAnnos) {
|
||||
if (tc.position == null || tc.position.type == TargetType.UNKNOWN) {
|
||||
boolean found = false;
|
||||
// TODO: the position for the container annotation of a
|
||||
// repeating type annotation has to be set.
|
||||
// This cannot be done when the container is created, because
|
||||
// then the position is not determined yet.
|
||||
// How can we link these pieces better together?
|
||||
if (tc.values.size() == 1) {
|
||||
Pair<MethodSymbol, Attribute> val = tc.values.get(0);
|
||||
if (val.fst.getSimpleName().contentEquals("value") &&
|
||||
val.snd instanceof Attribute.Array) {
|
||||
Attribute.Array arr = (Attribute.Array) val.snd;
|
||||
if (arr.values.length != 0 &&
|
||||
arr.values[0] instanceof Attribute.TypeCompound) {
|
||||
TypeCompound atycomp = (Attribute.TypeCompound) arr.values[0];
|
||||
if (atycomp.position.type != TargetType.UNKNOWN) {
|
||||
tc.position = atycomp.position;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (tc.hasUnknownPosition()) {
|
||||
boolean fixed = tc.tryFixPosition();
|
||||
|
||||
// Could we fix it?
|
||||
if (!fixed) {
|
||||
// This happens for nested types like @A Outer. @B Inner.
|
||||
// For method parameters we get the annotation twice! Once with
|
||||
// a valid position, once unknown.
|
||||
// TODO: find a cleaner solution.
|
||||
// System.err.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
|
||||
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
|
||||
pw.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (tc.position.type.isLocal() != inCode)
|
||||
continue;
|
||||
if (!tc.position.emitToClassfile())
|
||||
continue;
|
||||
switch (types.getRetention(tc)) {
|
||||
@ -936,7 +922,7 @@ public class ClassWriter extends ClassFile {
|
||||
break;
|
||||
// exception parameter
|
||||
case EXCEPTION_PARAMETER:
|
||||
databuf.appendByte(p.exception_index);
|
||||
databuf.appendChar(p.exception_index);
|
||||
break;
|
||||
// method receiver
|
||||
case METHOD_RECEIVER:
|
||||
@ -1241,6 +1227,9 @@ public class ClassWriter extends ClassFile {
|
||||
endAttr(alenIdx);
|
||||
acount++;
|
||||
}
|
||||
|
||||
acount += writeTypeAnnotations(code.meth.getRawTypeAttributes(), true);
|
||||
|
||||
endAttrs(acountIdx, acount);
|
||||
}
|
||||
//where
|
||||
@ -1627,7 +1616,7 @@ public class ClassWriter extends ClassFile {
|
||||
out = null;
|
||||
} finally {
|
||||
if (out != null) {
|
||||
// if we are propogating an exception, delete the file
|
||||
// if we are propagating an exception, delete the file
|
||||
out.close();
|
||||
outFile.delete();
|
||||
outFile = null;
|
||||
@ -1741,7 +1730,7 @@ public class ClassWriter extends ClassFile {
|
||||
|
||||
acount += writeFlagAttrs(c.flags());
|
||||
acount += writeJavaAnnotations(c.getRawAttributes());
|
||||
acount += writeTypeAnnotations(c.getRawTypeAttributes());
|
||||
acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
|
||||
acount += writeEnclosingMethodAttribute(c);
|
||||
acount += writeExtraClassAttributes(c);
|
||||
|
||||
|
@ -1010,7 +1010,16 @@ public class Code {
|
||||
state.pop(((Symbol)(pool.pool[od])).erasure(types));
|
||||
break;
|
||||
case new_:
|
||||
state.push(uninitializedObject(((Symbol)(pool.pool[od])).erasure(types), cp-3));
|
||||
Symbol sym;
|
||||
if (pool.pool[od] instanceof UniqueType) {
|
||||
// Required by change in Gen.makeRef to allow
|
||||
// annotated types.
|
||||
// TODO: is this needed anywhere else?
|
||||
sym = ((UniqueType)(pool.pool[od])).type.tsym;
|
||||
} else {
|
||||
sym = (Symbol)(pool.pool[od]);
|
||||
}
|
||||
state.push(uninitializedObject(sym.erasure(types), cp-3));
|
||||
break;
|
||||
case sipush:
|
||||
state.push(syms.intType);
|
||||
@ -1972,25 +1981,38 @@ public class Code {
|
||||
if (lv == null || lv.sym == null
|
||||
|| lv.sym.annotations.isTypesEmpty()
|
||||
|| !lv.sym.isExceptionParameter())
|
||||
return;
|
||||
|
||||
int exidx = findExceptionIndex(lv);
|
||||
continue;
|
||||
|
||||
for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
|
||||
TypeAnnotationPosition p = ta.position;
|
||||
p.exception_index = exidx;
|
||||
// At this point p.type_index contains the catch type index.
|
||||
// Use that index to determine the exception table index.
|
||||
// We can afterwards discard the type_index.
|
||||
// A TA position is shared for all type annotations in the
|
||||
// same location; updating one is enough.
|
||||
// Use -666 as a marker that the exception_index was already updated.
|
||||
if (p.type_index != -666) {
|
||||
p.exception_index = findExceptionIndex(p.type_index);
|
||||
p.type_index = -666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int findExceptionIndex(LocalVar lv) {
|
||||
private int findExceptionIndex(int catchType) {
|
||||
if (catchType == Integer.MIN_VALUE) {
|
||||
// We didn't set the catch type index correctly.
|
||||
// This shouldn't happen.
|
||||
// TODO: issue error?
|
||||
return -1;
|
||||
}
|
||||
List<char[]> iter = catchInfo.toList();
|
||||
int len = catchInfo.length();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
char[] catchEntry = iter.head;
|
||||
iter = iter.tail;
|
||||
char handlerpc = catchEntry[2];
|
||||
if (lv.start_pc == handlerpc + 1) {
|
||||
char ct = catchEntry[3];
|
||||
if (catchType == ct) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Attribute.TypeCompound;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.comp.*;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
|
||||
@ -47,7 +49,6 @@ import static com.sun.tools.javac.jvm.ByteCodes.*;
|
||||
import static com.sun.tools.javac.jvm.CRTFlags.*;
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK;
|
||||
|
||||
/** This pass maps flat Java (i.e. without inner classes) to bytecodes.
|
||||
*
|
||||
@ -308,7 +309,15 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
int makeRef(DiagnosticPosition pos, Type type) {
|
||||
checkDimension(pos, type);
|
||||
return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
|
||||
if (type.isAnnotated()) {
|
||||
// Treat annotated types separately - we don't want
|
||||
// to collapse all of them - at least for annotated
|
||||
// exceptions.
|
||||
// TODO: review this.
|
||||
return pool.put((Object)type);
|
||||
} else {
|
||||
return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if the given type is an array with too many dimensions.
|
||||
@ -456,7 +465,9 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
|
||||
ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();
|
||||
ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();
|
||||
ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();
|
||||
// Sort definitions into three listbuffers:
|
||||
// - initCode for instance initializers
|
||||
@ -486,6 +497,7 @@ public class Gen extends JCTree.Visitor {
|
||||
Assignment(sym, vdef.init);
|
||||
initCode.append(init);
|
||||
endPosTable.replaceTree(vdef, init);
|
||||
initTAs.addAll(getAndRemoveNonFieldTAs(sym));
|
||||
} else if (sym.getConstValue() == null) {
|
||||
// Initialize class (static) variables only if
|
||||
// they are not compile-time constants.
|
||||
@ -493,6 +505,7 @@ public class Gen extends JCTree.Visitor {
|
||||
Assignment(sym, vdef.init);
|
||||
clinitCode.append(init);
|
||||
endPosTable.replaceTree(vdef, init);
|
||||
clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
|
||||
} else {
|
||||
checkStringConstant(vdef.init.pos(), sym.getConstValue());
|
||||
}
|
||||
@ -505,8 +518,10 @@ public class Gen extends JCTree.Visitor {
|
||||
// Insert any instance initializers into all constructors.
|
||||
if (initCode.length() != 0) {
|
||||
List<JCStatement> inits = initCode.toList();
|
||||
initTAs.addAll(c.annotations.getInitTypeAttributes());
|
||||
List<Attribute.TypeCompound> initTAlist = initTAs.toList();
|
||||
for (JCTree t : methodDefs) {
|
||||
normalizeMethod((JCMethodDecl)t, inits);
|
||||
normalizeMethod((JCMethodDecl)t, inits, initTAlist);
|
||||
}
|
||||
}
|
||||
// If there are class initializers, create a <clinit> method
|
||||
@ -524,11 +539,31 @@ public class Gen extends JCTree.Visitor {
|
||||
JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
|
||||
block.endpos = TreeInfo.endPos(clinitStats.last());
|
||||
methodDefs.append(make.MethodDef(clinit, block));
|
||||
|
||||
if (!clinitTAs.isEmpty())
|
||||
clinit.annotations.appendUniqueTypes(clinitTAs.toList());
|
||||
if (!c.annotations.getClassInitTypeAttributes().isEmpty())
|
||||
clinit.annotations.appendUniqueTypes(c.annotations.getClassInitTypeAttributes());
|
||||
}
|
||||
// Return all method definitions.
|
||||
return methodDefs.toList();
|
||||
}
|
||||
|
||||
private List<Attribute.TypeCompound> getAndRemoveNonFieldTAs(VarSymbol sym) {
|
||||
List<TypeCompound> tas = sym.getRawTypeAttributes();
|
||||
ListBuffer<Attribute.TypeCompound> fieldTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
ListBuffer<Attribute.TypeCompound> nonfieldTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
for (TypeCompound ta : tas) {
|
||||
if (ta.position.type == TargetType.FIELD) {
|
||||
fieldTAs.add(ta);
|
||||
} else {
|
||||
nonfieldTAs.add(ta);
|
||||
}
|
||||
}
|
||||
sym.annotations.setTypeAttributes(fieldTAs.toList());
|
||||
return nonfieldTAs.toList();
|
||||
}
|
||||
|
||||
/** Check a constant value and report if it is a string that is
|
||||
* too large.
|
||||
*/
|
||||
@ -546,8 +581,9 @@ public class Gen extends JCTree.Visitor {
|
||||
* @param md The tree potentially representing a
|
||||
* constructor's definition.
|
||||
* @param initCode The list of instance initializer statements.
|
||||
* @param initTAs Type annotations from the initializer expression.
|
||||
*/
|
||||
void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode) {
|
||||
void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
|
||||
if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
|
||||
// We are seeing a constructor that does not call another
|
||||
// constructor of the same class.
|
||||
@ -581,6 +617,8 @@ public class Gen extends JCTree.Visitor {
|
||||
md.body.stats = newstats.toList();
|
||||
if (md.body.endpos == Position.NOPOS)
|
||||
md.body.endpos = TreeInfo.endPos(md.body.stats.last());
|
||||
|
||||
md.sym.annotations.appendUniqueTypes(initTAs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1527,6 +1565,11 @@ public class Gen extends JCTree.Visitor {
|
||||
registerCatch(tree.pos(),
|
||||
startpc, end, code.curPc(),
|
||||
catchType);
|
||||
if (subCatch.type.isAnnotated()) {
|
||||
// All compounds share the same position, simply update the
|
||||
// first one.
|
||||
subCatch.type.getAnnotationMirrors().head.position.type_index = catchType;
|
||||
}
|
||||
}
|
||||
gaps = gaps.tail;
|
||||
startpc = gaps.head.intValue();
|
||||
@ -1538,6 +1581,11 @@ public class Gen extends JCTree.Visitor {
|
||||
registerCatch(tree.pos(),
|
||||
startpc, endpc, code.curPc(),
|
||||
catchType);
|
||||
if (subCatch.type.isAnnotated()) {
|
||||
// All compounds share the same position, simply update the
|
||||
// first one.
|
||||
subCatch.type.getAnnotationMirrors().head.position.type_index = catchType;
|
||||
}
|
||||
}
|
||||
}
|
||||
VarSymbol exparam = tree.param.sym;
|
||||
@ -1783,42 +1831,44 @@ public class Gen extends JCTree.Visitor {
|
||||
result = items.makeStackItem(pt);
|
||||
}
|
||||
|
||||
private void setTypeAnnotationPositions(int treePos) {
|
||||
MethodSymbol meth = code.meth;
|
||||
private void setTypeAnnotationPositions(int treePos) {
|
||||
MethodSymbol meth = code.meth;
|
||||
boolean initOrClinit = code.meth.getKind() == javax.lang.model.element.ElementKind.CONSTRUCTOR
|
||||
|| code.meth.getKind() == javax.lang.model.element.ElementKind.STATIC_INIT;
|
||||
|
||||
for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
|
||||
if (ta.position.pos == treePos) {
|
||||
ta.position.offset = code.cp;
|
||||
ta.position.lvarOffset = new int[] { code.cp };
|
||||
ta.position.isValidOffset = true;
|
||||
}
|
||||
}
|
||||
for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
|
||||
if (ta.hasUnknownPosition())
|
||||
ta.tryFixPosition();
|
||||
|
||||
if (code.meth.getKind() != javax.lang.model.element.ElementKind.CONSTRUCTOR
|
||||
&& code.meth.getKind() != javax.lang.model.element.ElementKind.STATIC_INIT)
|
||||
return;
|
||||
if (ta.position.matchesPos(treePos))
|
||||
ta.position.updatePosOffset(code.cp);
|
||||
}
|
||||
|
||||
for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
|
||||
if (ta.position.pos == treePos) {
|
||||
ta.position.offset = code.cp;
|
||||
ta.position.lvarOffset = new int[] { code.cp };
|
||||
ta.position.isValidOffset = true;
|
||||
}
|
||||
}
|
||||
if (!initOrClinit)
|
||||
return;
|
||||
|
||||
ClassSymbol clazz = meth.enclClass();
|
||||
for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
|
||||
if (!s.getKind().isField())
|
||||
continue;
|
||||
for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
|
||||
if (ta.position.pos == treePos) {
|
||||
ta.position.offset = code.cp;
|
||||
ta.position.lvarOffset = new int[] { code.cp };
|
||||
ta.position.isValidOffset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
|
||||
if (ta.hasUnknownPosition())
|
||||
ta.tryFixPosition();
|
||||
|
||||
if (ta.position.matchesPos(treePos))
|
||||
ta.position.updatePosOffset(code.cp);
|
||||
}
|
||||
|
||||
ClassSymbol clazz = meth.enclClass();
|
||||
for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
|
||||
if (!s.getKind().isField())
|
||||
continue;
|
||||
|
||||
for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
|
||||
if (ta.hasUnknownPosition())
|
||||
ta.tryFixPosition();
|
||||
|
||||
if (ta.position.matchesPos(treePos))
|
||||
ta.position.updatePosOffset(code.cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitNewClass(JCNewClass tree) {
|
||||
// Enclosing instances or anonymous classes should have been eliminated
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package com.sun.tools.javac.main;
|
||||
|
||||
import com.sun.tools.javac.comp.CompileStates;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -55,6 +54,7 @@ import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.comp.*;
|
||||
import com.sun.tools.javac.comp.CompileStates.CompileState;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.parser.*;
|
||||
@ -62,7 +62,6 @@ import com.sun.tools.javac.processing.*;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.comp.CompileStates.CompileState;
|
||||
import com.sun.tools.javac.util.Log.WriterKind;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
||||
@ -484,7 +483,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||
*/
|
||||
protected boolean werror;
|
||||
|
||||
/** Switch: is annotation processing requested explitly via
|
||||
/** Switch: is annotation processing requested explicitly via
|
||||
* CompilationTask.setProcessors?
|
||||
*/
|
||||
protected boolean explicitAnnotationProcessingRequested = false;
|
||||
|
@ -2013,7 +2013,7 @@ public class JavacParser implements Parser {
|
||||
/** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
|
||||
*/
|
||||
JCExpression creator(int newpos, List<JCExpression> typeArgs) {
|
||||
List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
|
||||
List<JCAnnotation> newAnnotations = annotationsOpt(Tag.ANNOTATION);
|
||||
|
||||
switch (token.kind) {
|
||||
case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
|
||||
@ -2030,11 +2030,6 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
JCExpression t = qualident(true);
|
||||
|
||||
// handle type annotations for non primitive arrays
|
||||
if (newAnnotations.nonEmpty()) {
|
||||
t = insertAnnotationsToMostInner(t, newAnnotations, false);
|
||||
}
|
||||
|
||||
int oldmode = mode;
|
||||
mode = TYPE;
|
||||
boolean diamondFound = false;
|
||||
@ -2068,6 +2063,11 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
mode = oldmode;
|
||||
if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
|
||||
// handle type annotations for non primitive arrays
|
||||
if (newAnnotations.nonEmpty()) {
|
||||
t = insertAnnotationsToMostInner(t, newAnnotations, false);
|
||||
}
|
||||
|
||||
JCExpression e = arrayCreatorRest(newpos, t);
|
||||
if (diamondFound) {
|
||||
reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
|
||||
@ -2092,8 +2092,18 @@ public class JavacParser implements Parser {
|
||||
if (newClass.def != null) {
|
||||
assert newClass.def.mods.annotations.isEmpty();
|
||||
if (newAnnotations.nonEmpty()) {
|
||||
// Add type and declaration annotations to the new class;
|
||||
// com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitNewClass(JCNewClass)
|
||||
// will later remove all type annotations and only leave the
|
||||
// declaration annotations.
|
||||
newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
|
||||
newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
|
||||
newClass.def.mods.annotations = newAnnotations;
|
||||
}
|
||||
} else {
|
||||
// handle type annotations for instantiations
|
||||
if (newAnnotations.nonEmpty()) {
|
||||
t = insertAnnotationsToMostInner(t, newAnnotations, false);
|
||||
newClass.clazz = t;
|
||||
}
|
||||
}
|
||||
return newClass;
|
||||
@ -2987,7 +2997,22 @@ public class JavacParser implements Parser {
|
||||
syntaxError(pos, "expected", IDENTIFIER);
|
||||
name = token.name();
|
||||
} else {
|
||||
name = ident();
|
||||
if (allowThisIdent) {
|
||||
JCExpression pn = qualident(false);
|
||||
if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
|
||||
name = ((JCIdent)pn).name;
|
||||
} else {
|
||||
if ((mods.flags & Flags.VARARGS) != 0) {
|
||||
log.error(token.pos, "varargs.and.receiver");
|
||||
}
|
||||
if (token.kind == LBRACKET) {
|
||||
log.error(token.pos, "array.and.receiver");
|
||||
}
|
||||
return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
|
||||
}
|
||||
} else {
|
||||
name = ident();
|
||||
}
|
||||
}
|
||||
if ((mods.flags & Flags.VARARGS) != 0 &&
|
||||
token.kind == LBRACKET) {
|
||||
@ -3526,18 +3551,24 @@ public class JavacParser implements Parser {
|
||||
ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
|
||||
|
||||
List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
|
||||
if (!typeAnnos.isEmpty())
|
||||
ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true))));
|
||||
else
|
||||
ts.append(qualident(true));
|
||||
JCExpression qi = qualident(true);
|
||||
if (!typeAnnos.isEmpty()) {
|
||||
JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
|
||||
ts.append(at);
|
||||
} else {
|
||||
ts.append(qi);
|
||||
}
|
||||
while (token.kind == COMMA) {
|
||||
nextToken();
|
||||
|
||||
typeAnnos = typeAnnotationsOpt();
|
||||
if (!typeAnnos.isEmpty())
|
||||
ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true))));
|
||||
else
|
||||
ts.append(qualident(true));
|
||||
qi = qualident(true);
|
||||
if (!typeAnnos.isEmpty()) {
|
||||
JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
|
||||
ts.append(at);
|
||||
} else {
|
||||
ts.append(qi);
|
||||
}
|
||||
}
|
||||
return ts.toList();
|
||||
}
|
||||
@ -3601,7 +3632,7 @@ public class JavacParser implements Parser {
|
||||
if (token.kind != RPAREN) {
|
||||
this.allowThisIdent = true;
|
||||
lastParam = formalParameter(lambdaParameters);
|
||||
if (lastParam.name.contentEquals(TokenKind.THIS.name)) {
|
||||
if (lastParam.nameexpr != null) {
|
||||
this.receiverParam = lastParam;
|
||||
} else {
|
||||
params.append(lastParam);
|
||||
|
@ -221,7 +221,7 @@ compiler.misc.bad.intersection.target.for.functional.expr=\
|
||||
bad intersection type target for lambda or method reference\n\
|
||||
{0}
|
||||
|
||||
# 0: type
|
||||
# 0: symbol or type
|
||||
compiler.misc.not.an.intf.component=\
|
||||
component type {0} is not an interface
|
||||
|
||||
@ -331,29 +331,29 @@ compiler.err.duplicate.annotation.member.value=\
|
||||
|
||||
# 0: type, 1: type
|
||||
compiler.err.duplicate.annotation.missing.container=\
|
||||
duplicate annotation, the declaration of {0} does not have a valid {1} annotation
|
||||
duplicate annotation: the declaration of {0} does not have a valid {1} annotation
|
||||
|
||||
# 0: type
|
||||
compiler.err.invalid.repeatable.annotation=\
|
||||
duplicate annotation, {0} is annotated with an invalid Repeatable annotation
|
||||
duplicate annotation: {0} is annotated with an invalid Repeatable annotation
|
||||
|
||||
# 0: type
|
||||
# 0: symbol or type
|
||||
compiler.err.invalid.repeatable.annotation.no.value=\
|
||||
duplicate annotation, {0} is not a valid Repeatable, no value element method declared
|
||||
duplicate annotation: {0} is not a valid Repeatable, no value element method declared
|
||||
|
||||
# 0: type, 1: number
|
||||
compiler.err.invalid.repeatable.annotation.multiple.values=\
|
||||
duplicate annotation, {0} is not a valid Repeatable, {1} value element methods declared
|
||||
duplicate annotation: {0} is not a valid Repeatable, {1} value element methods declared
|
||||
|
||||
# 0: type
|
||||
compiler.err.invalid.repeatable.annotation.invalid.value=\
|
||||
duplicate annotation, {0} is not a valid Repeatable, invalid value element, need a method
|
||||
duplicate annotation: {0} is not a valid Repeatable: invalid value element
|
||||
|
||||
# 0: type, 1: type, 2: type
|
||||
# 0: symbol type, 1: type, 2: type
|
||||
compiler.err.invalid.repeatable.annotation.value.return=\
|
||||
duplicate annotation, value element of containing annotation {0} should have type {2}, found {1}
|
||||
duplicate annotation: value element of containing annotation {0} should have type {2}, found {1}
|
||||
|
||||
# 0: type, 1: symbol
|
||||
# 0: symbol or type, 1: symbol
|
||||
compiler.err.invalid.repeatable.annotation.elem.nondefault=\
|
||||
containing annotation {0} does not have a default value for element {1}
|
||||
|
||||
@ -592,6 +592,12 @@ compiler.err.invalid.meth.decl.ret.type.req=\
|
||||
compiler.err.varargs.and.old.array.syntax=\
|
||||
legacy array notation not allowed on variable-arity parameter
|
||||
|
||||
compiler.err.varargs.and.receiver =\
|
||||
varargs notation not allowed on receiver parameter
|
||||
|
||||
compiler.err.array.and.receiver =\
|
||||
legacy array notation not allowed on receiver parameter
|
||||
|
||||
compiler.err.variable.not.allowed=\
|
||||
variable declaration not allowed here
|
||||
|
||||
@ -659,6 +665,7 @@ compiler.err.missing.meth.body.or.decl.abstract=\
|
||||
compiler.err.missing.ret.stmt=\
|
||||
missing return statement
|
||||
|
||||
# 0: unused
|
||||
compiler.misc.missing.ret.val=\
|
||||
missing return value
|
||||
|
||||
@ -983,7 +990,7 @@ compiler.err.illegal.default.super.call=\
|
||||
compiler.misc.overridden.default=\
|
||||
method {0} is overridden in {1}
|
||||
|
||||
# 0: symbol, 1: symbol
|
||||
# 0: symbol, 1: type or symbol
|
||||
compiler.misc.redundant.supertype=\
|
||||
redundant interface {0} is extended by {1}
|
||||
|
||||
@ -1896,11 +1903,10 @@ compiler.misc.varargs.argument.mismatch=\
|
||||
|
||||
#####
|
||||
|
||||
# 0: type, 1: file name
|
||||
# 0: symbol or type, 1: file name
|
||||
compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file=\
|
||||
auxiliary class {0} in {1} should not be accessed from outside its own source file
|
||||
|
||||
|
||||
## The first argument ({0}) is a "kindname".
|
||||
# 0: symbol kind, 1: symbol, 2: symbol
|
||||
compiler.err.abstract.cant.be.accessed.directly=\
|
||||
@ -2185,15 +2191,42 @@ compiler.err.assert.as.identifier=\
|
||||
compiler.err.this.as.identifier=\
|
||||
as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter
|
||||
|
||||
# 0: symbol
|
||||
compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class=\
|
||||
receiver parameter not applicable for constructor of top-level class
|
||||
|
||||
# TODO 308: make a better error message
|
||||
compiler.err.cant.annotate.static.class=\
|
||||
enclosing static nested class cannot be annotated
|
||||
|
||||
# TODO 308: make a better error message
|
||||
# 0: unused
|
||||
compiler.err.cant.annotate.nested.type=\
|
||||
nested type cannot be annotated
|
||||
|
||||
# 0: type, 1: type
|
||||
compiler.err.incorrect.receiver.name=\
|
||||
the receiver name does not match the enclosing class type\n\
|
||||
required: {0}\n\
|
||||
found: {1}
|
||||
|
||||
# 0: type, 1: type
|
||||
compiler.err.incorrect.receiver.type=\
|
||||
the receiver type does not match the enclosing class type
|
||||
the receiver type does not match the enclosing class type\n\
|
||||
required: {0}\n\
|
||||
found: {1}
|
||||
|
||||
# 0: type, 1: type
|
||||
compiler.err.incorrect.constructor.receiver.type=\
|
||||
the receiver type does not match the enclosing outer class type\n\
|
||||
required: {0}\n\
|
||||
found: {1}
|
||||
|
||||
# 0: type, 1: type
|
||||
compiler.err.incorrect.constructor.receiver.name=\
|
||||
the receiver name does not match the enclosing outer class type\n\
|
||||
required: {0}\n\
|
||||
found: {1}
|
||||
|
||||
compiler.err.no.annotations.on.dot.class=\
|
||||
no annotations are allowed in the type of a class literal
|
||||
|
@ -42,7 +42,6 @@ import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import static com.sun.tools.javac.code.BoundKind.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
|
||||
/**
|
||||
@ -807,12 +806,15 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public JCModifiers mods;
|
||||
/** variable name */
|
||||
public Name name;
|
||||
/** variable name expression */
|
||||
public JCExpression nameexpr;
|
||||
/** type of the variable */
|
||||
public JCExpression vartype;
|
||||
/** variable's initial value */
|
||||
public JCExpression init;
|
||||
/** symbol */
|
||||
public VarSymbol sym;
|
||||
|
||||
protected JCVariableDecl(JCModifiers mods,
|
||||
Name name,
|
||||
JCExpression vartype,
|
||||
@ -824,12 +826,27 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
this.init = init;
|
||||
this.sym = sym;
|
||||
}
|
||||
|
||||
protected JCVariableDecl(JCModifiers mods,
|
||||
JCExpression nameexpr,
|
||||
JCExpression vartype) {
|
||||
this(mods, null, vartype, null, null);
|
||||
this.nameexpr = nameexpr;
|
||||
if (nameexpr.hasTag(Tag.IDENT)) {
|
||||
this.name = ((JCIdent)nameexpr).name;
|
||||
} else {
|
||||
// Only other option is qualified name x.y.this;
|
||||
this.name = ((JCFieldAccess)nameexpr).name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor v) { v.visitVarDef(this); }
|
||||
|
||||
public Kind getKind() { return Kind.VARIABLE; }
|
||||
public JCModifiers getModifiers() { return mods; }
|
||||
public Name getName() { return name; }
|
||||
public JCExpression getNameExpression() { return nameexpr; }
|
||||
public JCTree getType() { return vartype; }
|
||||
public JCExpression getInitializer() {
|
||||
return init;
|
||||
@ -845,7 +862,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* A no-op statement ";".
|
||||
*/
|
||||
public static class JCSkip extends JCStatement implements EmptyStatementTree {
|
||||
|
@ -261,8 +261,6 @@ public class Pretty extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void printTypeAnnotations(List<JCAnnotation> trees) throws IOException {
|
||||
if (trees.nonEmpty())
|
||||
print(" ");
|
||||
for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
|
||||
printExpr(l.head);
|
||||
print(" ");
|
||||
@ -564,8 +562,10 @@ public class Pretty extends JCTree.Visitor {
|
||||
vartype = ((JCAnnotatedType)vartype).underlyingType;
|
||||
}
|
||||
printExpr(((JCArrayTypeTree) vartype).elemtype);
|
||||
if (tas != null)
|
||||
if (tas != null) {
|
||||
print(' ');
|
||||
printTypeAnnotations(tas);
|
||||
}
|
||||
print("... " + tree.name);
|
||||
} else {
|
||||
printExpr(tree.vartype);
|
||||
@ -918,6 +918,9 @@ public class Pretty extends JCTree.Visitor {
|
||||
printExprs(tree.typeargs);
|
||||
print(">");
|
||||
}
|
||||
if (tree.def != null && tree.def.mods.annotations.nonEmpty()) {
|
||||
printTypeAnnotations(tree.def.mods.annotations);
|
||||
}
|
||||
printExpr(tree.clazz);
|
||||
print("(");
|
||||
printExprs(tree.args);
|
||||
@ -948,7 +951,8 @@ public class Pretty extends JCTree.Visitor {
|
||||
int i = 0;
|
||||
List<List<JCAnnotation>> da = tree.dimAnnotations;
|
||||
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
|
||||
if (da.size() > i) {
|
||||
if (da.size() > i && !da.get(i).isEmpty()) {
|
||||
print(' ');
|
||||
printTypeAnnotations(da.get(i));
|
||||
}
|
||||
print("[");
|
||||
@ -958,6 +962,7 @@ public class Pretty extends JCTree.Visitor {
|
||||
}
|
||||
if (tree.elems != null) {
|
||||
if (isElemAnnoType) {
|
||||
print(' ');
|
||||
printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations);
|
||||
}
|
||||
print("[]");
|
||||
@ -1264,6 +1269,7 @@ public class Pretty extends JCTree.Visitor {
|
||||
JCAnnotatedType atype = (JCAnnotatedType) elem;
|
||||
elem = atype.underlyingType;
|
||||
if (!elem.hasTag(TYPEARRAY)) break;
|
||||
print(' ');
|
||||
printTypeAnnotations(atype.annotations);
|
||||
}
|
||||
print("[]");
|
||||
@ -1301,6 +1307,9 @@ public class Pretty extends JCTree.Visitor {
|
||||
|
||||
public void visitTypeParameter(JCTypeParameter tree) {
|
||||
try {
|
||||
if (tree.annotations.nonEmpty()) {
|
||||
this.printTypeAnnotations(tree.annotations);
|
||||
}
|
||||
print(tree.name);
|
||||
if (tree.bounds.nonEmpty()) {
|
||||
print(" extends ");
|
||||
@ -1379,6 +1388,7 @@ public class Pretty extends JCTree.Visitor {
|
||||
} else if (tree.underlyingType.getKind() == JCTree.Kind.ARRAY_TYPE) {
|
||||
JCArrayTypeTree array = (JCArrayTypeTree) tree.underlyingType;
|
||||
printBaseElementType(tree);
|
||||
print(' ');
|
||||
printTypeAnnotations(tree.annotations);
|
||||
print("[]");
|
||||
JCExpression elem = array.elemtype;
|
||||
|
@ -422,8 +422,13 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
|
||||
JCVariableDecl t = (JCVariableDecl) node;
|
||||
JCModifiers mods = copy(t.mods, p);
|
||||
JCExpression vartype = copy(t.vartype, p);
|
||||
JCExpression init = copy(t.init, p);
|
||||
return M.at(t.pos).VarDef(mods, t.name, vartype, init);
|
||||
if (t.nameexpr == null) {
|
||||
JCExpression init = copy(t.init, p);
|
||||
return M.at(t.pos).VarDef(mods, t.name, vartype, init);
|
||||
} else {
|
||||
JCExpression nameexpr = copy(t.nameexpr, p);
|
||||
return M.at(t.pos).ReceiverVarDef(mods, nameexpr, vartype);
|
||||
}
|
||||
}
|
||||
|
||||
public JCTree visitWhileLoop(WhileLoopTree node, P p) {
|
||||
|
@ -204,6 +204,12 @@ public class TreeMaker implements JCTree.Factory {
|
||||
return tree;
|
||||
}
|
||||
|
||||
public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) {
|
||||
JCVariableDecl tree = new JCVariableDecl(mods, name, vartype);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
}
|
||||
|
||||
public JCSkip Skip() {
|
||||
JCSkip tree = new JCSkip();
|
||||
tree.pos = pos;
|
||||
|
@ -94,6 +94,7 @@ public class TreeScanner extends Visitor {
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
scan(tree.mods);
|
||||
scan(tree.vartype);
|
||||
scan(tree.nameexpr);
|
||||
scan(tree.init);
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,7 @@ public class TreeTranslator extends JCTree.Visitor {
|
||||
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
tree.mods = translate(tree.mods);
|
||||
tree.nameexpr = translate(tree.nameexpr);
|
||||
tree.vartype = translate(tree.vartype);
|
||||
tree.init = translate(tree.init);
|
||||
result = tree;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,7 +37,7 @@ import java.util.NoSuchElementException;
|
||||
/** A class for generic linked lists. Links are supposed to be
|
||||
* immutable, the only exception being the incremental construction of
|
||||
* lists via ListBuffers. List is the main container class in
|
||||
* GJC. Most data structures and algorthms in GJC use lists rather
|
||||
* GJC. Most data structures and algorithms in GJC use lists rather
|
||||
* than arrays.
|
||||
*
|
||||
* <p>Lists are always trailed by a sentinel element, whose head and tail
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,9 +31,7 @@ import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.code.Kinds;
|
||||
import com.sun.tools.javac.code.Scope;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
|
||||
/**
|
||||
* Represents an annotation type.
|
||||
@ -92,7 +90,6 @@ public class AnnotationTypeDocImpl
|
||||
* Elements are always public, so no need to filter them.
|
||||
*/
|
||||
public AnnotationTypeElementDoc[] elements() {
|
||||
Names names = tsym.name.table.names;
|
||||
List<AnnotationTypeElementDoc> elements = List.nil();
|
||||
for (Scope.Entry e = tsym.members().elems; e != null; e = e.sibling) {
|
||||
if (e.sym != null && e.sym.kind == Kinds.MTH) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,6 @@ import com.sun.javadoc.*;
|
||||
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
/**
|
||||
* Represents an element of an annotation type.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@ package com.sun.tools.javadoc;
|
||||
import com.sun.javadoc.*;
|
||||
|
||||
import com.sun.tools.javac.code.Attribute;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
|
||||
|
||||
|
@ -28,14 +28,10 @@ package com.sun.tools.javadoc;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.text.CollationKey;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.code.Attribute;
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.code.Attribute.Compound;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
@ -34,10 +34,6 @@ import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
|
||||
import com.sun.tools.javac.util.Position;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,10 +25,8 @@
|
||||
|
||||
package com.sun.tools.javadoc;
|
||||
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.code.Kinds;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.comp.Enter;
|
||||
|
@ -26,9 +26,7 @@
|
||||
package com.sun.tools.javadoc;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package com.sun.tools.javadoc;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
@ -64,12 +62,9 @@ public class TypeMaker {
|
||||
if (env.legacyDoclet) {
|
||||
t = env.types.erasure(t);
|
||||
}
|
||||
if (considerAnnotations
|
||||
&& t.isAnnotated()) {
|
||||
return new AnnotatedTypeImpl(env, (com.sun.tools.javac.code.Type.AnnotatedType) t);
|
||||
}
|
||||
|
||||
if (t.isAnnotated()) {
|
||||
if (considerAnnotations &&
|
||||
t.isAnnotated()) {
|
||||
Type.AnnotatedType at = (Type.AnnotatedType) t;
|
||||
return new AnnotatedTypeImpl(env, at);
|
||||
}
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package com.sun.tools.javadoc;
|
||||
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
|
||||
import com.sun.tools.javac.code.Attribute;
|
||||
|
@ -45,7 +45,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
private static final String[][] NEGATED_TEST = NO_TEST;
|
||||
private static final String[][] TEST = {
|
||||
// Test for type annotations on Class Extends (ClassExtends.java).
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "MyClass.html",
|
||||
"extends <a href=\"../typeannos/ClassExtA.html\" title=\"annotation " +
|
||||
"in typeannos\">@ClassExtA</a> <a href=\"../typeannos/ParameterizedClass.html\" " +
|
||||
@ -53,8 +52,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"../typeannos/ClassExtB.html\" title=\"annotation in typeannos\">" +
|
||||
"@ClassExtB</a> java.lang.String>"
|
||||
},
|
||||
*/
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "MyClass.html",
|
||||
"implements <a href=\"../typeannos/ClassExtB.html\" title=\"" +
|
||||
"annotation in typeannos\">@ClassExtB</a> java.lang.CharSequence, " +
|
||||
@ -64,8 +61,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"<a href=\"../typeannos/ClassExtB.html\" title=\"annotation in " +
|
||||
"typeannos\">@ClassExtB</a> java.lang.String></pre>"
|
||||
},
|
||||
*/
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "MyInterface.html",
|
||||
"extends <a href=\"../typeannos/ClassExtA.html\" title=\"annotation " +
|
||||
"in typeannos\">@ClassExtA</a> <a href=\"../typeannos/" +
|
||||
@ -75,7 +70,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"<a href=\"../typeannos/ClassExtB.html\" title=\"annotation in " +
|
||||
"typeannos\">@ClassExtB</a> java.lang.CharSequence</pre>"
|
||||
},
|
||||
*/
|
||||
|
||||
// Test for type annotations on Class Parameters (ClassParameters.java).
|
||||
{BUG_ID + FS + "typeannos" + FS + "ExtendsBound.html",
|
||||
@ -83,7 +77,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"href=\"../typeannos/ClassParamA.html\" title=\"annotation in " +
|
||||
"typeannos\">@ClassParamA</a> java.lang.String></span>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "ExtendsGeneric.html",
|
||||
"<pre> class <span class=\"strong\">ExtendsGeneric<K extends " +
|
||||
"<a href=\"../typeannos/ClassParamA.html\" title=\"annotation in " +
|
||||
@ -92,7 +85,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"../typeannos/ClassParamB.html\" title=\"annotation in typeannos\">" +
|
||||
"@ClassParamB</a> java.lang.String>></span>"
|
||||
},
|
||||
*/
|
||||
{BUG_ID + FS + "typeannos" + FS + "TwoBounds.html",
|
||||
"<pre> class <span class=\"strong\">TwoBounds<K extends <a href=\"" +
|
||||
"../typeannos/ClassParamA.html\" title=\"annotation in typeannos\">" +
|
||||
@ -119,7 +111,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
},
|
||||
|
||||
// Test for type annotations on fields (Fields.java).
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "DefaultScope.html",
|
||||
"<pre><a href=\"../typeannos/Parameterized.html\" title=\"class in " +
|
||||
"typeannos\">Parameterized</a><<a href=\"../typeannos/FldA.html\" " +
|
||||
@ -127,7 +118,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"href=\"../typeannos/FldB.html\" title=\"annotation in typeannos\">" +
|
||||
"@FldB</a> java.lang.String> bothTypeArgs</pre>"
|
||||
},
|
||||
*/
|
||||
{BUG_ID + FS + "typeannos" + FS + "DefaultScope.html",
|
||||
"<pre><a href=\"../typeannos/FldA.html\" title=\"annotation in " +
|
||||
"typeannos\">@FldA</a> java.lang.String <a href=\"../typeannos/" +
|
||||
@ -147,7 +137,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"typeannos\">@FldC</a> <a href=\"../typeannos/FldB.html\" title=\"" +
|
||||
"annotation in typeannos\">@FldB</a> [] array2Deep</pre>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "ModifiedScoped.html",
|
||||
"<pre>public final <a href=\"../typeannos/Parameterized.html\" " +
|
||||
"title=\"class in typeannos\">Parameterized</a><<a href=\"../" +
|
||||
@ -160,7 +149,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"title=\"annotation in typeannos\">@FldB</a> java.lang.String> " +
|
||||
"nestedParameterized</pre>"
|
||||
},
|
||||
*/
|
||||
{BUG_ID + FS + "typeannos" + FS + "ModifiedScoped.html",
|
||||
"<pre>public final <a href=\"../typeannos/FldA.html\" " +
|
||||
"title=\"annotation in typeannos\">@FldA</a> java.lang.String[][] " +
|
||||
@ -184,7 +172,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"<pre><a href=\"../typeannos/MRtnA.html\" title=\"annotation in " +
|
||||
"typeannos\">@MRtnA</a> java.lang.String[][] array2()</pre>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "MtdModifiedScoped.html",
|
||||
"<pre>public final <a href=\"../typeannos/MtdParameterized.html\" " +
|
||||
"title=\"class in typeannos\">MtdParameterized</a><<a href=\"../" +
|
||||
@ -197,7 +184,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"MRtnB.html\" title=\"annotation in typeannos\">@MRtnB</a> java." +
|
||||
"lang.String> nestedMtdParameterized()</pre>"
|
||||
},
|
||||
*/
|
||||
|
||||
// Test for type annotations on method type parameters (MethodTypeParameters.java).
|
||||
{BUG_ID + FS + "typeannos" + FS + "UnscopedUnmodified.html",
|
||||
@ -205,7 +191,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"annotation in typeannos\">@MTyParamA</a> java.lang.String>" +
|
||||
" void methodExtends()</pre>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "UnscopedUnmodified.html",
|
||||
"<pre><K extends <a href=\"../typeannos/MTyParamA.html\" title=\"" +
|
||||
"annotation in typeannos\">@MTyParamA</a> <a href=\"../typeannos/" +
|
||||
@ -214,13 +199,11 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"title=\"annotation in typeannos\">@MTyParamB</a> java.lang.String" +
|
||||
">> void nestedExtends()</pre>"
|
||||
},
|
||||
*/
|
||||
{BUG_ID + FS + "typeannos" + FS + "PublicModifiedMethods.html",
|
||||
"<pre>public final <K extends <a href=\"../typeannos/" +
|
||||
"MTyParamA.html\" title=\"annotation in typeannos\">@MTyParamA</a> " +
|
||||
"java.lang.String> void methodExtends()</pre>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "PublicModifiedMethods.html",
|
||||
"<pre>public final <K extends <a href=\"../typeannos/" +
|
||||
"MTyParamA.html\" title=\"annotation in typeannos\">@MTyParamA</a> " +
|
||||
@ -231,7 +214,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"title=\"annotation in typeannos\">@MTyParamB</a> java.lang.String" +
|
||||
">> void dual()</pre>"
|
||||
},
|
||||
*/
|
||||
|
||||
// Test for type annotations on parameters (Parameters.java).
|
||||
{BUG_ID + FS + "typeannos" + FS + "Parameters.html",
|
||||
@ -240,7 +222,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"ParaParameterized</a><java.lang.String,java.lang.String>" +
|
||||
" a)</pre>"
|
||||
},
|
||||
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
|
||||
{BUG_ID + FS + "typeannos" + FS + "Parameters.html",
|
||||
"<pre>void nestedParaParameterized(<a href=\"../typeannos/" +
|
||||
"ParaParameterized.html\" title=\"class in typeannos\">" +
|
||||
@ -254,7 +235,6 @@ public class TestTypeAnnotations extends JavadocTester {
|
||||
"typeannos/ParamB.html\" title=\"annotation in typeannos\">@ParamB" +
|
||||
"</a> java.lang.String> a)</pre>"
|
||||
},
|
||||
*/
|
||||
{BUG_ID + FS + "typeannos" + FS + "Parameters.html",
|
||||
"<pre>void array2Deep(<a href=\"../typeannos/ParamA.html\" " +
|
||||
"title=\"annotation in typeannos\">@ParamA</a> java.lang.String " +
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8006735
|
||||
* @summary Smoke test for ensuring that annotations are emited to javadoc
|
||||
* @summary Smoke test for ensuring that annotations are emitted to javadoc
|
||||
*
|
||||
* @author Mahmood Ali <mali>
|
||||
* @library ../../lib/
|
||||
@ -46,37 +46,35 @@ public class TestSmoke extends JavadocTester {
|
||||
//Input for string search tests.
|
||||
private static final String[][] TEST = {
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@DA"},
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@DA"},
|
||||
*/
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x06.html", "@DA"},
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20A.html", "@DTPA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20B.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22A.html", "@DTPA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22B.html", "@DA"},
|
||||
*/
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x10.html", "@DA"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@DA"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x12.html", "@DA"},
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x11.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x13.html", "@DA"},
|
||||
*/
|
||||
/* @ignore 8013406: Test cases fail in javadoc test TestSmoke.java
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x15.html", "@DA"},
|
||||
*/
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x14.html", "@DA"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x16.html", "@DA"}
|
||||
};
|
||||
@ -94,7 +92,11 @@ public class TestSmoke extends JavadocTester {
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20A.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x20B.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22A.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x22B.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x10.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@A"},
|
||||
{BUG_ID + FS + "pkg" + FS + "T0x12.html", "@A"},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,24 +36,19 @@ import java.io.*;
|
||||
* @author Yuri Gaevsky
|
||||
*/
|
||||
|
||||
@Target({TYPE_USE})
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface A {}
|
||||
|
||||
@Target({TYPE_USE})
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@interface DA {}
|
||||
|
||||
/** wildcard bound */
|
||||
class T0x1C {
|
||||
void m0x1C(List<? extends @A @DA String> lst) {}
|
||||
}
|
||||
|
||||
/** wildcard bound generic/array */
|
||||
class T0x1D<T> {
|
||||
void m0x1D(List<? extends @A @DA List<int[]>> lst) {}
|
||||
}
|
||||
@Target(TYPE_PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@interface DTPA {}
|
||||
|
||||
/** typecast */
|
||||
class T0x00 {
|
||||
@ -76,76 +71,6 @@ class T0x02 {
|
||||
}
|
||||
}
|
||||
|
||||
/** object creation (new) */
|
||||
class T0x04 {
|
||||
void m0x04() {
|
||||
new @A @DA ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
/** local variable */
|
||||
class T0x08 {
|
||||
void m0x08() {
|
||||
@A @DA String s = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** method parameter generic/array */
|
||||
class T0x0D {
|
||||
void m0x0D(HashMap<@A @DA Object, List<@A @DA List<@A @DA Class>>> s1) {}
|
||||
}
|
||||
|
||||
/** method receiver */
|
||||
class T0x06 {
|
||||
void m0x06(@A @DA T0x06 this) {}
|
||||
}
|
||||
|
||||
/** method return type generic/array */
|
||||
class T0x0B {
|
||||
Class<@A @DA Object> m0x0B() { return null; }
|
||||
}
|
||||
|
||||
/** field generic/array */
|
||||
class T0x0F {
|
||||
HashMap<@A @DA Object, @A @DA Object> c1;
|
||||
}
|
||||
|
||||
/** method type parameter */
|
||||
class T0x20<T, U> {
|
||||
<@A @DA T, @A @DA U> void m0x20() {}
|
||||
}
|
||||
|
||||
/** class type parameter */
|
||||
class T0x22<@A @DA T, @A @DA U> {
|
||||
}
|
||||
|
||||
/** class type parameter bound */
|
||||
class T0x10<T extends @A @DA Cloneable> {
|
||||
}
|
||||
|
||||
class T0x10A<T extends @A @DA Object> {
|
||||
}
|
||||
|
||||
/** method type parameter bound */
|
||||
class T0x12<T> {
|
||||
<T extends @A @DA Cloneable> void m0x12() {}
|
||||
}
|
||||
|
||||
/** class type parameter bound generic/array */
|
||||
class T0x11<T extends List<@A @DA T>> {
|
||||
}
|
||||
|
||||
/** method type parameter bound generic/array */
|
||||
class T0x13 {
|
||||
static <T extends Comparable<@A @DA T>> T m0x13() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** class extends/implements generic/array */
|
||||
class T0x15<T> extends ArrayList<@A @DA T> {
|
||||
}
|
||||
|
||||
/** type test (instanceof) generic/array */
|
||||
class T0x03<T> {
|
||||
void m0x03(T typeObj, Object obj) {
|
||||
@ -153,6 +78,13 @@ class T0x03<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/** object creation (new) */
|
||||
class T0x04 {
|
||||
void m0x04() {
|
||||
new @A @DA ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
/** object creation (new) generic/array */
|
||||
class T0x05<T> {
|
||||
void m0x05() {
|
||||
@ -160,6 +92,18 @@ class T0x05<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/** method receiver */
|
||||
class T0x06 {
|
||||
void m0x06(@A @DA T0x06 this) {}
|
||||
}
|
||||
|
||||
/** local variable */
|
||||
class T0x08 {
|
||||
void m0x08() {
|
||||
@A @DA String s = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** local variable generic/array */
|
||||
class T0x09<T> {
|
||||
void g() {
|
||||
@ -171,20 +115,55 @@ class T0x09<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/** type argument in constructor call generic/array */
|
||||
class T0x19 {
|
||||
<T> T0x19() {}
|
||||
/** method return type generic/array */
|
||||
class T0x0B {
|
||||
Class<@A @DA Object> m0x0B() { return null; }
|
||||
}
|
||||
|
||||
void g() {
|
||||
new <List<@A @DA String>> T0x19();
|
||||
/** method parameter generic/array */
|
||||
class T0x0D {
|
||||
void m0x0D(HashMap<@A @DA Object, List<@A @DA List<@A @DA Class>>> s1) {}
|
||||
}
|
||||
|
||||
/** field generic/array */
|
||||
class T0x0F {
|
||||
HashMap<@A @DA Object, @A @DA Object> c1;
|
||||
}
|
||||
|
||||
/** class type parameter bound */
|
||||
class T0x10<T extends @A @DA Cloneable> {
|
||||
}
|
||||
|
||||
class T0x10A<T extends @A @DA Object> {
|
||||
}
|
||||
|
||||
/** class type parameter bound generic/array */
|
||||
class T0x11<T extends List<@A @DA T>> {
|
||||
}
|
||||
|
||||
/** method type parameter bound */
|
||||
class T0x12<T> {
|
||||
<T extends @A @DA Cloneable> void m0x12() {}
|
||||
}
|
||||
|
||||
/** method type parameter bound generic/array */
|
||||
class T0x13 {
|
||||
static <T extends Comparable<@A @DA T>> T m0x13() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** type argument in method call generic/array */
|
||||
class T0x1B<T> {
|
||||
void m0x1B() {
|
||||
Collections.<T @A @DA []>emptyList();
|
||||
}
|
||||
/** class extends/implements */
|
||||
class T0x14 extends @A @DA Thread implements @A @DA Serializable, @A @DA Cloneable {
|
||||
}
|
||||
|
||||
/** class extends/implements generic/array */
|
||||
class T0x15<T> extends ArrayList<@A @DA T> {
|
||||
}
|
||||
|
||||
/** exception type in throws */
|
||||
class T0x16 {
|
||||
void m0x16() throws @A @DA Exception {}
|
||||
}
|
||||
|
||||
/** type argument in constructor call */
|
||||
@ -196,6 +175,15 @@ class T0x18<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/** type argument in constructor call generic/array */
|
||||
class T0x19 {
|
||||
<T> T0x19() {}
|
||||
|
||||
void g() {
|
||||
new <List<@A @DA String>> T0x19();
|
||||
}
|
||||
}
|
||||
|
||||
/** type argument in method call */
|
||||
class T0x1A<T,U> {
|
||||
public static <T, U> T m() { return null; }
|
||||
@ -204,11 +192,43 @@ class T0x1A<T,U> {
|
||||
}
|
||||
}
|
||||
|
||||
/** class extends/implements */
|
||||
class T0x14 extends @A @DA Thread implements @A @DA Serializable, @A @DA Cloneable {
|
||||
/** type argument in method call generic/array */
|
||||
class T0x1B<T> {
|
||||
void m0x1B() {
|
||||
Collections.<T @A @DA []>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/** exception type in throws */
|
||||
class T0x16 {
|
||||
void m0x16() throws @A @DA Exception {}
|
||||
/** wildcard bound */
|
||||
class T0x1C {
|
||||
void m0x1C(List<? extends @A @DA String> lst) {}
|
||||
}
|
||||
|
||||
/** wildcard bound generic/array */
|
||||
class T0x1D<T> {
|
||||
void m0x1D(List<? extends @A @DA List<int[]>> lst) {}
|
||||
}
|
||||
|
||||
/** method type parameter */
|
||||
class T0x20 {
|
||||
<@A @DA T> void m0x20() {}
|
||||
}
|
||||
|
||||
class T0x20A {
|
||||
<@A @DTPA T> void m0x20A() {}
|
||||
}
|
||||
|
||||
class T0x20B {
|
||||
<T> void m0x20B(@A @DA T p) {}
|
||||
}
|
||||
|
||||
/** class type parameter */
|
||||
class T0x22<@A @DA T> {
|
||||
}
|
||||
|
||||
class T0x22A<@A @DTPA T> {
|
||||
}
|
||||
|
||||
class T0x22B<T> {
|
||||
@A @DA T f;
|
||||
}
|
||||
|
@ -28,11 +28,17 @@
|
||||
* @author Mahmood Ali
|
||||
* @compile Scopes.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
class Scopes {
|
||||
|
||||
void test(@A(VALUE) Scopes this) { }
|
||||
void test1(@A(value=VALUE) Scopes this) { }
|
||||
|
||||
private static final int VALUE = 1;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface A { int value(); }
|
||||
}
|
||||
|
@ -66,12 +66,12 @@ public class ClassfileTestHelper {
|
||||
}
|
||||
|
||||
ClassFile getClassFile(URL url) throws IOException, ConstantPoolException {
|
||||
InputStream in = url.openStream();
|
||||
try {
|
||||
return ClassFile.read(in);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
InputStream in = url.openStream();
|
||||
try {
|
||||
return ClassFile.read(in);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
/************ Helper annotations counting methods ******************/
|
||||
@ -83,20 +83,43 @@ public class ClassfileTestHelper {
|
||||
test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
}
|
||||
|
||||
void test(ClassFile cf, Method m) {
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
void test(ClassFile cf, Field f, Boolean local) {
|
||||
if (!local) {
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
} else {
|
||||
test("CODE",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("CODE",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("CODE",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("CODE",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
}
|
||||
}
|
||||
|
||||
void test(ClassFile cf, Field f) {
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
test(cf, f, false);
|
||||
}
|
||||
|
||||
// 'local' determines whether to look for annotations in code attribute or not.
|
||||
void test(ClassFile cf, Method m, Boolean local) {
|
||||
if (!local) {
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
} else {
|
||||
test("MCODE",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
test("MCODE",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
|
||||
test("MCODE",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
|
||||
test("MCODE",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
|
||||
}
|
||||
}
|
||||
|
||||
// default to not looking in code attribute
|
||||
void test(ClassFile cf, Method m ) {
|
||||
test(cf, m, false);
|
||||
}
|
||||
|
||||
// Test the result of Attributes.getIndex according to expectations
|
||||
// encoded in the class/field/method name; increment annotations counts.
|
||||
@ -105,18 +128,47 @@ public class ClassfileTestHelper {
|
||||
String name = null;
|
||||
int index = -1;
|
||||
Attribute attr = null;
|
||||
Code_attribute cAttr = null;
|
||||
boolean isTAattr = annName.contains("TypeAnnotations");
|
||||
try {
|
||||
switch(testtype) {
|
||||
case "FIELD":
|
||||
name = f.getName(cf.constant_pool);
|
||||
index = f.attributes.getIndex(cf.constant_pool, annName);
|
||||
if(index!= -1) attr = f.attributes.get(index);
|
||||
if(index!= -1)
|
||||
attr = f.attributes.get(index);
|
||||
break;
|
||||
case "CODE":
|
||||
name = f.getName(cf.constant_pool);
|
||||
//fetch index of and code attribute and annotations from code attribute.
|
||||
index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code);
|
||||
if(index!= -1) {
|
||||
attr = cf.attributes.get(index);
|
||||
assert attr instanceof Code_attribute;
|
||||
cAttr = (Code_attribute)attr;
|
||||
index = cAttr.attributes.getIndex(cf.constant_pool, annName);
|
||||
if(index!= -1)
|
||||
attr = cAttr.attributes.get(index);
|
||||
}
|
||||
break;
|
||||
case "METHOD":
|
||||
name = m.getName(cf.constant_pool);
|
||||
index = m.attributes.getIndex(cf.constant_pool, annName);
|
||||
if(index!= -1) attr = m.attributes.get(index);
|
||||
if(index!= -1)
|
||||
attr = m.attributes.get(index);
|
||||
break;
|
||||
case "MCODE":
|
||||
name = m.getName(cf.constant_pool);
|
||||
//fetch index of and code attribute and annotations from code attribute.
|
||||
index = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
|
||||
if(index!= -1) {
|
||||
attr = m.attributes.get(index);
|
||||
assert attr instanceof Code_attribute;
|
||||
cAttr = (Code_attribute)attr;
|
||||
index = cAttr.attributes.getIndex(cf.constant_pool, annName);
|
||||
if(index!= -1)
|
||||
attr = cAttr.attributes.get(index);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
name = cf.getName();
|
||||
@ -126,7 +178,6 @@ public class ClassfileTestHelper {
|
||||
} catch(ConstantPoolException cpe) { cpe.printStackTrace(); }
|
||||
|
||||
if (index != -1) {
|
||||
assert attr instanceof RuntimeTypeAnnotations_attribute;
|
||||
if(isTAattr) { //count RuntimeTypeAnnotations
|
||||
RuntimeTypeAnnotations_attribute tAttr =
|
||||
(RuntimeTypeAnnotations_attribute)attr;
|
||||
|
@ -24,7 +24,6 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8005085 8005877 8004829 8005681 8006734 8006775
|
||||
* @ignore 8013409: test failures for type annotations
|
||||
* @summary Combinations of Target ElementTypes on (repeated)type annotations.
|
||||
*/
|
||||
|
||||
@ -32,10 +31,25 @@ import com.sun.tools.classfile.*;
|
||||
import java.io.File;
|
||||
|
||||
public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
// Helps identify test case in event of failure.
|
||||
|
||||
// Test count helps identify test case in event of failure.
|
||||
int testcount = 0;
|
||||
int src1 = 1, src2 = 2, src4 = 4,
|
||||
src5 = 5, src6 = 6, src7 = 7;
|
||||
|
||||
// Base test case template descriptions
|
||||
enum srce {
|
||||
src1("(repeating) type annotations at class level"),
|
||||
src2("(repeating) type annotations on method"),
|
||||
src3("(repeating) type annotations on wildcard, type arguments in anonymous class"),
|
||||
src4("(repeating) type annotations on type parameters, bounds and type arguments on class decl"),
|
||||
src5("(repeating) type annotations on type parameters, bounds and type arguments on method"),
|
||||
src6("(repeating) type annotations on type parameters, bounds and type arguments in method");
|
||||
|
||||
String description;
|
||||
|
||||
srce(String desc) {
|
||||
this.description = this + ": " +desc;
|
||||
}
|
||||
}
|
||||
|
||||
String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR",
|
||||
"LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"};
|
||||
@ -52,7 +66,6 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
// Determines which repeat and order in source(ABMix).
|
||||
Boolean As= false, BDs=true, ABMix=false;
|
||||
int testrun=0;
|
||||
// A repeats and/or B/D repeats, ABMix for order of As and Bs.
|
||||
Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats
|
||||
{true,false,false}, //repeat @A
|
||||
{false,true,false}, //repeat @B
|
||||
@ -64,29 +77,29 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
for(String et : ETypes) {
|
||||
switch(et) {
|
||||
case "METHOD":
|
||||
test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1);
|
||||
test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src2);
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src4);
|
||||
test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src6);
|
||||
test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1);
|
||||
test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src2);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src4);
|
||||
test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src6);
|
||||
test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
|
||||
test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src2);
|
||||
test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src3);
|
||||
test(10, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src5);
|
||||
test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
|
||||
test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src2);
|
||||
test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src3);
|
||||
test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
|
||||
break;
|
||||
case "CONSTRUCTOR":
|
||||
case "FIELD":
|
||||
test( 8, 0, 4, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1);
|
||||
test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5);
|
||||
test( 9, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src7);
|
||||
test( 0, 8, 0, 4, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1);
|
||||
test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5);
|
||||
test( 0, 9, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src7);
|
||||
test( 8, 0, 4, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
|
||||
test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src4);
|
||||
test( 9, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src6);
|
||||
test( 0, 8, 0, 4, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
|
||||
test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
|
||||
test( 0, 9, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src6);
|
||||
break;
|
||||
default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/
|
||||
test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src1);
|
||||
test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src5);
|
||||
test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, src1);
|
||||
test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, src5);
|
||||
test( 8, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
|
||||
test( 6, 0, 3, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src4);
|
||||
test( 0, 8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
|
||||
test( 0, 6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,7 +107,7 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
|
||||
public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
|
||||
Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
|
||||
Integer N, int source) throws Exception {
|
||||
Integer N, srce source) throws Exception {
|
||||
++testcount;
|
||||
expected_tvisibles = tvis;
|
||||
expected_tinvisibles = tinv;
|
||||
@ -125,7 +138,8 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
//if sourcString() set hasInnerClass it also set innerClassname.
|
||||
if(hasInnerClass) {
|
||||
StringBuffer sb = new StringBuffer(classFile.getAbsolutePath());
|
||||
classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString());
|
||||
classFile=new File(sb.insert(sb.lastIndexOf(".class"),
|
||||
innerClassname).toString());
|
||||
}
|
||||
ClassFile cf = ClassFile.read(classFile);
|
||||
|
||||
@ -152,7 +166,7 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
//
|
||||
String sourceString(String testname, String retentn, String annot2,
|
||||
Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
|
||||
int src) {
|
||||
srce src) {
|
||||
|
||||
String As = "@A", Bs = "@B", Ds = "@D";
|
||||
if(Arepeats) As = "@A @A";
|
||||
@ -201,11 +215,11 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
|
||||
"@Retention("+retentn+")\n" +
|
||||
"@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
|
||||
"@interface DC { D[] value(); }\n\n");
|
||||
"@interface DC { D[] value(); }\n");
|
||||
|
||||
// Test case sources with sample generated source.
|
||||
switch(src) {
|
||||
case 1: // repeating type annotations at class level
|
||||
case src1: // repeating type annotations at class level
|
||||
/*
|
||||
* @A @B class Test1 {
|
||||
* @A @B Test1(){}
|
||||
@ -218,21 +232,21 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }}
|
||||
*/
|
||||
source = new String(
|
||||
"// (repeating) type annotations at class level. \n" +
|
||||
"_As_ _Bs_ class " + testname + " {\n" +
|
||||
"_As_ _Bs_ " + testname +"(){} \n" +
|
||||
"_As_ _Bs_ Integer i1 = 0; \n" +
|
||||
"String _As_ _Bs_ [] _As_ _Bs_ [] sa = null; \n" +
|
||||
"// type usage in method body \n" +
|
||||
"String test("+testname+" this, " +
|
||||
"String param, String ... vararg) { \n" +
|
||||
" Object o = new String [3]; \n" +
|
||||
" return (String) null; \n" +
|
||||
"} \n" +
|
||||
"} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
"// " + src.description + "\n" +
|
||||
"_As_ _Bs_ class " + testname + " {\n" +
|
||||
"_As_ _Bs_ " + testname +"(){} \n" +
|
||||
"_As_ _Bs_ Integer i1 = 0; \n" +
|
||||
"String _As_ _Bs_ [] _As_ _Bs_ [] sa = null; \n" +
|
||||
"// type usage in method body \n" +
|
||||
"String test("+testname+" this, " +
|
||||
"String param, String ... vararg) { \n" +
|
||||
" Object o = new String [3]; \n" +
|
||||
" return (String) null; \n" +
|
||||
"}\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case 2: // (repeating) type annotations on method.
|
||||
case src2: // (repeating) type annotations on method.
|
||||
/*
|
||||
* class Test12 {
|
||||
* Test12(){}
|
||||
@ -243,26 +257,26 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }}
|
||||
*/
|
||||
source = new String(
|
||||
"// (repeating) type annotations on method. \n" +
|
||||
"class " + testname + " {\n" +
|
||||
testname +"(){} \n" +
|
||||
"// type usage on method \n" +
|
||||
"_As_ _Bs_ String test(_As_ _Bs_ "+testname+" this, " +
|
||||
"_As_ _Bs_ String param, _As_ _Bs_ String _As_ _Bs_ ... vararg) { \n" +
|
||||
" Object o = new String [3]; \n" +
|
||||
" return (String) null; \n" +
|
||||
"} \n" +
|
||||
"} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + " {\n" +
|
||||
testname +"(){} \n" +
|
||||
"// type usage on method \n" +
|
||||
"_As_ _Bs_ String test(_As_ _Bs_ "+testname+" this, " +
|
||||
"_As_ _Bs_ String param, _As_ _Bs_ String _As_ _Bs_ ... vararg) { \n" +
|
||||
" Object o = new String [3]; \n" +
|
||||
" return (String) null; \n" +
|
||||
"}\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case 4: //(repeating) annotations on wildcard, type arguments in anonymous class.
|
||||
case src3: //(repeating) annotations on wildcard, type arguments in anonymous class.
|
||||
/*
|
||||
* class Test13<T extends Object> {
|
||||
* public T data = null;
|
||||
* T getData() { return data;}
|
||||
* String mtest( Test13<String> t){ return t.getData(); }
|
||||
* public void test() {
|
||||
* mtest( new Test13<@A @B String>() {
|
||||
* mtest( new Test13<String>() {
|
||||
* void m1(List<@A @B ? extends @A @B Object> lst) {}
|
||||
* void m2() throws@A @B Exception { }
|
||||
* });
|
||||
@ -270,22 +284,23 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating) annotations on wildcard, type arguments in anonymous class. \n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" public T data = null;\n" +
|
||||
" T getData() { return data;}\n" +
|
||||
" String mtest( " + testname + "<String> t){ return t.getData(); }\n" +
|
||||
" public void test() {\n" +
|
||||
" mtest( new " + testname + "<_As_ _Bs_ String>() {\n" +
|
||||
" void m1(List<_As_ _Bs_ ? extends _As_ _Bs_ Object> lst) {}\n" +
|
||||
" void m2() throws_As_ _Bs_ Exception { }\n" +
|
||||
" });\n" +
|
||||
" }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) + "\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1";
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" public T data = null;\n" +
|
||||
" T getData() { return data;}\n" +
|
||||
" String mtest( " + testname + "<String> t){ return t.getData(); }\n" +
|
||||
" public void test() {\n" +
|
||||
" mtest( new " + testname + "<String>() {\n" +
|
||||
" void m1(List<_As_ _Bs_ ? extends _As_ _Bs_ Object> lst) {}\n" +
|
||||
" void m2() throws_As_ _Bs_ Exception { }\n" +
|
||||
" });\n" +
|
||||
" }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1";
|
||||
break;
|
||||
case 5: // (repeating)annotations on type parameters, bounds and type arguments on class decl.
|
||||
case src4: // (repeating)annotations on type parameters, bounds and type arguments on class decl.
|
||||
/*
|
||||
* @A @B @D
|
||||
* class Test2<@A @B @C @D T extends @A @B Object> {
|
||||
@ -297,18 +312,18 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating)annotations on type parameters, bounds and type arguments on class decl. \n" +
|
||||
"_As_ _Bs_ _Ds_\n" + //8004829: A and B on type parameter below.
|
||||
"class " + testname + "<_As_ _Bs_ @C _Ds_ T extends _As_ _Bs_ Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<List< String>, Integer>();\n" +
|
||||
" Map<List<String>,Integer> map2 = new HashMap<>();\n" +
|
||||
" String test(" + testname + "<T> this) { return null;}\n" +
|
||||
" <T> String genericMethod(T t) { return null; }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n\n";
|
||||
break;
|
||||
case 6: // (repeating) annotations on type parameters, bounds and type arguments on method.
|
||||
"// " + src.description + "\n" +
|
||||
"_As_ _Bs_ _Ds_\n" + //8004829: A and B on type parameter below.
|
||||
"class " + testname + "<_As_ _Bs_ @C _Ds_ T extends _As_ _Bs_ Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<List< String>, Integer>();\n" +
|
||||
" Map<List<String>,Integer> map2 = new HashMap<>();\n" +
|
||||
" String test(" + testname + "<T> this) { return null;}\n" +
|
||||
" <T> String genericMethod(T t) { return null; }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n";
|
||||
break;
|
||||
case src5: // (repeating) annotations on type parameters, bounds and type arguments on method.
|
||||
/*
|
||||
* class Test14<T extends Object> {
|
||||
* Map<List<String>, Integer> map =
|
||||
@ -319,17 +334,17 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating) annotations on type parameters, bounds and type arguments on method. \n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<List<String>, Integer>();\n" +
|
||||
" Map<List<String>, Integer> map2 = new HashMap<>();\n" +
|
||||
" String test(_As_ _Bs_ " + testname + "<_Ds_ T> this) { return null;}\n" +
|
||||
" <@C _Ds_ T> _As_ _Bs_ String genericMethod(_As_ _Bs_ _Ds_ T t) { return null; }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n\n";
|
||||
break;
|
||||
case 7: // repeating annotations on type parameters, bounds and type arguments in method.
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<List<String>, Integer>();\n" +
|
||||
" Map<List<String>, Integer> map2 = new HashMap<>();\n" +
|
||||
" String test(_As_ _Bs_ " + testname + "<_Ds_ T> this) { return null;}\n" +
|
||||
" <@C _Ds_ T> _As_ _Bs_ String genericMethod(_As_ _Bs_ _Ds_ T t) { return null; }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n";
|
||||
break;
|
||||
case src6: // repeating annotations on type parameters, bounds and type arguments in method.
|
||||
/*
|
||||
* class Test7{
|
||||
* <E extends Comparable> Map<List<E>, E > foo(E e) {
|
||||
@ -344,22 +359,22 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating)annotations on type parameters of class, method return value in method. \n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
|
||||
" class maptest <_As_ _Bs_ _Ds_ E> {\n" + // inner class $1maptest
|
||||
" Map<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E> getMap() { \n" +
|
||||
" return new HashMap<List<E>,E>();\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" return new maptest<E>().getMap();\n" +
|
||||
" }\n" +
|
||||
" Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1maptest";
|
||||
break;
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
|
||||
" class maptest <_As_ _Bs_ _Ds_ E> {\n" + // inner class $1maptest
|
||||
" Map<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E> getMap() { \n" +
|
||||
" return new HashMap<List<E>,E>();\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" return new maptest<E>().getMap();\n" +
|
||||
" }\n" +
|
||||
" Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1maptest";
|
||||
break;
|
||||
}
|
||||
return imports + source;
|
||||
}
|
||||
|
@ -23,8 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8005085 8005877 8004829 8005681 8006734 8006775
|
||||
* @ignore 8013409: test failures for type annotations
|
||||
* @bug 8005085 8005877 8004829 8005681 8006734 8006775 8006507
|
||||
* @summary Combinations of Target ElementTypes on (repeated)type annotations.
|
||||
*/
|
||||
|
||||
@ -32,9 +31,27 @@ import com.sun.tools.classfile.*;
|
||||
import java.io.File;
|
||||
|
||||
public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
// Helps identify test case in event of failure.
|
||||
|
||||
// Test count helps identify test case in event of failure.
|
||||
int testcount = 0;
|
||||
int src3 = 3, src8 = 8, src9 = 9;
|
||||
|
||||
// Base test case template descriptions
|
||||
enum srce {
|
||||
src1("(repeating) type annotations on on field in method body",true),
|
||||
src2("(repeating) type annotations on type parameters, bounds and type arguments", true),
|
||||
src3("(repeating) type annotations on type parameters of class, method return value in method", true),
|
||||
src4("(repeating) type annotations on field in anonymous class", false),
|
||||
src5("(repeating) type annotations on field in anonymous class", false);
|
||||
|
||||
String description;
|
||||
Boolean local;
|
||||
|
||||
srce(String desc, Boolean b) {
|
||||
this.description = this + ": " +desc;
|
||||
this.local = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR",
|
||||
"LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"};
|
||||
@ -51,31 +68,36 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
// Determines which repeat and order in source(ABMix).
|
||||
Boolean As= false, BDs=true, ABMix=false;
|
||||
int testrun=0;
|
||||
// A repeats and/or B/D repeats, ABMix for order of As and Bs.
|
||||
Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats
|
||||
{true,false,false}, //repeat @A
|
||||
{false,true,false}, //repeat @B
|
||||
{true,true,false}, //repeat both
|
||||
{false,false,true} //repeat mix
|
||||
};
|
||||
|
||||
for(Boolean[] bCombo : bRepeat) {
|
||||
As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
|
||||
for(String et : ETypes) {
|
||||
switch(et) {
|
||||
case "METHOD":
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3);
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
|
||||
test( 2, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src5);
|
||||
test( 0, 2, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
|
||||
break;
|
||||
case "CONSTRUCTOR":
|
||||
case "FIELD":
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src3);
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src8);
|
||||
test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, src9);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src3);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src8);
|
||||
test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, src9);
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
|
||||
test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src2);
|
||||
test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src3);
|
||||
test( 2, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src4);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
|
||||
test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src2);
|
||||
test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src3);
|
||||
test( 0, 2, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
|
||||
break;
|
||||
default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/
|
||||
test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
|
||||
test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -84,7 +106,7 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
|
||||
public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
|
||||
Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
|
||||
Integer N, int source) throws Exception {
|
||||
Integer N, srce source) throws Exception {
|
||||
++testcount;
|
||||
expected_tvisibles = tvis;
|
||||
expected_tinvisibles = tinv;
|
||||
@ -97,14 +119,19 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
|
||||
", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
|
||||
", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
|
||||
et2 + ", src=" + source;
|
||||
et2 + ", src=" + source + "\n " + source.description;
|
||||
|
||||
// Uncomment this block to run the tests but skip failing scenarios.
|
||||
// // 8005681 - skip cases with repeated annotations on new, array, cast.
|
||||
// if((source==3 || source==8 || source==9) && (ABmix || (Arepeats && BDrepeats))) {
|
||||
// System.out.println(testDef+"\n8005681-skip repeated annotations on new,array,cast");
|
||||
// return;
|
||||
// }
|
||||
if(
|
||||
// 8005681 - src1,2,3 - skip cases with repeated annotations on new, array, cast.
|
||||
(( source.equals(srce.src1) || source.equals(srce.src2) ||
|
||||
source.equals(srce.src3)) && (ABmix || (Arepeats && BDrepeats)))
|
||||
// 8008928 - src4,5 - this change cause crash with t-a on anon class)
|
||||
|| (source.equals(srce.src4) || source.equals(srce.src5))
|
||||
) {
|
||||
System.out.println(testDef +
|
||||
"\n 8005681-skip repeated annotations on new,array,cast");
|
||||
return;
|
||||
}
|
||||
|
||||
println(testDef);
|
||||
// Create test source and File.
|
||||
@ -123,6 +150,7 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
if(hasInnerClass) {
|
||||
StringBuffer sb = new StringBuffer(classFile.getAbsolutePath());
|
||||
classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString());
|
||||
println("classfile: " + classFile.getAbsolutePath());
|
||||
}
|
||||
ClassFile cf = ClassFile.read(classFile);
|
||||
|
||||
@ -130,10 +158,16 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
test(cf);
|
||||
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f);
|
||||
if(source.local)
|
||||
test(cf, f, true);
|
||||
else
|
||||
test(cf,f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
if(source.local)
|
||||
test(cf, m, true);
|
||||
else
|
||||
test(cf, m);
|
||||
}
|
||||
countAnnotations();
|
||||
if (errors > 0) {
|
||||
@ -149,7 +183,7 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
//
|
||||
String sourceString(String testname, String retentn, String annot2,
|
||||
Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
|
||||
int src) {
|
||||
srce src) {
|
||||
|
||||
String As = "@A", Bs = "@B", Ds = "@D";
|
||||
if(Arepeats) As = "@A @A";
|
||||
@ -198,7 +232,7 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
|
||||
// Test case sources with sample generated source
|
||||
switch(src) {
|
||||
case 3: // (repeating) type annotations on field in method body
|
||||
case src1: // (repeating) type annotations on field in method body
|
||||
/*
|
||||
* class Test1 {
|
||||
* Test1(){}
|
||||
@ -210,18 +244,19 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
* }}
|
||||
*/
|
||||
source = new String(
|
||||
"class " + testname + " {\n" +
|
||||
"" + testname +"(){} \n" +
|
||||
"// type usage in method body \n" +
|
||||
"String test("+testname+" this, " +
|
||||
"String param, String ... vararg) { \n" +
|
||||
" _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" +
|
||||
" return (_As_ _Bs_ String) null; \n" +
|
||||
"} \n" +
|
||||
"} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
break;
|
||||
case 8: // (repeating) annotations on type parameters, bounds and type arguments in new statement.
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + " {\n" +
|
||||
"" + testname +"(){} \n" +
|
||||
"// type usage in method body \n" +
|
||||
"String test("+testname+" this, " +
|
||||
"String param, String ... vararg) { \n" +
|
||||
" _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" +
|
||||
" return (_As_ _Bs_ String) null; \n" +
|
||||
"} \n" +
|
||||
"} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
break;
|
||||
case src2: // (repeating) annotations on type parameters, bounds and type arguments in new statement.
|
||||
/*
|
||||
* class Test2<T extends Object> {
|
||||
* Map<List<String>, Integer> map =
|
||||
@ -232,17 +267,17 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating) annotations on type parameters, bounds and type arguments. \n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" +
|
||||
" Map<List<String>, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" +
|
||||
" String test(" + testname + "<T> this) { return null;}\n" +
|
||||
" <T> String genericMethod(T t) { return null; }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
break;
|
||||
case 9: // (repeating)annotations on type parameters of class, method return value in method.
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + "<T extends Object> {\n" +
|
||||
" Map<List<String>, Integer> map =\n" +
|
||||
" new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" +
|
||||
" Map<List<String>, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" +
|
||||
" String test(" + testname + "<T> this) { return null;}\n" +
|
||||
" <T> String genericMethod(T t) { return null; }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
break;
|
||||
case src3: // (repeating)annotations on type parameters of class, method return value in method.
|
||||
/*
|
||||
* class Test3{
|
||||
* <E extends Comparable> Map<List<E>, E > foo(E e) {
|
||||
@ -258,24 +293,72 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper {
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// (repeating)annotations on type parameters of class, method return value in method. \n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
|
||||
" class maptest <E> {\n" + // inner class $1maptest
|
||||
" Map<List<E>,E> getMap() { \n" +
|
||||
" Map<List<E>,E> Em = new HashMap<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E>();\n" +
|
||||
" return Em;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" return new maptest<E>().getMap();\n" +
|
||||
" }\n" +
|
||||
" Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1maptest";
|
||||
break;
|
||||
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
|
||||
" class maptest <E> {\n" + // inner class $1maptest
|
||||
" Map<List<E>,E> getMap() { \n" +
|
||||
" Map<List<E>,E> Em = new HashMap<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E>();\n" +
|
||||
" return Em;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" return new maptest<E>().getMap();\n" +
|
||||
" }\n" +
|
||||
" Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1maptest";
|
||||
break;
|
||||
case src4: // (repeating)annotations on field in anonymous class
|
||||
/*
|
||||
* class Test95{
|
||||
* void mtest( Test95 t){ }
|
||||
* public void test() {
|
||||
* mtest( new Test95() {
|
||||
* @A @A @B @B String data2 = "test";
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" void mtest( "+ testname + " t){ }\n" +
|
||||
" public void test() {\n" +
|
||||
" mtest( new "+ testname + "() {\n" +
|
||||
" _As_ _Bs_ String data2 = \"test\";\n" +
|
||||
" });\n" +
|
||||
" }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1";
|
||||
break;
|
||||
case src5: // (repeating)annotations on method in anonymous class
|
||||
/*
|
||||
* class Test120{
|
||||
* void mtest( Test120 t){ }
|
||||
* public void test() {
|
||||
* mtest( new Test120() {
|
||||
* @A @B @A @B String m2(){return null;};
|
||||
* });
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" void mtest( "+ testname + " t){ }\n" +
|
||||
" public void test() {\n" +
|
||||
" mtest( new "+ testname + "() {\n" +
|
||||
" _As_ _Bs_ String m2(){return null;};\n" +
|
||||
" });\n" +
|
||||
" }\n" +
|
||||
"}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n\n";
|
||||
hasInnerClass=true;
|
||||
innerClassname="$1";
|
||||
break;
|
||||
}
|
||||
return imports + source;
|
||||
}
|
||||
|
@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8005085 8005681 8008769 8010015
|
||||
* @summary Check (repeating)type annotations on lambda usage.
|
||||
* @run main CombinationsTargetTest3
|
||||
*/
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
|
||||
public class CombinationsTargetTest3 extends ClassfileTestHelper {
|
||||
|
||||
// Helps identify test case in event of failure.
|
||||
int testcount = 0;
|
||||
|
||||
// Known failure cases due to open bugs.
|
||||
Vector<String> skippedTests = new Vector<>();
|
||||
void printSkips() {
|
||||
if(!skippedTests.isEmpty()) {
|
||||
println(skippedTests.size() + " tests were skipped:");
|
||||
for(String t : skippedTests)
|
||||
println(" " + t);
|
||||
}
|
||||
}
|
||||
|
||||
// Test case descriptions and expected annotation counts.
|
||||
enum srce {
|
||||
src1("type annotations on lambda expression as method arg.",4,0),
|
||||
src2("type annotations on new in single line lambda expression",2,0),
|
||||
src3("type annotations in lambda expression code block",4,0),
|
||||
src4("type annotations in code block with recursion,cast",2,0),
|
||||
src5("type annotations in lambda expression code block",4,0),
|
||||
src6("type annotations on type parm in method reference",4,0),
|
||||
src7("type annotations on inner class field of lambda expression",2,2),
|
||||
src8("type annotations in inner class of lambda expression",4,2),
|
||||
src9("type annotations on static method of interface",4,2);
|
||||
|
||||
String description;
|
||||
// Expected annotation counts are same for Vis or Invis, but which one
|
||||
// depends on retention type.
|
||||
Integer[] exp = { 0, 0 };
|
||||
|
||||
// If class to test is inner class, this may be set in SourceString()
|
||||
String innerClassname = null ;
|
||||
|
||||
// If class to test is not main or inner class; set in sourceString()
|
||||
String altClassName = null;
|
||||
|
||||
srce(String desc, int e1, int e2) {
|
||||
description = this + ": " +desc;
|
||||
exp[0]=e1;
|
||||
exp[1]=e2;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for RuntimeInvisible or RuntimeVisible annotations.
|
||||
String[] RType={"CLASS", "RUNTIME"};
|
||||
|
||||
// This can be a compile only test.
|
||||
static boolean compileonly=false;
|
||||
|
||||
// Collect failure for end of test report()
|
||||
Vector<String> vFailures = new Vector<>();
|
||||
|
||||
// pass/fail determined after all tests have run.
|
||||
void report() {
|
||||
if(vFailures.isEmpty()) {
|
||||
printSkips();
|
||||
println("PASS");
|
||||
} else {
|
||||
System.err.println("FAILED: There were failures:");
|
||||
for(String f : vFailures)
|
||||
System.err.println(f);
|
||||
throw new RuntimeException("There were failures. See test log.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if(args.length>0 && args[0].compareTo("compileonly")==0)
|
||||
compileonly=true;
|
||||
new CombinationsTargetTest3().run();
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
// Determines which repeat and order in source(ABMix).
|
||||
Boolean As= false, BDs=true, ABMix=false;
|
||||
int testrun=0;
|
||||
// A repeats and/or B/D repeats, ABMix for order of As and Bs.
|
||||
Boolean [][] bRepeat = new Boolean[][]{{false,false,false}, //no repeats
|
||||
{true,false,false}, //repeat @A
|
||||
{false,true,false}, //repeat @B
|
||||
{true,true,false}, //repeat both
|
||||
{false,false,true} //repeat mix
|
||||
};
|
||||
// Added ElementType's. All set; not permuted (so far) for this test
|
||||
String et = "TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE";
|
||||
|
||||
// test loop
|
||||
for(Boolean[] bCombo : bRepeat) {
|
||||
As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
|
||||
for(srce src : srce.values())
|
||||
for( String rtype : RType ) {
|
||||
switch( rtype ) {
|
||||
case "RUNTIME":
|
||||
test(0,src.exp[0],0,src.exp[1],As, BDs, ABMix,
|
||||
"RUNTIME", et, ++testrun, src);
|
||||
break;
|
||||
case "CLASS":
|
||||
test(src.exp[0],0,src.exp[1],0,As, BDs, ABMix,
|
||||
"CLASS", et, ++testrun, src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
report();
|
||||
}
|
||||
|
||||
// Filter out skipped cases, compile, pass class file to test method,
|
||||
// count annotations and asses results.
|
||||
public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
|
||||
Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
|
||||
Integer N, srce source) throws Exception {
|
||||
++testcount;
|
||||
expected_tvisibles = tvis;
|
||||
expected_tinvisibles = tinv;
|
||||
expected_visibles = vis;
|
||||
expected_invisibles = inv;
|
||||
File testFile = null;
|
||||
String tname="Test" + N.toString();
|
||||
String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
|
||||
", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
|
||||
", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
|
||||
", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
|
||||
et2 + ", src=" + source;
|
||||
|
||||
// Skip failing cases with bug ID's
|
||||
if ((source.equals(srce.src2) || source.equals(srce.src4) ||
|
||||
source.equals(srce.src5)) &&
|
||||
(ABmix || (Arepeats && BDrepeats))) {
|
||||
skippedTests.add(testDef +
|
||||
"\n--8005681 repeated type-annotations on new/cast/array in" +
|
||||
" inner class in lambda expression.");
|
||||
return;
|
||||
}//8008769 Repeated type-annotations on type parm of local variable
|
||||
else if (source.equals(srce.src6) &&
|
||||
(ABmix || (Arepeats && BDrepeats))) {
|
||||
skippedTests.add(testDef + "\n--8008769 Repeated " +
|
||||
"type-annotations on type parm of local variable");
|
||||
return;
|
||||
}
|
||||
|
||||
println(testDef);
|
||||
// Create test source and File.
|
||||
String sourceString = sourceString(tname, rtn, et2, Arepeats,
|
||||
BDrepeats, ABmix, source);
|
||||
testFile = writeTestFile(tname+".java", sourceString);
|
||||
// Compile test source and read classfile.
|
||||
File classFile = null;
|
||||
try {
|
||||
classFile = compile(testFile);
|
||||
System.out.println("pass compile: " + tname + ".java");
|
||||
} catch (Error err) {
|
||||
System.err.println("fail compile. Source:\n" + sourceString);
|
||||
throw err;
|
||||
}
|
||||
if(!compileonly) {
|
||||
//check if innerClassname is set
|
||||
String classdir = classFile.getAbsolutePath();
|
||||
if(source.innerClassname != null) {
|
||||
StringBuffer sb = new StringBuffer(classdir);
|
||||
classFile=new File(sb.insert(sb.lastIndexOf(".class"),
|
||||
source.innerClassname).toString());
|
||||
source.innerClassname=null;
|
||||
} else if (source.altClassName != null) {
|
||||
classdir = classdir.substring(0,classdir.lastIndexOf("Test"));
|
||||
classFile=new File(classdir.concat(source.altClassName));
|
||||
source.innerClassname=null;
|
||||
}
|
||||
ClassFile cf = ClassFile.read(classFile);
|
||||
|
||||
println("Testing classfile: " + cf.getName());
|
||||
//Test class,fields and method counts.
|
||||
test(cf);
|
||||
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f);
|
||||
test(cf, f, true);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations(); // sets errors=0 before counting.
|
||||
if (errors > 0) {
|
||||
System.err.println( testDef );
|
||||
System.err.println( "Source:\n" + sourceString );
|
||||
vFailures.add(testDef);
|
||||
}
|
||||
}
|
||||
if(errors==0) println("Pass"); println("");
|
||||
}
|
||||
|
||||
/*
|
||||
* Source definitions for test cases.
|
||||
* To add a test:
|
||||
* Add enum to srce(near top of file) with expected annotation counts.
|
||||
* Add source defintion below.
|
||||
*/
|
||||
String sourceString(String testname, String retentn, String annot2,
|
||||
Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
|
||||
srce src) {
|
||||
|
||||
String As = "@A", Bs = "@B", Ds = "@D";
|
||||
if(Arepeats) As = "@A @A";
|
||||
if(BDrepeats) {
|
||||
Bs = "@B @B";
|
||||
Ds = "@D @D";
|
||||
}
|
||||
if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
|
||||
|
||||
// Source to check for TYPE_USE and TYPE_PARAMETER annotations.
|
||||
// Source base (annotations) is same for all test cases.
|
||||
String source = new String();
|
||||
String imports = new String("import java.lang.annotation.*; \n" +
|
||||
"import static java.lang.annotation.RetentionPolicy.*; \n" +
|
||||
"import static java.lang.annotation.ElementType.*; \n" +
|
||||
"import java.util.List; \n" +
|
||||
"import java.util.ArrayList;\n\n");
|
||||
|
||||
String sourceBase = new String(
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( AC.class ) @interface A { }\n" +
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface AC { A[] value(); } \n" +
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( BC.class ) @interface B { }\n" +
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface BC { B[] value(); } \n" +
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @Repeatable(DC.class) @interface D { }\n" +
|
||||
"@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @interface DC { D[] value(); }");
|
||||
|
||||
// Test case sources with sample generated source
|
||||
switch(src) {
|
||||
case src1: //(repeating) type annotations on lambda expressions.
|
||||
/*
|
||||
* class Test1 {
|
||||
* Test1(){}
|
||||
* interface MapFun<T,R> { R m( T n); }
|
||||
* void meth( MapFun<String,Integer> mf ) {
|
||||
* assert( mf.m("four") == 4);
|
||||
* }
|
||||
* void test(Integer i) {
|
||||
* // lambda expression as method arg
|
||||
* meth( (@A @B String s) -> { @A @B Integer len = s.length(); return len; } );
|
||||
* }}
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + " {\n" +
|
||||
" " + testname +"(){} \n" +
|
||||
" interface MapFun<T,R> { R m( T n); }\n\n" +
|
||||
" void meth( MapFun<String,Integer> mf ) {\n" +
|
||||
" assert( mf.m(\"four\") == 4);\n" +
|
||||
" }\n\n" +
|
||||
" void test(Integer i) {\n" +
|
||||
" // lambda expression as method arg\n" +
|
||||
" meth( (_As_ _Bs_ String s) -> { _As_ _Bs_ Integer len = s.length(); return len; } );\n" +
|
||||
"}}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case src2: //(repeating) type annotations on new in single line lambda expression.
|
||||
/*
|
||||
* //case2: (repeating) type annotations on new in single lambda expressions.
|
||||
* class Test2{
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<Integer, String> its;
|
||||
* void test(Integer i) {
|
||||
* its = a -> "~"+new @A @B Integer(a).toString()+"~";
|
||||
* System.out.println("in: " + i + " out: " + its.m(i));
|
||||
* }}
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class " + testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<Integer, String> its;\n" +
|
||||
" void test(Integer i) {\n" +
|
||||
" its = a -> \"~\"+new _As_ _Bs_ Integer(a).toString()+\"~\";\n" +
|
||||
" System.out.println(\"in: \" + i + \" out: \" + its.m(i));\n" +
|
||||
" }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case src3: //(repeating) type annotations in lambda expression code block.
|
||||
/*
|
||||
* class Test183{
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<List<Integer>, String> iLs;
|
||||
* void testm(Integer i) {
|
||||
* iLs = l -> { @A @B @A @B String ret = new String();
|
||||
* for( @A @B @A @B Integer i2 : l)
|
||||
* ret=ret.concat(i2.toString() + " ");
|
||||
* return ret; };
|
||||
* List<Integer> li = new ArrayList<>();
|
||||
* for(int j=0; j<i; j++) li.add(j);
|
||||
* System.out.println(iLs.m(li) );
|
||||
* }}
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<List<Integer>, String> iLs;\n" +
|
||||
" void testm(Integer i) {\n" +
|
||||
" iLs = l -> { _As_ _Bs_ String ret = new String();\n" +
|
||||
" for( _As_ _Bs_ Integer i2 : l)\n" +
|
||||
" ret=ret.concat(i2.toString() + \" \");\n" +
|
||||
" return ret; };\n" +
|
||||
" List<Integer> li = new ArrayList<>();\n" +
|
||||
" for(int j=0; j<i; j++) li.add(j);\n" +
|
||||
" System.out.println(iLs.m(li) );\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
" public static void main(String... args) {new " + testname + "().testm(5); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case src4: //(repeating) type annotations in code block with recursion,cast
|
||||
/*
|
||||
* class Test194{
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<Integer, Double> nf;
|
||||
* void testm(Integer i) {
|
||||
* nf = j -> { return j == 1 ? 1.0 : (@A @B @A @B Double)(nf.m(j-1) * j); };
|
||||
* System.out.println( "nf.m(" + i + "): " + nf.m(i));
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<Integer, Double> nf;\n" +
|
||||
" void testm(Integer i) {\n" +
|
||||
" nf = j -> { return j == 1 ? 1.0 : (_As_ _Bs_ Double)(nf.m(j-1) * j); };\n" +
|
||||
" System.out.println( \"nf.m(\" + i + \"): \" + nf.m(i));\n" +
|
||||
" }\n" +
|
||||
" public static void main(String... args) {new " + testname + "().testm(5); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case src5: //(repeating) type annotations in lambda expression code block.
|
||||
/*
|
||||
* class Test180 {
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<Integer,List<Integer>> iLi;
|
||||
* void test(Integer i) {
|
||||
* // type parameter use.
|
||||
* iLi = n -> { List<@A @B @A @B Integer> LI = new ArrayList<@A @B @A @B Integer>(n);
|
||||
* for(int nn = n; nn >=0; nn--) LI.add(nn);
|
||||
* return LI; };
|
||||
* List<Integer> li = iLi.m(i);
|
||||
* for(Integer k : li) System.out.print(k);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<Integer,List<Integer>> iLi;\n" +
|
||||
" void test(Integer i) {\n" +
|
||||
" // type parameter use.\n" +
|
||||
" iLi = n -> { List<_As_ _Bs_ Integer> LI = new ArrayList<_As_ _Bs_ Integer>(n);\n" +
|
||||
" for(int nn = n; nn >=0; nn--) LI.add(nn);\n" +
|
||||
" return LI; };\n" +
|
||||
" List<Integer> li = iLi.m(i);\n" +
|
||||
" for(Integer k : li) System.out.print(k);\n" +
|
||||
"}\n" +
|
||||
" public static void main(String... args) {new " + testname + "().test(5); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
|
||||
"\n";
|
||||
break;
|
||||
case src6: //(repeating) type annotations on type parm in method reference.
|
||||
/*
|
||||
* class Test240{
|
||||
* interface PrintString { void print(String s); }
|
||||
* public void printArray(Object[] oa, PrintString ps) {
|
||||
* for(Object o : oa ) ps.print(o.toString());
|
||||
* }
|
||||
* public void test() {
|
||||
* Integer[] intarray = {1,2,3,4,5};
|
||||
* printArray(intarray, @A @B @A @B TPrint::<@A @B @A @B String>print);
|
||||
* }
|
||||
* }
|
||||
* class TPrint {
|
||||
* public static <T> void print(T t) { System.out.println( t.toString()); }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface PrintString { void print(String s); }\n" +
|
||||
" public void printArray(Object[] oa, PrintString ps) {\n" +
|
||||
" for(Object o : oa ) ps.print(o.toString());\n" +
|
||||
" }\n" +
|
||||
" public void test() {\n" +
|
||||
" Integer[] intarray = {1,2,3,4,5};\n" +
|
||||
" printArray(intarray, _As_ _Bs_ TPrint::<_As_ _Bs_ String>print);\n" +
|
||||
" }\n" +
|
||||
" public static void main(String... args) {new " + testname + "().test(); }\n" +
|
||||
"}\n\n" +
|
||||
"class TPrint {\n" +
|
||||
" public static <T> void print(T t) { System.out.println( t.toString()); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
break;
|
||||
case src7: //(repeating)type annotations in inner class of lambda expression.
|
||||
/*
|
||||
* class Test2{
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<Class<?>,String> cs;
|
||||
* void test() {
|
||||
* cs = c -> {
|
||||
* class innerClass {
|
||||
* @A @B Class<?> icc = null;
|
||||
* String getString() { return icc.toString(); }
|
||||
* }
|
||||
* return new innerClass().getString();
|
||||
* };
|
||||
* System.out.println("cs.m : " + cs.m(Integer.class));
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<Class<?>,String> cs;\n" +
|
||||
" void test() {\n" +
|
||||
" cs = c -> {\n" +
|
||||
" class innerClass {\n" +
|
||||
" _As_ _Bs_ Class<?> icc = null;\n" +
|
||||
" innerClass(Class<?> _c) { icc = _c; }\n" +
|
||||
" String getString() { return icc.toString(); }\n" +
|
||||
" }\n" +
|
||||
" return new innerClass(c).getString();\n" +
|
||||
" };\n" +
|
||||
" System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public static void main(String... args) {new " + testname + "().test(); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
src.innerClassname="$1innerClass";
|
||||
break;
|
||||
case src8: //(repeating)type annotations in inner class of lambda expression.
|
||||
/*
|
||||
* class Test2{
|
||||
* interface MapFun<T, R> { R m( T n); }
|
||||
* MapFun<Class<?>,String> cs;
|
||||
* void test() {
|
||||
* cs = c -> {
|
||||
* class innerClass {
|
||||
* Class<?> icc;
|
||||
* innerClass(@A @B Class<?> _c) { icc = _c; }
|
||||
* @A @B String getString() { return icc.toString(); }
|
||||
* }
|
||||
* return new innerClass(c).getString();
|
||||
* };
|
||||
* System.out.println("cs.m : " + cs.m(Integer.class));
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface MapFun<T, R> { R m( T n); }\n" +
|
||||
" MapFun<Class<?>,String> cs;\n" +
|
||||
" void test() {\n" +
|
||||
" cs = c -> {\n" +
|
||||
" class innerClass {\n" +
|
||||
" Class<?> icc;\n" +
|
||||
" innerClass(_As_ _Bs_ Class<?> _c) { icc = _c; }\n" +
|
||||
" _As_ _Bs_ String getString() { return icc.toString(); }\n" +
|
||||
" }\n" +
|
||||
" return new innerClass(c).getString();\n" +
|
||||
" };\n" +
|
||||
" System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public static void main(String... args) {new " + testname + "().test(); }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
src.innerClassname="$1innerClass";
|
||||
break;
|
||||
case src9: //(repeating)type annotations on static method of interface
|
||||
/*
|
||||
* class Test90{
|
||||
* interface I {
|
||||
* static @A @B @A @B String m() { @A @B @A @B String ret = "I.m"; return ret; }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
source = new String( source +
|
||||
"// " + src.description + "\n" +
|
||||
"class "+ testname + "{\n" +
|
||||
" interface I { \n" +
|
||||
" static _As_ _Bs_ String m() { _As_ _Bs_ String ret = \"I.m\"; return ret; }\n" +
|
||||
" }\n" +
|
||||
"}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
|
||||
"\n";
|
||||
src.innerClassname="$I";
|
||||
break;
|
||||
}
|
||||
return imports + source;
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ public class DeadCode extends ClassfileTestHelper {
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,7 @@ public class NewTypeArguments extends ClassfileTestHelper{
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8008762
|
||||
* @ignore 8013409: test failures for type annotations
|
||||
* @summary Type annotation on inner class in anonymous class
|
||||
* shows up as regular annotation
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
public class T8008762 extends ClassfileTestHelper{
|
||||
public static void main(String[] args) throws Exception {
|
||||
new T8008762().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
expected_tinvisibles = 0;
|
||||
expected_tvisibles = 4;
|
||||
|
||||
ClassFile cf = getClassFile("T8008762$Test$1$InnerAnon.class");
|
||||
test(cf);
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f, false);
|
||||
}
|
||||
for (Method m : cf.methods) {
|
||||
test(cf, m, false);
|
||||
}
|
||||
countAnnotations();
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors found");
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
|
||||
/*********************** Test class *************************/
|
||||
static class Test {
|
||||
Object mtest( Test t){ return null; }
|
||||
public void test() {
|
||||
mtest( new Test() {
|
||||
class InnerAnon { // Test1$1$InnerAnon.class
|
||||
@A @B String ai_data = null;
|
||||
@A @B String ai_m(){ return null; };
|
||||
}
|
||||
InnerAnon IA = new InnerAnon();
|
||||
});
|
||||
}
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @interface A { }
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @interface B { }
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @summary Repeated type-annotations on type parm of local variable
|
||||
* are not written to classfile.
|
||||
* @bug 8008769
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
public class T8008769 extends ClassfileTestHelper{
|
||||
public static void main(String[] args) throws Exception {
|
||||
new T8008769().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
expected_tvisibles = 4;
|
||||
ClassFile cf = getClassFile("T8008769$Test.class");
|
||||
for (Method m : cf.methods) {
|
||||
test(cf, m, true);
|
||||
}
|
||||
countAnnotations();
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors found");
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
|
||||
/*********************** Test class *************************/
|
||||
static class Test<T> {
|
||||
public void test() {
|
||||
Test<@A @B String> t0 = new Test<>(); // 2 ok
|
||||
Test<@B @B String> t1 = new Test<>(); // 1 missing
|
||||
Test<@A @A @A String> t2 = new Test<>(); // 1 missing
|
||||
}
|
||||
}
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @Repeatable( AC.class ) @interface A { }
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @Repeatable( BC.class ) @interface B { }
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @interface AC { A[] value(); }
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @interface BC { B[] value(); }
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Wrong classfile attribution in inner class of lambda expression.
|
||||
* @bug 8010015
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
/*
|
||||
* A type-annotations on a field in an inner class not in a lambda expression
|
||||
* results in RuntimeTypeAnnotations_attibute and RuntimeAnnotations_attribute.
|
||||
* On a field in an innner class in a lambda expression, it leaves off the
|
||||
* RuntimeAnnotations_attribute.
|
||||
*/
|
||||
public class T8010015 extends ClassfileTestHelper{
|
||||
public static void main(String[] args) throws Exception {
|
||||
new T8010015().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
expected_tvisibles = 1;
|
||||
expected_visibles = 1;
|
||||
ClassFile cf = getClassFile("T8010015$Test$1innerClass.class");
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f);
|
||||
}
|
||||
countAnnotations();
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors found");
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
|
||||
/*********************** Test class **************************/
|
||||
interface MapFun<T, R> { R m( T n); }
|
||||
static class Test {
|
||||
MapFun<Class<?>,String> cs;
|
||||
void test() {
|
||||
cs = c -> {
|
||||
class innerClass {
|
||||
@A Class<?> icc = null;
|
||||
innerClass(Class<?> _c) { icc = _c; }
|
||||
String getString() { return icc.toString(); }
|
||||
}
|
||||
return new innerClass(c).getString();
|
||||
};
|
||||
System.out.println("cs.m : " + cs.m(Integer.class));
|
||||
}
|
||||
|
||||
public static void main(String... args) {new Test().test(); }
|
||||
}
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,FIELD}) @interface A { }
|
||||
}
|
@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8005681
|
||||
* @summary Repeated annotations on new,array,cast.
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
public class TestNewCastArray {
|
||||
int errors = 0;
|
||||
List<String> failedTests = new java.util.LinkedList<>();
|
||||
|
||||
// 'b' tests fail with only even numbers of annotations (8005681).
|
||||
String[] testclasses = {"Test1",
|
||||
"Test2a", "Test3a", "Test4a", "Test5a",
|
||||
"Test2b", "Test3b", "Test4b", "Test5b"
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestNewCastArray().run();
|
||||
}
|
||||
|
||||
void check(String testcase, int expected, int actual) {
|
||||
String res = testcase + ": (expected) " + expected + ", " + actual + " (actual): ";
|
||||
if(expected == actual) {
|
||||
res = res.concat("PASS");
|
||||
} else {
|
||||
errors++;
|
||||
res = res.concat("FAIL");
|
||||
failedTests.add(res);
|
||||
}
|
||||
System.out.println(res);
|
||||
}
|
||||
|
||||
void report() {
|
||||
if(errors!=0) {
|
||||
System.err.println("Failed tests: " + errors +
|
||||
"\nfailed test cases:\n");
|
||||
for(String t: failedTests)
|
||||
System.err.println(" " + t);
|
||||
throw new RuntimeException("FAIL: There were test failures.");
|
||||
} else
|
||||
System.out.println("PASS");
|
||||
}
|
||||
|
||||
void test(String clazz, String ttype, ClassFile cf, Method m, Field f,
|
||||
String name, boolean codeattr) {
|
||||
int actual = 0;
|
||||
int expected = 0, cexpected = 0;
|
||||
int index = 0;
|
||||
String memberName = null;
|
||||
Attribute attr = null;
|
||||
Code_attribute cAttr = null;
|
||||
String testcase = "undefined";
|
||||
try {
|
||||
switch(ttype) {
|
||||
case "METHOD":
|
||||
index = m.attributes.getIndex(cf.constant_pool, name);
|
||||
memberName = m.getName(cf.constant_pool);
|
||||
if(index != -1)
|
||||
attr = m.attributes.get(index);
|
||||
break;
|
||||
case "MCODE":
|
||||
memberName = m.getName(cf.constant_pool);
|
||||
//fetch index of and code attribute and annotations from code attribute.
|
||||
index = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
|
||||
if(index!= -1) {
|
||||
attr = m.attributes.get(index);
|
||||
assert attr instanceof Code_attribute;
|
||||
cAttr = (Code_attribute)attr;
|
||||
index = cAttr.attributes.getIndex(cf.constant_pool, name);
|
||||
if(index!= -1)
|
||||
attr = cAttr.attributes.get(index);
|
||||
}
|
||||
break;
|
||||
case "FIELD":
|
||||
index = f.attributes.getIndex(cf.constant_pool, name);
|
||||
memberName = f.getName(cf.constant_pool);
|
||||
if(index != -1)
|
||||
attr = f.attributes.get(index);
|
||||
break;
|
||||
case "CODE":
|
||||
memberName = f.getName(cf.constant_pool);
|
||||
//fetch index of and code attribute and annotations from code attribute.
|
||||
index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code);
|
||||
if(index!= -1) {
|
||||
attr = cf.attributes.get(index);
|
||||
assert attr instanceof Code_attribute;
|
||||
cAttr = (Code_attribute)attr;
|
||||
index = cAttr.attributes.getIndex(cf.constant_pool, name);
|
||||
if(index!= -1)
|
||||
attr = cAttr.attributes.get(index);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch(ConstantPoolException cpe) { cpe.printStackTrace(); }
|
||||
testcase = clazz+" "+ttype + ": " + memberName + ", " + name;
|
||||
if(index != -1) {
|
||||
//count RuntimeTypeAnnotations
|
||||
assert attr instanceof RuntimeTypeAnnotations_attribute;
|
||||
RuntimeTypeAnnotations_attribute tAttr =
|
||||
(RuntimeTypeAnnotations_attribute)attr;
|
||||
actual += tAttr.annotations.length;
|
||||
}
|
||||
if(memberName.compareTo("<init>")==0) memberName=clazz+memberName;
|
||||
switch ( memberName ) {
|
||||
//METHOD:
|
||||
case "Test1<init>": expected=0; break;
|
||||
case "testr22_22": expected=4; break;
|
||||
case "testr11_11": expected=4; break;
|
||||
case "testr12_21": expected=4; break;
|
||||
case "testr20_02": expected=2; break;
|
||||
|
||||
case "Test2a<init>": cexpected=0; break;
|
||||
case "test00_00_11_11": cexpected=4; break;
|
||||
case "test21_12_21_12": cexpected=8; break;
|
||||
case "test_new1": cexpected=2; break;
|
||||
case "test_new2": cexpected=2; break;
|
||||
case "test_cast1": cexpected=2; break;
|
||||
case "test_cast2": cexpected=2; break;
|
||||
|
||||
case "Test2b<init>": cexpected=0; break;
|
||||
case "test20_02_20_02": cexpected=4; break;
|
||||
case "test22_22_22_22": cexpected=8; break;
|
||||
case "test_new3": cexpected=1; break;
|
||||
case "test_new4": cexpected=1; break;
|
||||
case "test_new5": cexpected=2; break;
|
||||
case "test_cast3": cexpected=1; break;
|
||||
case "test_cast4": cexpected=2; break;
|
||||
|
||||
case "Test3a<init>": cexpected=10; break;
|
||||
case "SA_21_12c": cexpected = 0; break;
|
||||
case "SA_01_10c": expected = 0; break;
|
||||
case "SA_11_11c": expected = 0; break;
|
||||
|
||||
case "Test3b<init>": cexpected=6; break;
|
||||
case "SA_22_22c": cexpected = 0; break;
|
||||
case "SA_20_02c": cexpected = 0; break;
|
||||
|
||||
case "Test3c<init>": cexpected=8; break;
|
||||
case "SA_10_10": cexpected = 0; break;
|
||||
case "SA_10_01": cexpected = 0; break;
|
||||
case "SA_21_12": cexpected = 0; break;
|
||||
|
||||
case "Test3d<init>": cexpected=6; break;
|
||||
case "SA_20_02": cexpected = 0; break;
|
||||
case "SA_22_22": cexpected = 0; break;
|
||||
|
||||
case "Test4a<init>": cexpected=4; break;
|
||||
case "nS_21": cexpected = 0; break;
|
||||
case "nS_12": cexpected = 0; break;
|
||||
|
||||
case "Test4b<init>": cexpected=4; break;
|
||||
case "nS20": cexpected = 0; break;
|
||||
case "nS02": cexpected = 0; break;
|
||||
case "nS22": cexpected = 0; break;
|
||||
|
||||
case "Test5a<init>": cexpected=4; break;
|
||||
case "ci11": expected = 0; break;
|
||||
case "ci21": expected = 0; break;
|
||||
|
||||
case "Test5b<init>": cexpected=3; break;
|
||||
case "ci2": expected = 0; break;
|
||||
case "ci22": expected = 0; break;
|
||||
|
||||
default: expected = 0; break;
|
||||
}
|
||||
if(codeattr)
|
||||
check(testcase, cexpected, actual);
|
||||
else
|
||||
check(testcase, expected, actual);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
ClassFile cf = null;
|
||||
InputStream in = null;
|
||||
for( String clazz : testclasses) {
|
||||
String testclazz = "TestNewCastArray$" + clazz + ".class";
|
||||
System.out.println("Testing " + testclazz);
|
||||
try {
|
||||
in = getClass().getResource(testclazz).openStream();
|
||||
cf = ClassFile.read(in);
|
||||
in.close();
|
||||
} catch(Exception e) { e.printStackTrace(); }
|
||||
|
||||
if(clazz.startsWith("Test1")) {
|
||||
for (Field f: cf.fields)
|
||||
test(clazz, "FIELD", cf, null, f, Attribute.RuntimeVisibleTypeAnnotations, false);
|
||||
for (Method m: cf.methods)
|
||||
test(clazz, "METHOD", cf, m, null, Attribute.RuntimeVisibleTypeAnnotations, false);
|
||||
} else {
|
||||
for (Field f: cf.fields)
|
||||
test(clazz, "CODE", cf, null, f, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
for (Method m: cf.methods)
|
||||
test(clazz, "MCODE", cf, m, null, Attribute.RuntimeVisibleTypeAnnotations, true);
|
||||
}
|
||||
}
|
||||
report();
|
||||
}
|
||||
|
||||
//////// test class //////////////////////////
|
||||
// "Test1" not in code attribute.
|
||||
// on arrays on and in method return
|
||||
static class Test1 {
|
||||
Test1(){}
|
||||
// OK expect 5, got 5
|
||||
String @A @A @B @B[] @A @A @B @B [] testr22_22(Test1 this, String param, String ... vararg) {
|
||||
String [][] sarray = new String [2][2];
|
||||
return sarray;
|
||||
}
|
||||
// OK expect 5, got 5
|
||||
String @A @B [] @A @B [] testr11_11(Test1 this, String param, String ... vararg) {
|
||||
String [][] sarray = new String [2][2];
|
||||
return sarray;
|
||||
}
|
||||
// OK expect 5, got 5
|
||||
String @A @B @B []@B @B @A[] testr12_21(Test1 this, String param, String ... vararg) {
|
||||
String [][] sarray = new String [2][2];
|
||||
return sarray;
|
||||
}
|
||||
// OK expect 3, got 3
|
||||
String @A @A [] @B @B [] testr20_02(Test1 this, String param, String ... vararg) {
|
||||
String [][] sarray = new String [2][2];
|
||||
return sarray;
|
||||
}
|
||||
}
|
||||
|
||||
// Inside method body (in method's code attribute)
|
||||
static class Test2a {
|
||||
Test2a(){}
|
||||
Object o = new Integer(1);
|
||||
// expect 4
|
||||
String[][] test00_00_11_11(Test2a this, String param, String ... vararg) {
|
||||
String [] [] sarray = new String @A @B[2] @A @B [2];
|
||||
return sarray;
|
||||
}
|
||||
|
||||
// expect 8
|
||||
String[][] test21_12_21_12(Test2a this, String param, String ... vararg) {
|
||||
String @A @A @B [] @A @B @B [] sarray = new String @A @A @B[2] @A @B @B [2];
|
||||
return sarray;
|
||||
}
|
||||
|
||||
void test_new1() { String nS_21 = new @A @A @B String("Hello"); }
|
||||
void test_new2() { String nS_12 = new @A @B @B String("Hello"); }
|
||||
void test_cast1() { String tcs11 = (@A @B String)o; }
|
||||
void test_cast2() { String tcs21 = (@A @A @B String)o; }
|
||||
}
|
||||
|
||||
static class Test2b {
|
||||
Test2b(){}
|
||||
Object o = new Integer(1);
|
||||
// expect 4
|
||||
String[][] test20_02_20_02(Test2b this, String param, String ... vararg) {
|
||||
String @A @A [] @B @B [] sarray = new String @A @A[2] @B @B [2];
|
||||
return sarray;
|
||||
}
|
||||
|
||||
// expect 8
|
||||
String[][] test22_22_22_22(Test2b this, String param, String ... vararg) {
|
||||
String @A @A @B @B [] @A @A @B @B [] sarray = new String @A @A @B @B [2] @A @A @B @B [2];
|
||||
return sarray;
|
||||
}
|
||||
|
||||
void test_new3() { String nS20 = new @A @A String("Hello"); }
|
||||
void test_new4() { String nS02 = new @B @B String("Hello"); }
|
||||
void test_new5() { String nS22 = new @A @A @B @B String("Hello"); }
|
||||
void test_cast3() { String tcs2 = (@A @A String)o; }
|
||||
void test_cast4() { String tcs22 = (@A @A @B @B String)o;}
|
||||
}
|
||||
|
||||
// array levels
|
||||
static class Test3a {
|
||||
Test3a(){}
|
||||
// expect 4+2+4=10
|
||||
String [][] SA_21_12c = new String @A @A @B [2] @A @B @B[2];
|
||||
String [][] SA_01_10c = new String @B [2] @A [2];
|
||||
String [][] SA_11_11c = new String @A @B [2] @A @B [2];
|
||||
}
|
||||
|
||||
static class Test3b {
|
||||
Test3b(){}
|
||||
// expect 4+2=6
|
||||
String [][] SA_22_22c = new String @A @A @B @B[2] @A @A @B @B[2];
|
||||
String [][] SA_20_02c = new String @A @A [2] @B @B[2];
|
||||
}
|
||||
static class Test3c {
|
||||
Test3c(){}
|
||||
// OK expect 4
|
||||
String @A [] @A[] SA_10_10 = new String [2][2];
|
||||
String @A [] @B[] SA_10_01 = new String [2][2];
|
||||
String @A @A @B[] @A @B @B [] SA_21_12 = new String [2][2];
|
||||
}
|
||||
|
||||
static class Test3d {
|
||||
Test3d(){}
|
||||
// OK expect 4
|
||||
String @A @A [] @B @B [] SA_20_02 = new String [2][2];
|
||||
String @A @A @B @B[] @A @A @B @B [] SA_22_22 = new String [2][2];
|
||||
}
|
||||
|
||||
// on new
|
||||
static class Test4a {
|
||||
Test4a(){}
|
||||
// expect 2+2=4
|
||||
String nS_21 = new @A @A @B String("Hello");
|
||||
String nS_12 = new @A @B @B String("Hello");
|
||||
}
|
||||
|
||||
static class Test4b {
|
||||
Test4b(){}
|
||||
// expect 1+1+2=4
|
||||
String nS20 = new @A @A String("Hello");
|
||||
String nS02 = new @B @B String("Hello");
|
||||
String nS22 = new @A @A @B @B String("Hello");
|
||||
}
|
||||
|
||||
// Cast expressions
|
||||
static class Test5a {
|
||||
Test5a(){}
|
||||
Object o = new Integer(1);
|
||||
// expect 2+2=4
|
||||
Integer ci11 = (@A @B Integer)o; // OK expect 3, got 3
|
||||
Integer ci21 = (@A @A @B Integer)o; // OK expect 3, got 3
|
||||
}
|
||||
|
||||
static class Test5b {
|
||||
Test5b(){}
|
||||
Object o = new Integer(1);
|
||||
// Cast expressions
|
||||
// expect 1+2=3
|
||||
Integer ci2 = (@A @A Integer)o; // FAIL expect 2, got 1
|
||||
Integer ci22 = (@A @A @B @B Integer)o; // FAIL expect 3, got 1
|
||||
}
|
||||
|
||||
@Retention(RUNTIME) @Target({TYPE_USE}) @Repeatable( AC.class ) @interface A { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE}) @Repeatable( BC.class ) @interface B { }
|
||||
@Retention(RUNTIME) @Target({FIELD}) @Repeatable( FC.class ) @interface F { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE}) @interface AC { A[] value(); }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE}) @interface BC { B[] value(); }
|
||||
@Retention(RUNTIME) @Target({FIELD}) @interface FC { F[] value(); }
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -50,7 +50,7 @@ public class TypeCasts extends ClassfileTestHelper{
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,7 @@ public class Wildcards extends ClassfileTestHelper {
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m);
|
||||
test(cf, m,false);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
@ -27,7 +27,7 @@
|
||||
* @summary Type annotations in a lazy constant need to be attributed
|
||||
* in the correct order.
|
||||
* @author Werner Dietl
|
||||
* @compile LazyConstantValue.java
|
||||
* @compile/ref=LazyConstantValue.out LazyConstantValue.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
@ -40,5 +40,9 @@ class ClassB {
|
||||
static final String[] lcv = new @TA String[0];
|
||||
}
|
||||
|
||||
class ClassC {
|
||||
static final Object o = (@TA Object) null;
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TA {}
|
||||
|
@ -1,11 +1,11 @@
|
||||
LintCast.java:15:21: compiler.warn.redundant.cast: java.lang.String
|
||||
LintCast.java:21:27: compiler.warn.redundant.cast: java.util.List<java.lang.String>
|
||||
LintCast.java:27:20: compiler.warn.redundant.cast: (@A :: int[])
|
||||
LintCast.java:27:20: compiler.warn.redundant.cast: int @A []
|
||||
LintCast.java:39:24: compiler.warn.redundant.cast: java.lang.String
|
||||
LintCast.java:40:26: compiler.warn.redundant.cast: java.lang.String
|
||||
LintCast.java:45:23: compiler.warn.redundant.cast: (@A :: java.lang.Object[])
|
||||
LintCast.java:45:23: compiler.warn.redundant.cast: java.lang.Object @A []
|
||||
LintCast.java:49:27: compiler.warn.redundant.cast: java.util.List<java.lang.String>
|
||||
LintCast.java:53:27: compiler.warn.redundant.cast: java.util.List<java.lang.String>
|
||||
LintCast.java:53:27: compiler.warn.redundant.cast: java.util.List<@A java.lang.String>
|
||||
LintCast.java:57:21: compiler.warn.redundant.cast: java.lang.Object
|
||||
LintCast.java:61:27: compiler.warn.redundant.cast: LintCast.Outer.Inner
|
||||
10 warnings
|
@ -6,7 +6,7 @@
|
||||
* @compile/fail/ref=StaticMethods.out -XDrawDiagnostics StaticMethods.java
|
||||
*/
|
||||
class StaticMethods {
|
||||
static void main(@A StaticMethods this) { }
|
||||
static void main(StaticMethods this) { }
|
||||
}
|
||||
|
||||
@interface A { }
|
||||
|
@ -1,2 +1,2 @@
|
||||
StaticMethods.java:9:37: compiler.err.annotation.type.not.applicable
|
||||
StaticMethods.java:9:34: compiler.err.non-static.cant.be.ref: kindname.variable, this
|
||||
1 error
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary type-annotation on array level in nested class results in NPE
|
||||
* @bug 8008751
|
||||
* @compile T8008751.java
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import java.util.List;
|
||||
|
||||
class T8008751 {
|
||||
Object mtest( T8008751 t){ return null; }
|
||||
public void test() {
|
||||
mtest( new T8008751() {
|
||||
class InnerAnon {
|
||||
@A("ok") String s = (@A("ok") String)( new @A("ok") Object());
|
||||
@A("ok") Object @A("NPE")[] [] ia_sa1 = null;
|
||||
}
|
||||
// If not instanciated, no crash.
|
||||
InnerAnon IA = new InnerAnon();
|
||||
});
|
||||
}
|
||||
}
|
||||
@Retention(RUNTIME) @Target(TYPE_USE) @interface A { String value(); }
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8009360
|
||||
* @summary AssertionError from type annotation on member of anonymous class
|
||||
* @compile T8009360.java
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
class Test1<T> {
|
||||
Object mtest( Test1<T> t){ return null; }
|
||||
public void test() {
|
||||
mtest( new Test1<T>() {
|
||||
@A String data1 = "test"; // ok
|
||||
@A @A String data2 = "test"; // ok
|
||||
@A @B String data3 = "test"; // was AssertionError
|
||||
@B @C String data4 = "test"; // was AssertionError
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Target({TYPE_USE,FIELD}) @Repeatable( AC.class) @interface A { }
|
||||
@Target({TYPE_USE,FIELD}) @interface AC { A[] value(); }
|
||||
@Target({TYPE_USE}) @interface B { }
|
||||
@Target({TYPE_USE, FIELD}) @interface C { }
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8011722
|
||||
* @summary AssertionError from type annotations on qualified type
|
||||
* @compile T8011722.java
|
||||
*/
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
public class T8011722 {
|
||||
class InnerException extends Exception { }
|
||||
void foo() throws @C T8011722.@C InnerException { }
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE) @interface C { }
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 1234567
|
||||
* @summary ensure that declaration annotations are not allowed on
|
||||
* new array expressions
|
||||
* @author Werner Dietl
|
||||
* @compile/fail/ref=DeclarationAnnotation.out -XDrawDiagnostics DeclarationAnnotation.java
|
||||
*/
|
||||
class DeclarationAnnotation {
|
||||
Object e1 = new @DA int[5];
|
||||
Object e2 = new @DA String[42];
|
||||
Object e3 = new @DA Object();
|
||||
|
||||
// The declaration annotation is only allowed for
|
||||
// an anonymous class creation.
|
||||
Object ok = new @DA Object() { };
|
||||
}
|
||||
|
||||
@interface DA { }
|
@ -0,0 +1,4 @@
|
||||
DeclarationAnnotation.java:10:21: compiler.err.annotation.type.not.applicable
|
||||
DeclarationAnnotation.java:11:21: compiler.err.annotation.type.not.applicable
|
||||
DeclarationAnnotation.java:12:21: compiler.err.annotation.type.not.applicable
|
||||
3 errors
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 1234567
|
||||
* @summary ensure that declaration annotations are not allowed on
|
||||
* method receiver types
|
||||
* @author Werner Dietl
|
||||
* @compile/fail/ref=DeclarationAnnotation.out -XDrawDiagnostics DeclarationAnnotation.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
class DeclarationAnnotation {
|
||||
void bad(@DA DeclarationAnnotation this) {}
|
||||
void good(@TA DeclarationAnnotation this) {}
|
||||
}
|
||||
|
||||
@interface DA { }
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TA { }
|
@ -0,0 +1,2 @@
|
||||
DeclarationAnnotation.java:14:14: compiler.err.annotation.type.not.applicable
|
||||
1 error
|
@ -28,6 +28,11 @@
|
||||
* @author Werner Dietl
|
||||
* @compile Nesting.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface A { }
|
||||
|
||||
class Nesting {
|
||||
|
@ -1,5 +1,5 @@
|
||||
StaticThings.java:52:32: compiler.err.annotation.type.not.applicable
|
||||
StaticThings.java:54:37: compiler.err.annotation.type.not.applicable
|
||||
StaticThings.java:33:26: compiler.err.annotation.type.not.applicable
|
||||
StaticThings.java:36:28: compiler.err.annotation.type.not.applicable
|
||||
4 errors
|
||||
StaticThings.java:33:26: compiler.err.non-static.cant.be.ref: kindname.variable, this
|
||||
StaticThings.java:36:28: compiler.err.non-static.cant.be.ref: kindname.variable, this
|
||||
StaticThings.java:52:32: compiler.err.non-static.cant.be.ref: kindname.variable, this
|
||||
StaticThings.java:54:37: compiler.err.non-static.cant.be.ref: kindname.variable, this
|
||||
4 errors
|
||||
|
@ -29,6 +29,10 @@
|
||||
* @compile/fail/ref=WrongType.out -XDrawDiagnostics WrongType.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface A {}
|
||||
|
||||
class WrongType {
|
||||
|
@ -1,9 +1,9 @@
|
||||
WrongType.java:51:15: compiler.err.cant.resolve.location: kindname.class, XYZ, , , (compiler.misc.location: kindname.class, WrongType, null)
|
||||
WrongType.java:61:27: compiler.err.doesnt.exist: Outer
|
||||
WrongType.java:62:31: compiler.err.cant.resolve.location: kindname.class, XY, , , (compiler.misc.location: kindname.class, WrongType, null)
|
||||
WrongType.java:44:23: compiler.err.incorrect.receiver.type
|
||||
WrongType.java:46:23: compiler.err.incorrect.receiver.type
|
||||
WrongType.java:59:33: compiler.err.incorrect.receiver.type
|
||||
WrongType.java:60:31: compiler.err.incorrect.receiver.type
|
||||
WrongType.java:66:28: compiler.err.incorrect.receiver.type
|
||||
8 errors
|
||||
WrongType.java:48:16: compiler.err.incorrect.receiver.type: WrongType, java.lang.Object
|
||||
WrongType.java:50:16: compiler.err.incorrect.receiver.type: WrongType, java.lang.Object
|
||||
WrongType.java:55:15: compiler.err.cant.resolve.location: kindname.class, XYZ, , , (compiler.misc.location: kindname.class, WrongType, null)
|
||||
WrongType.java:63:23: compiler.err.incorrect.receiver.type: WrongType.Inner, WrongType
|
||||
WrongType.java:64:24: compiler.err.incorrect.receiver.type: WrongType.Inner, java.lang.Object
|
||||
WrongType.java:65:27: compiler.err.doesnt.exist: Outer
|
||||
WrongType.java:66:31: compiler.err.cant.resolve.location: kindname.class, XY, , , (compiler.misc.location: kindname.class, WrongType, null)
|
||||
WrongType.java:70:24: compiler.err.incorrect.receiver.type: WrongType.Generics<X>, WrongType.Generics<Y>
|
||||
8 errors
|
||||
|
@ -5,10 +5,15 @@
|
||||
* @author Mahmood Ali
|
||||
* @compile/fail/ref=MissingAnnotationValue.out -XDrawDiagnostics MissingAnnotationValue.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
class MissingAnnotationValue {
|
||||
void test() {
|
||||
new @A String();
|
||||
}
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface A { int field(); }
|
||||
|
@ -1,2 +1,2 @@
|
||||
MissingAnnotationValue.java:10:9: compiler.err.annotation.missing.default.value: A, field
|
||||
MissingAnnotationValue.java:14:9: compiler.err.annotation.missing.default.value: A, field
|
||||
1 error
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 1234567
|
||||
* @summary ensure that declaration annotations are not allowed on
|
||||
* wildcards
|
||||
* @author Werner Dietl
|
||||
* @compile/fail/ref=DeclarationAnnotation.out -XDrawDiagnostics DeclarationAnnotation.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
class DeclarationAnnotation {
|
||||
List<@DA ? extends Object> bad;
|
||||
List<@TA ? extends Object> good;
|
||||
}
|
||||
|
||||
@interface DA { }
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TA { }
|
@ -0,0 +1,2 @@
|
||||
DeclarationAnnotation.java:15:10: compiler.err.annotation.type.not.applicable
|
||||
1 error
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 1234567
|
||||
* @summary new type annotation location: anonymous class creation
|
||||
* @author Werner Dietl
|
||||
* @compile AnonymousClass.java
|
||||
*/
|
||||
class AnonymousClass {
|
||||
Object o1 = new @TA Object() { };
|
||||
// Declaration annotations are also allowed.
|
||||
Object o2 = new @TA @DA Object() { };
|
||||
}
|
||||
|
||||
@interface DA { }
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TA { }
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TB { }
|
@ -50,6 +50,13 @@ public class Lambda {
|
||||
return LambdaImpl::<@TA Object, @TB Object>new;
|
||||
}
|
||||
|
||||
interface LambdaInt2 {
|
||||
void lambda(Object p1, Object p2);
|
||||
}
|
||||
|
||||
LambdaInt2 getLambda() {
|
||||
return (@TA Object x, @TB Object y) -> { @TA Object l = null; System.out.println("We have: " + (@TB Object) x); };
|
||||
}
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
|
@ -25,7 +25,6 @@ import java.lang.annotation.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @ignore 8013408: Need specification for type exceptions on multicatch
|
||||
* @bug 8006775
|
||||
* @summary new type annotation location: multicatch
|
||||
* @author Werner Dietl
|
||||
@ -40,6 +39,8 @@ class DefaultScope {
|
||||
e.toString();
|
||||
}
|
||||
}
|
||||
/* Disabled: there is no syntax to annotate all components
|
||||
* of the multicatch.
|
||||
void exception02() {
|
||||
try {
|
||||
System.out.println("Hello 2!");
|
||||
@ -47,18 +48,24 @@ class DefaultScope {
|
||||
e.toString();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
class ModifiedVars {
|
||||
/*
|
||||
void exception() {
|
||||
void exception01() {
|
||||
try {
|
||||
arrays();
|
||||
} catch (final @A Exception e) {
|
||||
System.out.println("Hello 1!");
|
||||
} catch (final @B NullPointerException | @C IllegalArgumentException e) {
|
||||
e.toString();
|
||||
}
|
||||
}
|
||||
void exception02() {
|
||||
try {
|
||||
System.out.println("Hello 1!");
|
||||
} catch (@Decl @B NullPointerException | @C IllegalArgumentException e) {
|
||||
e.toString();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@ -67,5 +74,5 @@ class ModifiedVars {
|
||||
@interface B { }
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface C { }
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface D { }
|
||||
|
||||
@interface Decl { }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,7 +54,6 @@ public class Constructors {
|
||||
" } }";
|
||||
}
|
||||
|
||||
/* TODO: Outer.this annotation support.
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_RECEIVER),
|
||||
@TADescription(annotation = "TB", type = METHOD_RETURN),
|
||||
@ -69,5 +68,21 @@ public class Constructors {
|
||||
" @TD Inner(@TC Test Test.this, @TE int b) {}" +
|
||||
" } }";
|
||||
}
|
||||
*/
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_RECEIVER),
|
||||
@TADescription(annotation = "TB", type = METHOD_RECEIVER, genericLocation = {1, 0}),
|
||||
@TADescription(annotation = "TC", type = METHOD_RETURN),
|
||||
@TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0}),
|
||||
@TADescription(annotation = "TE", type = METHOD_RETURN),
|
||||
@TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
|
||||
})
|
||||
@TestClass("Outer$Middle$Inner")
|
||||
public String innerClass3() {
|
||||
return "class Outer { class Middle { class Inner {" +
|
||||
" @TC Inner(@TA Outer. @TB Middle Middle.this) {}" +
|
||||
" @TE Inner(@TD Middle Outer.Middle.this, @TF int b) {}" +
|
||||
" } } }";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ public class Driver {
|
||||
|
||||
if (isSnippet) {
|
||||
// Have a few common nested types for testing
|
||||
sb.append("class Outer { class Inner {} }");
|
||||
sb.append("class Outer { class Inner {} class Middle { class MInner {} } }");
|
||||
sb.append("class SOuter { static class SInner {} }");
|
||||
sb.append("class GOuter<X, Y> { class GInner<X, Y> {} }");
|
||||
}
|
||||
|
@ -47,11 +47,43 @@ public class ExceptionParameters {
|
||||
@TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1),
|
||||
@TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2)
|
||||
})
|
||||
public String multipleExceptions() {
|
||||
public String multipleExceptions1() {
|
||||
return "void multipleExceptions() { " +
|
||||
"try { new Object(); } catch(@TA Exception e) { }" +
|
||||
"try { new Object(); } catch(@TB Exception e) { }" +
|
||||
"try { new Object(); } catch(@TC Exception e) { }" +
|
||||
" }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0),
|
||||
@TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1),
|
||||
@TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2)
|
||||
})
|
||||
public String multipleExceptions2() {
|
||||
return "void multipleExceptions() { " +
|
||||
" try { new Object(); " +
|
||||
" try { new Object(); " +
|
||||
" try { new Object(); } catch(@TA Exception e) { }" +
|
||||
" } catch(@TB Exception e) { }" +
|
||||
" } catch(@TC Exception e) { }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 0),
|
||||
@TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1),
|
||||
@TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2)
|
||||
})
|
||||
public String multipleExceptions3() {
|
||||
return "void multipleExceptions() { " +
|
||||
" try { new Object(); " +
|
||||
" } catch(@TA Exception e1) { "+
|
||||
" try { new Object(); " +
|
||||
" } catch(@TB Exception e2) {" +
|
||||
" try { new Object(); } catch(@TC Exception e3) { }" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 1234567
|
||||
* @summary Test population of reference info for instance and class initializers
|
||||
* @author Werner Dietl
|
||||
* @compile -g Driver.java ReferenceInfoUtil.java Initializers.java
|
||||
* @run main Driver Initializers
|
||||
*/
|
||||
public class Initializers {
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String instanceInit1() {
|
||||
return "class Test { { Object o = new @TA ArrayList<@TB String>(); } }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TD", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String instanceInit2() {
|
||||
return "class Test { Object f = new @TA ArrayList<@TB String>(); " +
|
||||
" { Object o = new @TC ArrayList<@TD String>(); } }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String staticInit1() {
|
||||
return "class Test { static { Object o = new @TA ArrayList<@TB String>(); } }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TD", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TE", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TF", type = NEW,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String staticInit2() {
|
||||
return "class Test { Object f = new @TA ArrayList<@TB String>(); " +
|
||||
" static Object g = new @TC ArrayList<@TD String>(); " +
|
||||
" static { Object o = new @TE ArrayList<@TF String>(); } }";
|
||||
}
|
||||
|
||||
// TODO: test interaction with several constructors, especially non-initial constuctors.
|
||||
// I don't think this kind of test is possible here.
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST,
|
||||
typeIndex = 0, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
})
|
||||
public String lazyConstantCast1() {
|
||||
return "class Test { public static final Object o = (@TA Object) null; }";
|
||||
}
|
||||
|
||||
}
|
@ -259,4 +259,30 @@ public class Lambda {
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER,
|
||||
paramIndex = 0),
|
||||
@TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER,
|
||||
paramIndex = 1),
|
||||
@TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER,
|
||||
paramIndex = 1, genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "TD", type = LOCAL_VARIABLE,
|
||||
lvarOffset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
lvarLength = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
lvarIndex = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TE", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String returnLambdaExpr1() {
|
||||
return
|
||||
"interface LambdaInt {" +
|
||||
" void lambda(Object p1, List<Object> p2);" +
|
||||
"}" +
|
||||
"class Test {" +
|
||||
" LambdaInt getLambda() {" +
|
||||
" return (@TA Object x, @TB List<@TC Object> y) -> { @TD Object l = null; System.out.println((@TE Object) l); };" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -54,4 +54,24 @@ public class MethodThrows {
|
||||
public String interfaceMethod() {
|
||||
return "interface Test { void test() throws @TA RuntimeException, IllegalArgumentException, @TB Exception; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = THROWS, typeIndex = 0,
|
||||
genericLocation = {}),
|
||||
@TADescription(annotation = "TB", type = THROWS, typeIndex = 0,
|
||||
genericLocation = {1, 0}),
|
||||
@TADescription(annotation = "TC", type = THROWS, typeIndex = 0,
|
||||
genericLocation = {1, 0, 1, 0}),
|
||||
@TADescription(annotation = "TD", type = THROWS, typeIndex = 1,
|
||||
genericLocation = {}),
|
||||
@TADescription(annotation = "TE", type = THROWS, typeIndex = 1,
|
||||
genericLocation = {1, 0}),
|
||||
@TADescription(annotation = "TF", type = THROWS, typeIndex = 1,
|
||||
genericLocation = {1, 0, 1, 0})
|
||||
})
|
||||
public String NestedTypes() {
|
||||
return "class Outer { class Middle { class Inner1 extends Exception {}" +
|
||||
" class Inner2 extends Exception{} } }" +
|
||||
"class Test { void test() throws @TA Outer.@TB Middle.@TC Inner1, @TD Outer.@TE Middle.@TF Inner2 { } }";
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
|
||||
/*
|
||||
* @test
|
||||
* @bug 8006732 8006775
|
||||
* @ignore 8013408: Need specification for type exceptions on multicatch
|
||||
* @summary Test population of reference info for multicatch exception parameters
|
||||
* @author Werner Dietl
|
||||
* @compile -g Driver.java ReferenceInfoUtil.java MultiCatch.java
|
||||
@ -53,4 +52,16 @@ public class MultiCatch {
|
||||
"try { new Object(); } catch (@TA NullPointerException | @TB IndexOutOfBoundsException | @TC IllegalArgumentException e) { e.toString(); } }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = EXCEPTION_PARAMETER, exceptionIndex = 1),
|
||||
@TADescription(annotation = "TB", type = EXCEPTION_PARAMETER, exceptionIndex = 1),
|
||||
@TADescription(annotation = "TC", type = EXCEPTION_PARAMETER, exceptionIndex = 2),
|
||||
@TADescription(annotation = "TD", type = EXCEPTION_PARAMETER, exceptionIndex = 2),
|
||||
@TADescription(annotation = "TE", type = EXCEPTION_PARAMETER, exceptionIndex = 3),
|
||||
})
|
||||
public String multiCatch3() {
|
||||
return "void multiCatch3() { " +
|
||||
"try { new Object(); } catch (NullPointerException e1) {}" +
|
||||
"try { new Object(); } catch (@TA @TB NullPointerException | @TC @TD IndexOutOfBoundsException | @TE IllegalArgumentException e2) { e2.toString(); } }";
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -831,4 +831,48 @@ public class NestedTypes {
|
||||
" }\n" +
|
||||
"}}\n";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CLASS_EXTENDS,
|
||||
genericLocation = {}, typeIndex = -1),
|
||||
@TADescription(annotation = "TB", type = CLASS_EXTENDS,
|
||||
genericLocation = {3, 0}, typeIndex = -1),
|
||||
@TADescription(annotation = "TC", type = CLASS_EXTENDS,
|
||||
genericLocation = {3, 1}, typeIndex = -1),
|
||||
@TADescription(annotation = "TD", type = CLASS_EXTENDS,
|
||||
genericLocation = {1, 0}, typeIndex = -1),
|
||||
@TADescription(annotation = "TE", type = CLASS_EXTENDS,
|
||||
genericLocation = {1, 0, 3, 0}, typeIndex = -1),
|
||||
@TADescription(annotation = "TF", type = CLASS_EXTENDS,
|
||||
genericLocation = {1, 0, 3, 1}, typeIndex = -1)
|
||||
})
|
||||
@TestClass("GOuter$GInner$Test")
|
||||
public String testExtends1() {
|
||||
return "class GOuter<A, B> {\n" +
|
||||
" class GInner<X, Y> {\n" +
|
||||
" class Test extends @TA GOuter<@TB String, @TC String>.@TD GInner<@TE String, @TF String> {}" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CLASS_TYPE_PARAMETER,
|
||||
genericLocation = {}, paramIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CLASS_TYPE_PARAMETER_BOUND,
|
||||
genericLocation = {}, paramIndex = 0, boundIndex = 0),
|
||||
@TADescription(annotation = "TC", type = FIELD,
|
||||
genericLocation = {}),
|
||||
@TADescription(annotation = "TD", type = FIELD,
|
||||
genericLocation = {3, 0})
|
||||
})
|
||||
@TestClass("Test$1Nested")
|
||||
public String testNestedInMethod1() {
|
||||
return "class Test {\n" +
|
||||
" void foobar() {\n" +
|
||||
" class Nested<@TA X extends @TB Object> {\n" +
|
||||
" @TC List<@TD Object> f;\n" +
|
||||
" }\n" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,4 +75,81 @@ public class NewObjects {
|
||||
return "void eqtestObjectGeneric() { if (null == new @TA ArrayList<@TB String >()); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0}),
|
||||
@TADescription(annotation = "TB", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String returnNewArray1() {
|
||||
return "Object returnNewArray1() { return new @TA String @TB[1]; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0}),
|
||||
@TADescription(annotation = "TB", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0}),
|
||||
})
|
||||
public String returnNewArray2() {
|
||||
return "Object returnNewArray2() { return new @TA String @TB [1] @TC [2]; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0}),
|
||||
@TADescription(annotation = "TB", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0, 1, 0}),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TD", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0}),
|
||||
})
|
||||
public String returnNewArray3() {
|
||||
return "Object returnNewArray3() { return new @TA Outer. @TB Inner @TC [1] @TD [2]; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0}),
|
||||
@TADescription(annotation = "TB", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0, 1, 0}),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0, 1, 0, 1, 0}),
|
||||
@TADescription(annotation = "TD", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TE", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0}),
|
||||
})
|
||||
public String returnNewArray4() {
|
||||
return "Object returnNewArray4() { return new @TA Outer. @TB Middle. @TC MInner @TD [1] @TE [2]; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {3, 0, 0, 0, 0, 0}),
|
||||
@TADescription(annotation = "TC", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {3, 0, 0, 0, 0, 0, 1, 0}),
|
||||
@TADescription(annotation = "TD", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {3, 0, 0, 0, 0, 0, 1, 0, 1, 0}),
|
||||
@TADescription(annotation = "TE", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {3, 0}),
|
||||
@TADescription(annotation = "TF", type = NEW, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {3, 0, 0, 0}),
|
||||
})
|
||||
public String returnNewArray5() {
|
||||
return "Object returnNewArray5() { return new @TA ArrayList<@TB Outer. @TC Middle. @TD MInner @TE [] @TF []>(); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = FIELD, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0}),
|
||||
@TADescription(annotation = "TB", type = FIELD, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0, 0, 0, 1, 0}),
|
||||
@TADescription(annotation = "TC", type = FIELD, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TD", type = FIELD, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = {0, 0}),
|
||||
})
|
||||
public String arrayField() {
|
||||
return "@TA Outer. @TB Inner @TC [] @TD [] f;";
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,7 @@ import java.util.Map;
|
||||
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.TypeAnnotation;
|
||||
import com.sun.tools.classfile.Field;
|
||||
import com.sun.tools.classfile.Method;
|
||||
@ -90,6 +91,20 @@ public class ReferenceInfoUtil {
|
||||
RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
|
||||
annos.addAll(Arrays.asList(tAttr.annotations));
|
||||
}
|
||||
|
||||
int cindex = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
|
||||
if (cindex != -1) {
|
||||
Attribute cattr = m.attributes.get(cindex);
|
||||
assert cattr instanceof Code_attribute;
|
||||
Code_attribute cAttr = (Code_attribute)cattr;
|
||||
index = cAttr.attributes.getIndex(cf.constant_pool, name);
|
||||
if (index != -1) {
|
||||
Attribute attr = cAttr.attributes.get(index);
|
||||
assert attr instanceof RuntimeTypeAnnotations_attribute;
|
||||
RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
|
||||
annos.addAll(Arrays.asList(tAttr.annotations));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test the result of Attributes.getIndex according to expectations
|
||||
|
@ -0,0 +1,33 @@
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
class Test<K> { GOuter<@TC Object, String> entrySet() { return null; } }
|
||||
|
||||
@interface A {}
|
||||
@interface B {}
|
||||
@interface C {}
|
||||
@interface D {}
|
||||
@interface E {}
|
||||
@interface F {}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TA {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TB {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TC {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TD {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TE {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TF {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TG {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TH {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TI {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TJ {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TK {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TL {}
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface TM {}
|
||||
|
||||
@Repeatable(RTAs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA {}
|
||||
@Repeatable(RTBs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTB {}
|
||||
@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }
|
||||
@ContainerFor(RTB.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }
|
||||
@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})
|
||||
@interface Decl {}
|
@ -111,7 +111,8 @@ public class TestJavacTaskScanner extends ToolTester {
|
||||
DeclaredType type = (DeclaredType)task.parseType("List<String>", clazz);
|
||||
for (Element member : elements.getAllMembers((TypeElement)type.asElement())) {
|
||||
TypeMirror mt = types.asMemberOf(type, member);
|
||||
System.out.format("%s : %s -> %s%n", member.getSimpleName(), member.asType(), mt);
|
||||
System.out.format("type#%d: %s : %s -> %s%n",
|
||||
numParseTypeElements, member.getSimpleName(), member.asType(), mt);
|
||||
numParseTypeElements++;
|
||||
}
|
||||
}
|
||||
@ -123,7 +124,8 @@ public class TestJavacTaskScanner extends ToolTester {
|
||||
|
||||
private void testGetAllMembers(TypeElement clazz) {
|
||||
for (Element member : elements.getAllMembers(clazz)) {
|
||||
System.out.format("%s : %s%n", member.getSimpleName(), member.asType());
|
||||
System.out.format("elem#%d: %s : %s%n",
|
||||
numAllMembers, member.getSimpleName(), member.asType());
|
||||
numAllMembers++;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.array.and.receiver
|
||||
// key: compiler.err.expected
|
||||
// key: compiler.err.expected3
|
||||
// key: compiler.err.illegal.start.of.type
|
||||
|
||||
class ArrayAndReceiver {
|
||||
void m(ArrayAndReceiver this[]) { }
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.incorrect.constructor.receiver.name
|
||||
|
||||
class IncorrectConstructorReceiverName {
|
||||
class Inner {
|
||||
Inner(IncorrectConstructorReceiverName this) { }
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.incorrect.constructor.receiver.type
|
||||
|
||||
class IncorrectConstructorReceiverType {
|
||||
class Inner {
|
||||
Inner(Object IncorrectConstructorReceiverType.this) { }
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.incorrect.receiver.name
|
||||
|
||||
class IncorrectReceiverName {
|
||||
class Inner {
|
||||
void m(Inner IncorrectReceiverName.this) { }
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.receiver.parameter.not.applicable.constructor.toplevel.class
|
||||
|
||||
class ReceiverParameterNotApplicableConstructor {
|
||||
ReceiverParameterNotApplicableConstructor(ReceiverParameterNotApplicableConstructor this) { }
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.varargs.and.receiver
|
||||
|
||||
class VarargsAndReceiver {
|
||||
void m(VarargsAndReceiver... this) { }
|
||||
}
|
@ -469,6 +469,7 @@ public class DPrinter {
|
||||
indent(+1);
|
||||
printSymbol("tsym", type.tsym, Details.SUMMARY);
|
||||
printObject("constValue", type.constValue(), Details.SUMMARY);
|
||||
printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY);
|
||||
type.accept(typeVisitor, null);
|
||||
indent(-1);
|
||||
}
|
||||
|
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 1234567
|
||||
* @summary Annotations on types
|
||||
* @library /tools/javac/lib
|
||||
* @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests
|
||||
* @compile/process -processor BasicAnnoTests -proc:only BasicAnnoTests.java
|
||||
*/
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.AnnotatedConstruct;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.ArrayType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
|
||||
|
||||
/**
|
||||
* The test scans this file looking for test cases annotated with @Test.
|
||||
*/
|
||||
public class BasicAnnoTests extends JavacTestingAbstractProcessor {
|
||||
DPrinter dprinter;
|
||||
PrintWriter out;
|
||||
boolean verbose = true;
|
||||
|
||||
@Override
|
||||
public void init(ProcessingEnvironment pEnv) {
|
||||
super.init(pEnv);
|
||||
dprinter = new DPrinter(((JavacProcessingEnvironment) pEnv).getContext());
|
||||
out = dprinter.out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
TestElementScanner s = new TestElementScanner();
|
||||
for (Element e: roundEnv.getRootElements()) {
|
||||
s.scan(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void error(Element e, String msg) {
|
||||
messager.printMessage(Kind.ERROR, msg, e);
|
||||
errors++;
|
||||
}
|
||||
|
||||
int errors;
|
||||
|
||||
/**
|
||||
* Scan an element looking for declarations annotated with @Test.
|
||||
* Run a TestTypeScanner on the annotations that are found.
|
||||
*/
|
||||
class TestElementScanner extends ElementScanner<Void,Void> {
|
||||
public Void scan(Element elem, Void ignore) {
|
||||
AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.'));
|
||||
if (test != null) {
|
||||
out.println("Test: " + elem + " " + test);
|
||||
TestTypeScanner s = new TestTypeScanner(elem, test);
|
||||
s.scan(elem.asType(), null);
|
||||
if (getPosn(test) >= s.count)
|
||||
error(elem, "position " + getPosn(test) + " not found");
|
||||
if (!s.found) {
|
||||
dprinter.printSymbol("element", (Symbol) elem);
|
||||
dprinter.printType("type", (Type) elem.asType());
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
return super.scan(elem, ignore);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the type of an element, looking for an annotation
|
||||
* to match the expected annotation specified in the @Test annotation.
|
||||
*/
|
||||
class TestTypeScanner extends TypeScanner<Void, Void> {
|
||||
Element elem;
|
||||
AnnotationMirror test;
|
||||
int count = 0;
|
||||
boolean found = false;
|
||||
|
||||
TestTypeScanner(Element elem, AnnotationMirror test) {
|
||||
this.elem = elem;
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
@Override
|
||||
Void scan(TypeMirror t, Void ignore) {
|
||||
if (t == null)
|
||||
return DEFAULT_VALUE;
|
||||
if (verbose)
|
||||
out.println("scan " + count + ": " + t);
|
||||
if (count == getPosn(test)) {
|
||||
String annoType = getAnnoType(test);
|
||||
AnnotationMirror anno = getAnnotation(t, annoType);
|
||||
if (anno == null) {
|
||||
error(elem, "annotation not found on " + count + ": " + t);
|
||||
} else {
|
||||
String v = getValue(anno, "value").toString();
|
||||
if (v.equals(getExpect(test))) {
|
||||
out.println("found " + anno + " as expected");
|
||||
found = true;
|
||||
} else {
|
||||
error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
|
||||
}
|
||||
}
|
||||
}
|
||||
count++;
|
||||
return super.scan(t, ignore);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the position value from an @Test annotation mirror. */
|
||||
static int getPosn(AnnotationMirror test) {
|
||||
AnnotationValue v = getValue(test, "posn");
|
||||
return (Integer) v.getValue();
|
||||
}
|
||||
|
||||
/** Get the expect value from an @Test annotation mirror. */
|
||||
static String getExpect(AnnotationMirror test) {
|
||||
AnnotationValue v = getValue(test, "expect");
|
||||
return (String) v.getValue();
|
||||
}
|
||||
|
||||
/** Get the annoType value from an @Test annotation mirror. */
|
||||
static String getAnnoType(AnnotationMirror test) {
|
||||
AnnotationValue v = getValue(test, "annoType");
|
||||
TypeMirror m = (TypeMirror) v.getValue();
|
||||
return m.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific annotation mirror from an annotated construct.
|
||||
*/
|
||||
static AnnotationMirror getAnnotation(AnnotatedConstruct e, String name) {
|
||||
for (AnnotationMirror m: e.getAnnotationMirrors()) {
|
||||
TypeElement te = (TypeElement) m.getAnnotationType().asElement();
|
||||
if (te.getQualifiedName().contentEquals(name)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific value from an annotation mirror.
|
||||
*/
|
||||
static AnnotationValue getValue(AnnotationMirror anno, String name) {
|
||||
Map<? extends ExecutableElement, ? extends AnnotationValue> map = anno.getElementValues();
|
||||
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e: map.entrySet()) {
|
||||
if (e.getKey().getSimpleName().contentEquals(name)) {
|
||||
return e.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Language Model API does not provide a type scanner, so provide
|
||||
* one sufficient for our needs.
|
||||
*/
|
||||
static class TypeScanner<R, P> extends SimpleTypeVisitor<R, P> {
|
||||
@Override
|
||||
public R visitArray(ArrayType t, P p) {
|
||||
scan(t.getComponentType(), p);
|
||||
return super.visitArray(t, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitExecutable(ExecutableType t, P p) {
|
||||
scan(t.getReceiverType());
|
||||
//out.println(" params: " + t.getParameterTypes());
|
||||
scan(t.getParameterTypes(), p);
|
||||
//out.println(" return: " + t.getReturnType());
|
||||
scan(t.getReturnType(), p);
|
||||
//out.println(" throws: " + t.getThrownTypes());
|
||||
scan(t.getThrownTypes(), p);
|
||||
return super.visitExecutable(t, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitTypeVariable(TypeVariable t, P p) {
|
||||
scan(t.getLowerBound(), p);
|
||||
scan(t.getUpperBound(), p);
|
||||
return super.visitTypeVariable(t, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitWildcard(WildcardType t, P p) {
|
||||
scan(t.getExtendsBound(), p);
|
||||
scan(t.getSuperBound(), p);
|
||||
return super.visitWildcard(t, p);
|
||||
}
|
||||
|
||||
R scan(TypeMirror t) {
|
||||
return scan(t, null);
|
||||
}
|
||||
|
||||
R scan(TypeMirror t, P p) {
|
||||
return (t == null) ? DEFAULT_VALUE : t.accept(this, p);
|
||||
}
|
||||
|
||||
R scan(Iterable<? extends TypeMirror> iter, P p) {
|
||||
if (iter == null)
|
||||
return DEFAULT_VALUE;
|
||||
R result = DEFAULT_VALUE;
|
||||
for (TypeMirror t: iter)
|
||||
result = scan(t, p);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** Annotation to identify test cases. */
|
||||
@interface Test {
|
||||
/** Where to look for the annotation, expressed as a scan index. */
|
||||
int posn();
|
||||
/** The annotation to look for. */
|
||||
Class<? extends Annotation> annoType();
|
||||
/** The string representation of the annotation's value. */
|
||||
String expect();
|
||||
}
|
||||
|
||||
/** Type annotation to use in test cases. */
|
||||
@Target(ElementType.TYPE_USE)
|
||||
public @interface TA {
|
||||
int value();
|
||||
}
|
||||
|
||||
@Test(posn=0, annoType=TA.class, expect="1")
|
||||
public @TA(1) int f1;
|
||||
|
||||
@Test(posn=0, annoType=TA.class, expect="2")
|
||||
public int @TA(2) [] f2;
|
||||
|
||||
@Test(posn=1, annoType=TA.class, expect="3")
|
||||
public @TA(3) int [] f3;
|
||||
|
||||
@Test(posn=1, annoType=TA.class, expect="4")
|
||||
public int m1(@TA(4) float a) throws Exception { return 0; }
|
||||
|
||||
@Test(posn=2, annoType=TA.class, expect="5")
|
||||
public @TA(5) int m2(float a) throws Exception { return 0; }
|
||||
|
||||
@Test(posn=3, annoType=TA.class, expect="6")
|
||||
public int m3(float a) throws @TA(6) Exception { return 0; }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,6 +36,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6923080
|
||||
* @ignore 8014323: Add VariableTree.getNameExpression
|
||||
* @summary TreeScanner.visitNewClass should scan tree.typeargs
|
||||
* @build AbstractTreeScannerTest SourceTreeScannerTest
|
||||
* @run main SourceTreeScannerTest -q -r .
|
||||
|
@ -121,280 +121,307 @@ public class RepeatingTypeAnnotations extends Tester {
|
||||
*/
|
||||
|
||||
@TestCase
|
||||
@ignore // 8008082: missing type annotation for cast
|
||||
public static class TC1 extends RepeatingTypeAnnotations {
|
||||
public TC1() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC1 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public @A @A @A Object o = (@A @A @A String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(#26=[@#27(),@#27(),@#27()]): FIELD",
|
||||
"1: #25(#26=[@#27(),@#27(),@#27()]): CAST, offset=5");
|
||||
"0: #25(#26=[@#27(),@#27(),@#27()]): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC2 extends RepeatingTypeAnnotations {
|
||||
public TC2() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC2 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public @A @B @A Object o = (@B @A @B String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(#26=[@#27(),@#27()]): FIELD",
|
||||
"1: #28(): FIELD",
|
||||
"2: #29(#26=[@#28(),@#28()]): CAST, offset=5",
|
||||
"3: #27(): CAST, offset=5");
|
||||
"0: #36(#26=[@#28(),@#28()]): CAST, offset=5, type_index=0",
|
||||
"1: #27(): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC3 extends RepeatingTypeAnnotations {
|
||||
public TC3() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC3 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public @A @A @C Object o = (@B @C @B String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
verify("RuntimeVisibleTypeAnnotations",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(): FIELD",
|
||||
"1: #25(): CAST, offset=5",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
"0: #27(#28=[@#29(),@#29()]): FIELD",
|
||||
"1: #30(#28=[@#31(),@#31()]): CAST, offset=5");
|
||||
"0: #25(): CAST, offset=5, type_index=0",
|
||||
"0: #37(#28=[@#38(),@#38()]): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC4 extends RepeatingTypeAnnotations {
|
||||
public TC4() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC4 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public @A @B @C Object o = (@C @B @A String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
"0: #25(): FIELD",
|
||||
"1: #25(): CAST, offset=5",
|
||||
"0: #27(): FIELD",
|
||||
"1: #28(): FIELD",
|
||||
"2: #28(): CAST, offset=5",
|
||||
"3: #27(): CAST, offset=5");
|
||||
"0: #25(): CAST, offset=5, type_index=0",
|
||||
"0: #28(): CAST, offset=5, type_index=0",
|
||||
"1: #27(): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
@ignore // 8008082: missing type annotation for cast
|
||||
public static class TC5 extends RepeatingTypeAnnotations {
|
||||
public TC5() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC5 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public static @A @A @A Object o = (@B @B @B String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(#26=[@#27(),@#27(),@#27()]): FIELD",
|
||||
"1: #28(#26=[@#29(),@#29(),@#29()]): CAST, offset=5, type_index=0");
|
||||
"0: #36(#26=[@#37(),@#37(),@#37()]): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC6 extends RepeatingTypeAnnotations {
|
||||
public TC6() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC6 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public static @A @B @A Object o = (@B @A @B String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(#26=[@#27(),@#27()]): FIELD",
|
||||
"1: #28(): FIELD",
|
||||
"2: #29(#26=[@#28(),@#28()]): CAST, offset=5",
|
||||
"3: #27(): CAST, offset=5");
|
||||
"0: #37(#26=[@#28(),@#28()]): CAST, offset=5, type_index=0",
|
||||
"1: #27(): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC7 extends RepeatingTypeAnnotations {
|
||||
public TC7() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC7 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public static @A @A @C Object o = (@B @C @B String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
verify("RuntimeVisibleTypeAnnotations",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(): FIELD",
|
||||
"1: #25(): CAST, offset=5",
|
||||
"0: #27(#28=[@#29(),@#29()]): FIELD",
|
||||
"1: #30(#28=[@#31(),@#31()]): CAST, offset=5");
|
||||
"0: #25(): CAST, offset=5, type_index=0",
|
||||
"0: #38(#28=[@#39(),@#39()]): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC8 extends RepeatingTypeAnnotations {
|
||||
public TC8() {
|
||||
setSrc(" static String so = \"hello world\";",
|
||||
setSrc(" /* TC8 */ ",
|
||||
" static String so = \"hello world\";",
|
||||
" public static @A @B @C Object o = (@C @B @A String) Test.so;");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
|
||||
verify("RuntimeVisibleTypeAnnotations",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #25(): FIELD",
|
||||
"1: #25(): CAST, offset=5",
|
||||
"0: #27(): FIELD",
|
||||
"1: #28(): FIELD",
|
||||
"2: #28(): CAST, offset=5",
|
||||
"3: #27(): CAST, offset=5");
|
||||
"0: #25(): CAST, offset=5, type_index=0",
|
||||
"0: #28(): CAST, offset=5, type_index=0",
|
||||
"1: #27(): CAST, offset=5, type_index=0");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
@ignore // 8008082: missing type annotation for cast
|
||||
public static class TC9 extends RepeatingTypeAnnotations {
|
||||
public TC9() {
|
||||
setSrc(" public Test(@A @A @A Object o, @A int i, long l) {",
|
||||
setSrc(" /* TC9 */ ",
|
||||
" public Test(@A @A @A Object o, @A int i, long l) {",
|
||||
" @A @A @A String ls = (@B @B @B String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #34(#35=[@#36(),@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #36(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"2: #37(#35=[@#38(),@#38(),@#38()]): CAST, offset=4, type_index=0",
|
||||
"3: #34(#35=[@#36(),@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}");
|
||||
"0: #34(#35=[@#36(),@#36(),@#36()]): CAST, offset=4, type_index=0",
|
||||
"1: #37(#35=[@#38(),@#38(),@#38()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #37(#35=[@#38(),@#38(),@#38()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #38(): METHOD_FORMAL_PARAMETER, param_index=1");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC10 extends RepeatingTypeAnnotations {
|
||||
public TC10() {
|
||||
setSrc(" public Test(@A @A @B Object o, @A @B int i, long l) {",
|
||||
setSrc(" /* TC10 */ ",
|
||||
" public Test(@A @A @B Object o, @A @B int i, long l) {",
|
||||
" @A @A @B String ls = (@B @A @B String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #34(#35=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #37(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #36(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #37(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"4: #38(#35=[@#37(),@#37()]): CAST, offset=4, type_index=0",
|
||||
"5: #36(): CAST, offset=4, type_index=0",
|
||||
"6: #34(#35=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"7: #37(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #34(#35=[@#36(),@#36()]): CAST, offset=4, type_index=0",
|
||||
"1: #37(): CAST, offset=4, type_index=0",
|
||||
"2: #38(#35=[@#37(),@#37()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"3: #36(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #38(#35=[@#37(),@#37()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #36(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #37(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #36(): METHOD_FORMAL_PARAMETER, param_index=1");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC11 extends RepeatingTypeAnnotations {
|
||||
public TC11() {
|
||||
setSrc(" public Test(@C @C @A Object o, @A @B int i, long l) {",
|
||||
setSrc(" /* TC11 */ ",
|
||||
" public Test(@C @C @A Object o, @A @B int i, long l) {",
|
||||
" @C @C @A String ls = (@A @A @C String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
"0: #34(#35=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #36(): CAST, offset=4",
|
||||
"2: #34(#35=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"0: #38(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #38(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"2: #39(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #40(#35=[@#38(),@#38()]): CAST, offset=4",
|
||||
"4: #38(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}");
|
||||
verify("RuntimeVisibleTypeAnnotations",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #34(): CAST, offset=4, type_index=0",
|
||||
"1: #35(#36=[@#34(),@#34()]): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"0: #38(#36=[@#39(),@#39()]): CAST, offset=4, type_index=0",
|
||||
"1: #39(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"0: #35(#36=[@#34(),@#34()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"0: #39(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #39(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"2: #40(): METHOD_FORMAL_PARAMETER, param_index=1");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC12 extends RepeatingTypeAnnotations {
|
||||
public TC12() {
|
||||
setSrc(" public Test(@A @B @C Object o, @A @C int i, long l) {",
|
||||
setSrc(" /* TC12 */ ",
|
||||
" public Test(@A @B @C Object o, @A @C int i, long l) {",
|
||||
" @A @B @C String ls = (@C @A @B String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
verify("RuntimeVisibleTypeAnnotations",
|
||||
"0: #34(): CAST, offset=4, type_index=0",
|
||||
"1: #34(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #36(): CAST, offset=4, type_index=0",
|
||||
"1: #37(): CAST, offset=4, type_index=0",
|
||||
"2: #36(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"3: #37(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"0: #34(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #34(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"2: #34(): CAST, offset=4",
|
||||
"3: #34(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"0: #36(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"1: #37(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #36(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #36(): CAST, offset=4",
|
||||
"4: #37(): CAST, offset=4",
|
||||
"5: #36(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}",
|
||||
"6: #37(): LOCAL_VARIABLE, {start_pc=10, length=1, index=5}");
|
||||
"2: #36(): METHOD_FORMAL_PARAMETER, param_index=1");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
@ignore // 8008082: missing type annotation for cast
|
||||
public static class TC13 extends RepeatingTypeAnnotations {
|
||||
public TC13() {
|
||||
setSrc(" public @A @A @A String foo(@A @A @A Object o, @A int i, long l) {",
|
||||
setSrc(" /* TC13 */ ",
|
||||
" public @A @A @A String foo(@A @A @A Object o, @A int i, long l) {",
|
||||
" @A @A @A String ls = (@B @B @B String) o;",
|
||||
" return (@A @A @A String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #36(#37=[@#38(),@#38(),@#38()]): METHOD_RETURN",
|
||||
"1: #36(#37=[@#38(),@#38(),@#38()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #38(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #39(#37=[@#40(),@#40(),@#40()]): CAST, offset=0, type_index=0",
|
||||
"4: #36(#37=[@#38(),@#38(),@#38()]): CAST, offset=6, type_index=0",
|
||||
"5: #36(#37=[@#38(),@#38(),@#38()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}");
|
||||
"0: #36(#37=[@#38(),@#38(),@#38()]): CAST, offset=0, type_index=0",
|
||||
"1: #39(#37=[@#40(),@#40(),@#40()]): CAST, offset=6, type_index=0",
|
||||
"2: #39(#37=[@#40(),@#40(),@#40()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations",
|
||||
"0: #39(#37=[@#40(),@#40(),@#40()]): METHOD_RETURN",
|
||||
"1: #39(#37=[@#40(),@#40(),@#40()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #40(): METHOD_FORMAL_PARAMETER, param_index=1");
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC14 extends RepeatingTypeAnnotations {
|
||||
public TC14() {
|
||||
setSrc(" public @A @B @B String foo(@A @A @B Object o, @A @B int i, long l) {",
|
||||
setSrc(" /* TC14 */ ",
|
||||
" public @A @B @B String foo(@A @A @B Object o, @A @B int i, long l) {",
|
||||
" @A @A @B String ls = (@B @A @B String) o;",
|
||||
" return (@A @B @B String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"0: #36(): METHOD_RETURN",
|
||||
"1: #37(#38=[@#39(),@#39()]): METHOD_RETURN",
|
||||
"2: #40(#38=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"3: #39(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"4: #36(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"5: #39(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"6: #37(#38=[@#39(),@#39()]): CAST, offset=0",
|
||||
"7: #36(): CAST, offset=0",
|
||||
"8: #36(): CAST, offset=6",
|
||||
"9: #37(#38=[@#39(),@#39()]): CAST, offset=6",
|
||||
"10: #40(#38=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"11: #39(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}");
|
||||
verify(
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #36(#37=[@#38(),@#38()]): CAST, offset=0, type_index=0",
|
||||
"1: #39(): CAST, offset=0, type_index=0",
|
||||
"2: #39(): CAST, offset=6, type_index=0",
|
||||
"3: #36(#37=[@#38(),@#38()]): CAST, offset=6, type_index=0",
|
||||
"4: #40(#37=[@#39(),@#39()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"5: #38(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #39(): METHOD_RETURN",
|
||||
"1: #36(#37=[@#38(),@#38()]): METHOD_RETURN",
|
||||
"2: #40(#37=[@#39(),@#39()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"3: #38(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"4: #39(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"5: #38(): METHOD_FORMAL_PARAMETER, param_index=1"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC15 extends RepeatingTypeAnnotations {
|
||||
public TC15() {
|
||||
setSrc(" public @A @A @C String foo(@C @C @A Object o, @A @B int i, long l) {",
|
||||
setSrc(" /* TC15 */ ",
|
||||
" public @A @A @C String foo(@C @C @A Object o, @A @B int i, long l) {",
|
||||
" @C @C @A String ls = (@A @A @C String) o;",
|
||||
" return (@C @B @B String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
"0: #36(): METHOD_RETURN",
|
||||
"1: #37(#38=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #36(): CAST, offset=0",
|
||||
"3: #36(): CAST, offset=6",
|
||||
"4: #37(#38=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"0: #40(#38=[@#41(),@#41()]): METHOD_RETURN",
|
||||
"1: #41(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #41(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #42(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"4: #40(#38=[@#41(),@#41()]): CAST, offset=0",
|
||||
"5: #43(#38=[@#42(),@#42()]): CAST, offset=6",
|
||||
"6: #41(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}");
|
||||
verify(
|
||||
"RuntimeVisibleTypeAnnotations:",
|
||||
"0: #36(): CAST, offset=0, type_index=0",
|
||||
"1: #36(): CAST, offset=6, type_index=0",
|
||||
"2: #37(#38=[@#36(),@#36()]): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #40(#38=[@#41(),@#41()]): CAST, offset=0, type_index=0",
|
||||
"1: #42(#38=[@#43(),@#43()]): CAST, offset=6, type_index=0",
|
||||
"2: #41(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeVisibleTypeAnnotations:",
|
||||
"0: #36(): METHOD_RETURN",
|
||||
"1: #37(#38=[@#36(),@#36()]): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #40(#38=[@#41(),@#41()]): METHOD_RETURN",
|
||||
"1: #41(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #41(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #43(): METHOD_FORMAL_PARAMETER, param_index=1"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@TestCase
|
||||
public static class TC16 extends RepeatingTypeAnnotations {
|
||||
public TC16() {
|
||||
setSrc(" public @A @B @C String foo(@A @B @C Object o, @A @C int i, long l) {",
|
||||
setSrc(" /* TC16 */ ",
|
||||
" public @A @B @C String foo(@A @B @C Object o, @A @C int i, long l) {",
|
||||
" @A @B @C String ls = (@C @A @B String) o;",
|
||||
" return (@B @A @C String) o;",
|
||||
" }");
|
||||
verify("RuntimeInvisibleTypeAnnotations",
|
||||
"RuntimeVisibleTypeAnnotations",
|
||||
verify(
|
||||
"RuntimeVisibleTypeAnnotations:",
|
||||
"0: #36(): CAST, offset=0, type_index=0",
|
||||
"1: #36(): CAST, offset=6, type_index=0",
|
||||
"2: #36(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #38(): CAST, offset=0, type_index=0",
|
||||
"1: #39(): CAST, offset=0, type_index=0",
|
||||
"2: #39(): CAST, offset=6, type_index=0",
|
||||
"3: #38(): CAST, offset=6, type_index=0",
|
||||
"4: #38(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"5: #39(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeVisibleTypeAnnotations:",
|
||||
"0: #36(): METHOD_RETURN",
|
||||
"1: #36(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"2: #36(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"3: #36(): CAST, offset=0",
|
||||
"4: #36(): CAST, offset=6",
|
||||
"5: #36(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"RuntimeInvisibleTypeAnnotations:",
|
||||
"0: #38(): METHOD_RETURN",
|
||||
"1: #39(): METHOD_RETURN",
|
||||
"2: #38(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"3: #39(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
"4: #38(): METHOD_FORMAL_PARAMETER, param_index=1",
|
||||
"5: #38(): CAST, offset=0",
|
||||
"6: #39(): CAST, offset=0",
|
||||
"7: #39(): CAST, offset=6",
|
||||
"8: #38(): CAST, offset=6",
|
||||
"9: #38(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}",
|
||||
"10: #39(): LOCAL_VARIABLE, {start_pc=6, length=5, index=5}");
|
||||
"4: #38(): METHOD_FORMAL_PARAMETER, param_index=1"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user