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:
Werner Dietl 2013-05-14 15:04:06 -07:00 committed by Jonathan Gibbons
parent ac02470255
commit 54582cab82
103 changed files with 4087 additions and 999 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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');

View File

@ -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);

View File

@ -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.

View File

@ -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();

View File

@ -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

View File

@ -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.

View File

@ -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;
}
}
}

View File

@ -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() {

View File

@ -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
***********************************/

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;
/**

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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&gt;"
},
*/
/* @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&gt;</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&gt;</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&lt;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&gt;&gt;</span>"
},
*/
{BUG_ID + FS + "typeannos" + FS + "TwoBounds.html",
"<pre> class <span class=\"strong\">TwoBounds&lt;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>&lt;<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&gt; 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&nbsp;<a href=\"../typeannos/Parameterized.html\" " +
"title=\"class in typeannos\">Parameterized</a>&lt;<a href=\"../" +
@ -160,7 +149,6 @@ public class TestTypeAnnotations extends JavadocTester {
"title=\"annotation in typeannos\">@FldB</a> java.lang.String&gt; " +
"nestedParameterized</pre>"
},
*/
{BUG_ID + FS + "typeannos" + FS + "ModifiedScoped.html",
"<pre>public final&nbsp;<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[][]&nbsp;array2()</pre>"
},
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
{BUG_ID + FS + "typeannos" + FS + "MtdModifiedScoped.html",
"<pre>public final&nbsp;<a href=\"../typeannos/MtdParameterized.html\" " +
"title=\"class in typeannos\">MtdParameterized</a>&lt;<a href=\"../" +
@ -197,7 +184,6 @@ public class TestTypeAnnotations extends JavadocTester {
"MRtnB.html\" title=\"annotation in typeannos\">@MRtnB</a> java." +
"lang.String&gt;&nbsp;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&gt;" +
"&nbsp;void&nbsp;methodExtends()</pre>"
},
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
{BUG_ID + FS + "typeannos" + FS + "UnscopedUnmodified.html",
"<pre>&lt;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" +
"&gt;&gt;&nbsp;void&nbsp;nestedExtends()</pre>"
},
*/
{BUG_ID + FS + "typeannos" + FS + "PublicModifiedMethods.html",
"<pre>public final&nbsp;&lt;K extends <a href=\"../typeannos/" +
"MTyParamA.html\" title=\"annotation in typeannos\">@MTyParamA</a> " +
"java.lang.String&gt;&nbsp;void&nbsp;methodExtends()</pre>"
},
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
{BUG_ID + FS + "typeannos" + FS + "PublicModifiedMethods.html",
"<pre>public final&nbsp;&lt;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" +
"&gt;&gt;&nbsp;void&nbsp;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>&lt;java.lang.String,java.lang.String&gt;" +
"&nbsp;a)</pre>"
},
/* @ignore 8012173: javadoc does not receive all type annotations information from javac
{BUG_ID + FS + "typeannos" + FS + "Parameters.html",
"<pre>void&nbsp;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&gt;&nbsp;a)</pre>"
},
*/
{BUG_ID + FS + "typeannos" + FS + "Parameters.html",
"<pre>void&nbsp;array2Deep(<a href=\"../typeannos/ParamA.html\" " +
"title=\"annotation in typeannos\">@ParamA</a> java.lang.String " +

View File

@ -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"},

View File

@ -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;
}

View File

@ -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(); }
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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 { }
}
}

View File

@ -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(); }
}

View File

@ -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 { }
}

View File

@ -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(); }
}

View File

@ -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();

View File

@ -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();

View File

@ -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 {}

View File

@ -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

View File

@ -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 { }

View File

@ -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

View File

@ -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(); }

View File

@ -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 { }

View File

@ -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 { }

View File

@ -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 { }

View File

@ -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

View File

@ -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 { }

View File

@ -0,0 +1,2 @@
DeclarationAnnotation.java:14:14: compiler.err.annotation.type.not.applicable
1 error

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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(); }

View File

@ -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

View File

@ -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 { }

View File

@ -0,0 +1,2 @@
DeclarationAnnotation.java:15:10: compiler.err.annotation.type.not.applicable
1 error

View File

@ -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 { }

View File

@ -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})

View File

@ -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 { }

View File

@ -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) {}" +
" } } }";
}
}

View File

@ -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> {} }");
}

View File

@ -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) { }" +
" }" +
" }" +
"}";
}
}

View File

@ -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; }";
}
}

View File

@ -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); };" +
" }" +
"}";
}
}

View File

@ -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 { } }";
}
}

View File

@ -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(); } }";
}
}

View File

@ -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" +
" }" +
"}";
}
}

View File

@ -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;";
}
}

View File

@ -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

View File

@ -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 {}

View File

@ -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++;
}
}

View File

@ -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[]) { }
}

View File

@ -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) { }
}
}

View File

@ -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) { }
}
}

View File

@ -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) { }
}
}

View File

@ -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) { }
}

View File

@ -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) { }
}

View File

@ -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);
}

View File

@ -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; }
}

View File

@ -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 .

View File

@ -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