8008077: update reference impl for type-annotations
Reviewed-by: jjg
This commit is contained in:
parent
1ec5dfafe0
commit
464abcb4fa
@ -727,12 +727,13 @@ public class ClassWriter {
|
||||
private void write(TypeAnnotation.Position p, ClassOutputStream out) {
|
||||
out.writeByte(p.type.targetTypeValue());
|
||||
switch (p.type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
out.writeShort(p.offset);
|
||||
break;
|
||||
// local variable
|
||||
@ -779,9 +780,12 @@ public class ClassWriter {
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
out.writeByte(p.parameter_index);
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
out.writeShort(p.offset);
|
||||
out.writeByte(p.type_index);
|
||||
@ -790,10 +794,6 @@ public class ClassWriter {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
out.writeByte(p.parameter_index);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("ClassWriter: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
|
@ -86,12 +86,13 @@ public class TypeAnnotation {
|
||||
position.type = type;
|
||||
|
||||
switch (type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
position.offset = cr.readUnsignedShort();
|
||||
break;
|
||||
// local variable
|
||||
@ -142,9 +143,12 @@ public class TypeAnnotation {
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
position.parameter_index = cr.readUnsignedByte();
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
position.offset = cr.readUnsignedShort();
|
||||
position.type_index = cr.readUnsignedByte();
|
||||
@ -153,10 +157,6 @@ public class TypeAnnotation {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
position.parameter_index = cr.readUnsignedByte();
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
@ -177,13 +177,14 @@ public class TypeAnnotation {
|
||||
int n = 0;
|
||||
n += 1; // TargetType tag is a byte
|
||||
switch (pos.type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
n += 2;
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
n += 2; // offset
|
||||
break;
|
||||
// local variable
|
||||
case LOCAL_VARIABLE:
|
||||
@ -192,7 +193,7 @@ public class TypeAnnotation {
|
||||
n += 2; // table_length;
|
||||
int table_length = pos.lvarOffset.length;
|
||||
n += 2 * table_length; // offset
|
||||
n += 2 * table_length; // length;
|
||||
n += 2 * table_length; // length
|
||||
n += 2 * table_length; // index
|
||||
break;
|
||||
// exception parameter
|
||||
@ -206,7 +207,7 @@ public class TypeAnnotation {
|
||||
// type parameter
|
||||
case CLASS_TYPE_PARAMETER:
|
||||
case METHOD_TYPE_PARAMETER:
|
||||
n += 1; // parameter_index;
|
||||
n += 1; // parameter_index
|
||||
break;
|
||||
// type parameter bound
|
||||
case CLASS_TYPE_PARAMETER_BOUND:
|
||||
@ -226,9 +227,12 @@ public class TypeAnnotation {
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
n += 1; // parameter_index
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
n += 2; // offset
|
||||
n += 1; // type index
|
||||
@ -237,10 +241,6 @@ public class TypeAnnotation {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
n += 1; // parameter_index
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
@ -377,12 +377,13 @@ public class TypeAnnotation {
|
||||
sb.append(type);
|
||||
|
||||
switch (type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
sb.append(", offset = ");
|
||||
sb.append(offset);
|
||||
break;
|
||||
@ -444,9 +445,12 @@ public class TypeAnnotation {
|
||||
sb.append(", param_index = ");
|
||||
sb.append(parameter_index);
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
sb.append(", offset = ");
|
||||
sb.append(offset);
|
||||
@ -457,12 +461,6 @@ public class TypeAnnotation {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
// TODO: also needs an offset?
|
||||
sb.append(", param_index = ");
|
||||
sb.append(parameter_index);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
sb.append(", position UNKNOWN!");
|
||||
break;
|
||||
@ -564,34 +562,37 @@ public class TypeAnnotation {
|
||||
/** For annotations on an exception parameter. */
|
||||
EXCEPTION_PARAMETER(0x42, true),
|
||||
|
||||
/** For annotations on a typecast. */
|
||||
CAST(0x43, true),
|
||||
|
||||
/** For annotations on a type test. */
|
||||
INSTANCEOF(0x44, true),
|
||||
INSTANCEOF(0x43, true),
|
||||
|
||||
/** For annotations on an object creation expression. */
|
||||
NEW(0x45, true),
|
||||
NEW(0x44, true),
|
||||
|
||||
/** For annotations on a constructor reference receiver. */
|
||||
CONSTRUCTOR_REFERENCE(0x45, true),
|
||||
|
||||
/** For annotations on a method reference receiver. */
|
||||
METHOD_REFERENCE(0x46, true),
|
||||
|
||||
/** For annotations on a typecast. */
|
||||
CAST(0x47, true),
|
||||
|
||||
/** For annotations on a type argument of an object creation expression. */
|
||||
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x46, true),
|
||||
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x48, true),
|
||||
|
||||
/** For annotations on a type argument of a method call. */
|
||||
METHOD_INVOCATION_TYPE_ARGUMENT(0x47, true),
|
||||
METHOD_INVOCATION_TYPE_ARGUMENT(0x49, true),
|
||||
|
||||
/** For annotations on a lambda parameter type. */
|
||||
LAMBDA_FORMAL_PARAMETER(0x48, true),
|
||||
|
||||
/** For annotations on a method reference. */
|
||||
METHOD_REFERENCE(0x49, true),
|
||||
/** For annotations on a type argument of a constructor reference. */
|
||||
CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(0x4A, true),
|
||||
|
||||
/** For annotations on a type argument of a method reference. */
|
||||
METHOD_REFERENCE_TYPE_ARGUMENT(0x50, true),
|
||||
METHOD_REFERENCE_TYPE_ARGUMENT(0x4B, true),
|
||||
|
||||
/** For annotations with an unknown target. */
|
||||
UNKNOWN(0xFF);
|
||||
|
||||
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x50;
|
||||
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x4B;
|
||||
|
||||
private final int targetTypeValue;
|
||||
private final boolean isLocal;
|
||||
|
@ -82,34 +82,37 @@ public enum TargetType {
|
||||
/** For annotations on an exception parameter. */
|
||||
EXCEPTION_PARAMETER(0x42, true),
|
||||
|
||||
/** For annotations on a typecast. */
|
||||
CAST(0x43, true),
|
||||
|
||||
/** For annotations on a type test. */
|
||||
INSTANCEOF(0x44, true),
|
||||
INSTANCEOF(0x43, true),
|
||||
|
||||
/** For annotations on an object creation expression. */
|
||||
NEW(0x45, true),
|
||||
NEW(0x44, true),
|
||||
|
||||
/** For annotations on a constructor reference receiver. */
|
||||
CONSTRUCTOR_REFERENCE(0x45, true),
|
||||
|
||||
/** For annotations on a method reference receiver. */
|
||||
METHOD_REFERENCE(0x46, true),
|
||||
|
||||
/** For annotations on a typecast. */
|
||||
CAST(0x47, true),
|
||||
|
||||
/** For annotations on a type argument of an object creation expression. */
|
||||
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x46, true),
|
||||
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x48, true),
|
||||
|
||||
/** For annotations on a type argument of a method call. */
|
||||
METHOD_INVOCATION_TYPE_ARGUMENT(0x47, true),
|
||||
METHOD_INVOCATION_TYPE_ARGUMENT(0x49, true),
|
||||
|
||||
/** For annotations on a lambda parameter type. */
|
||||
LAMBDA_FORMAL_PARAMETER(0x48, true),
|
||||
|
||||
/** For annotations on a method reference. */
|
||||
METHOD_REFERENCE(0x49, true),
|
||||
/** For annotations on a type argument of a constructor reference. */
|
||||
CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(0x4A, true),
|
||||
|
||||
/** For annotations on a type argument of a method reference. */
|
||||
METHOD_REFERENCE_TYPE_ARGUMENT(0x50, true),
|
||||
METHOD_REFERENCE_TYPE_ARGUMENT(0x4B, true),
|
||||
|
||||
/** For annotations with an unknown target. */
|
||||
UNKNOWN(0xFF);
|
||||
|
||||
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x92;
|
||||
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x4B;
|
||||
|
||||
private final int targetTypeValue;
|
||||
private final boolean isLocal;
|
||||
|
@ -126,7 +126,8 @@ public class TypeAnnotationPosition {
|
||||
// Tree position.
|
||||
public int pos = -1;
|
||||
|
||||
// For typecasts, type tests, new (and locals, as start_pc).
|
||||
// For type casts, type tests, new, locals (as start_pc),
|
||||
// and method and constructor reference type arguments.
|
||||
public boolean isValidOffset = false;
|
||||
public int offset = -1;
|
||||
|
||||
@ -156,12 +157,13 @@ public class TypeAnnotationPosition {
|
||||
sb.append(type);
|
||||
|
||||
switch (type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
sb.append(", offset = ");
|
||||
sb.append(offset);
|
||||
break;
|
||||
@ -223,9 +225,12 @@ public class TypeAnnotationPosition {
|
||||
sb.append(", param_index = ");
|
||||
sb.append(parameter_index);
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
sb.append(", offset = ");
|
||||
sb.append(offset);
|
||||
@ -236,12 +241,6 @@ public class TypeAnnotationPosition {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
// TODO: also needs an offset?
|
||||
sb.append(", param_index = ");
|
||||
sb.append(parameter_index);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
sb.append(", position UNKNOWN!");
|
||||
break;
|
||||
|
@ -217,6 +217,9 @@ public class TypeAnnotations {
|
||||
// Such an annotation is _not_ part of an JCAnnotatedType tree and we therefore
|
||||
// need to set its position explicitly.
|
||||
// The method returns a copy of type that contains these annotations.
|
||||
//
|
||||
// As a side effect the method sets the type annotation position of "annotations".
|
||||
// Note that it is assumed that all annotations share the same position.
|
||||
private static Type typeWithAnnotations(final JCTree typetree, final Type type,
|
||||
final List<Attribute.TypeCompound> annotations, Log log) {
|
||||
// System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n",
|
||||
@ -267,7 +270,9 @@ public class TypeAnnotations {
|
||||
}
|
||||
Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log);
|
||||
tomodify.elemtype = arelemType;
|
||||
for (Attribute.TypeCompound a : annotations) {
|
||||
{
|
||||
// All annotations share the same position; modify the first one.
|
||||
Attribute.TypeCompound a = annotations.get(0);
|
||||
TypeAnnotationPosition p = a.position;
|
||||
p.location = p.location.prependList(depth.toList());
|
||||
}
|
||||
@ -345,10 +350,10 @@ public class TypeAnnotations {
|
||||
if (depth.nonEmpty()) {
|
||||
// Only need to change the annotation positions
|
||||
// if they are on an enclosed type.
|
||||
for (Attribute.TypeCompound a : annotations) {
|
||||
TypeAnnotationPosition p = a.position;
|
||||
p.location = p.location.appendList(depth.toList());
|
||||
}
|
||||
// All annotations share the same position; modify the first one.
|
||||
Attribute.TypeCompound a = annotations.get(0);
|
||||
TypeAnnotationPosition p = a.position;
|
||||
p.location = p.location.appendList(depth.toList());
|
||||
}
|
||||
|
||||
Type ret = typeWithAnnotations(type, enclTy, annotations);
|
||||
@ -463,8 +468,7 @@ public class TypeAnnotations {
|
||||
|
||||
@Override
|
||||
public Type visitType(Type t, List<TypeCompound> s) {
|
||||
// Error?
|
||||
return t;
|
||||
return new AnnotatedType(s, t);
|
||||
}
|
||||
};
|
||||
|
||||
@ -575,6 +579,10 @@ public class TypeAnnotations {
|
||||
System.out.println("Resolving tree: " + tree + " kind: " + tree.getKind());
|
||||
System.out.println(" Framing tree: " + frame + " kind: " + frame.getKind());
|
||||
*/
|
||||
|
||||
// Note that p.offset is set in
|
||||
// com.sun.tools.javac.jvm.Gen.setTypeAnnotationPositions(int)
|
||||
|
||||
switch (frame.getKind()) {
|
||||
case TYPE_CAST:
|
||||
p.type = TargetType.CAST;
|
||||
@ -659,6 +667,45 @@ public class TypeAnnotations {
|
||||
return;
|
||||
}
|
||||
|
||||
case MEMBER_REFERENCE: {
|
||||
JCMemberReference mrframe = (JCMemberReference) frame;
|
||||
|
||||
if (mrframe.expr == tree) {
|
||||
switch (mrframe.mode) {
|
||||
case INVOKE:
|
||||
p.type = TargetType.METHOD_REFERENCE;
|
||||
break;
|
||||
case NEW:
|
||||
p.type = TargetType.CONSTRUCTOR_REFERENCE;
|
||||
break;
|
||||
default:
|
||||
Assert.error("Unknown method reference mode " + mrframe.mode +
|
||||
" for tree " + tree + " within frame " + frame);
|
||||
}
|
||||
p.pos = frame.pos;
|
||||
} else if (mrframe.typeargs != null &&
|
||||
mrframe.typeargs.contains(tree)) {
|
||||
int arg = mrframe.typeargs.indexOf(tree);
|
||||
p.type_index = arg;
|
||||
switch (mrframe.mode) {
|
||||
case INVOKE:
|
||||
p.type = TargetType.METHOD_REFERENCE_TYPE_ARGUMENT;
|
||||
break;
|
||||
case NEW:
|
||||
p.type = TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
|
||||
break;
|
||||
default:
|
||||
Assert.error("Unknown method reference mode " + mrframe.mode +
|
||||
" for tree " + tree + " within frame " + frame);
|
||||
}
|
||||
p.pos = frame.pos;
|
||||
} else {
|
||||
Assert.error("Could not determine type argument position of tree " + tree +
|
||||
" within frame " + frame);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case ARRAY_TYPE: {
|
||||
ListBuffer<TypePathEntry> index = ListBuffer.lb();
|
||||
index = index.append(TypePathEntry.ARRAY);
|
||||
@ -766,6 +813,14 @@ public class TypeAnnotations {
|
||||
return;
|
||||
}
|
||||
|
||||
case INTERSECTION_TYPE: {
|
||||
JCTypeIntersection isect = (JCTypeIntersection)frame;
|
||||
p.type_index = isect.bounds.indexOf(tree);
|
||||
List<JCTree> newPath = path.tail;
|
||||
resolveFrame(newPath.head, newPath.tail.head, newPath, p);
|
||||
return;
|
||||
}
|
||||
|
||||
case METHOD_INVOCATION: {
|
||||
JCMethodInvocation invocation = (JCMethodInvocation)frame;
|
||||
if (!invocation.typeargs.contains(tree)) {
|
||||
@ -911,6 +966,8 @@ public class TypeAnnotations {
|
||||
public void visitVarDef(final JCVariableDecl tree) {
|
||||
if (tree.sym == null) {
|
||||
// Something is wrong already. Quietly ignore.
|
||||
} else if (tree.sym.getKind() == ElementKind.PARAMETER) {
|
||||
// Parameters are handled in visitMethodDef above.
|
||||
} else if (tree.sym.getKind() == ElementKind.FIELD) {
|
||||
if (sigOnly) {
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
@ -924,7 +981,6 @@ public class TypeAnnotations {
|
||||
pos.pos = tree.pos;
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
|
||||
// System.out.println("Found exception param: " + tree);
|
||||
TypeAnnotationPosition pos = new TypeAnnotationPosition();
|
||||
pos.type = TargetType.EXCEPTION_PARAMETER;
|
||||
pos.pos = tree.pos;
|
||||
@ -934,9 +990,11 @@ public class TypeAnnotations {
|
||||
pos.type = TargetType.RESOURCE_VARIABLE;
|
||||
pos.pos = tree.pos;
|
||||
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
|
||||
} else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) {
|
||||
// No type annotations can occur here.
|
||||
} else {
|
||||
// There is nothing else in a variable declaration that needs separation.
|
||||
// System.out.println("We found a: " + tree);
|
||||
Assert.error("Unhandled variable kind: " + tree + " of kind: " + tree.sym.getKind());
|
||||
}
|
||||
|
||||
push(tree);
|
||||
|
@ -2068,7 +2068,15 @@ public class Types {
|
||||
|
||||
@Override
|
||||
public Type visitAnnotatedType(AnnotatedType t, Boolean recurse) {
|
||||
return new AnnotatedType(t.typeAnnotations, erasure(t.underlyingType, recurse));
|
||||
Type erased = erasure(t.underlyingType, recurse);
|
||||
if (erased.getKind() == TypeKind.ANNOTATED) {
|
||||
// This can only happen when the underlying type is a
|
||||
// type variable and the upper bound of it is annotated.
|
||||
// The annotation on the type variable overrides the one
|
||||
// on the bound.
|
||||
erased = ((AnnotatedType)erased).underlyingType;
|
||||
}
|
||||
return new AnnotatedType(t.typeAnnotations, erased);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -766,6 +766,8 @@ public class Attr extends JCTree.Visitor {
|
||||
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
|
||||
|
||||
try {
|
||||
memberEnter.typeAnnotate(initializer, env, env.info.enclVar);
|
||||
annotate.flush();
|
||||
Type itype = attribExpr(initializer, env, type);
|
||||
if (itype.constValue() != null)
|
||||
return coerce(itype, type).constValue();
|
||||
@ -2539,7 +2541,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
if (exprType.isErroneous()) {
|
||||
//if the qualifier expression contains problems,
|
||||
//give up atttribution of method reference
|
||||
//give up attribution of method reference
|
||||
result = that.type = exprType;
|
||||
return;
|
||||
}
|
||||
|
@ -1470,12 +1470,13 @@ public class ClassReader implements Completer {
|
||||
position.type = type;
|
||||
|
||||
switch (type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
position.offset = nextChar();
|
||||
break;
|
||||
// local variable
|
||||
@ -1524,9 +1525,12 @@ public class ClassReader implements Completer {
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
position.parameter_index = nextByte();
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
position.offset = nextChar();
|
||||
position.type_index = nextByte();
|
||||
@ -1535,10 +1539,6 @@ public class ClassReader implements Completer {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
position.parameter_index = nextByte();
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
|
@ -992,12 +992,13 @@ public class ClassWriter extends ClassFile {
|
||||
void writePosition(TypeAnnotationPosition p) {
|
||||
databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
|
||||
switch (p.type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
databuf.appendChar(p.offset);
|
||||
break;
|
||||
// local variable
|
||||
@ -1042,9 +1043,12 @@ public class ClassWriter extends ClassFile {
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
databuf.appendByte(p.parameter_index);
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
databuf.appendChar(p.offset);
|
||||
databuf.appendByte(p.type_index);
|
||||
@ -1053,10 +1057,6 @@ public class ClassWriter extends ClassFile {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
databuf.appendByte(p.parameter_index);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
|
@ -1164,7 +1164,7 @@ public class JavacParser implements Parser {
|
||||
} else return illegal();
|
||||
break;
|
||||
case MONKEYS_AT:
|
||||
// Only annotated cast types are valid
|
||||
// Only annotated cast types and method references are valid
|
||||
List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
|
||||
if (typeAnnos.isEmpty()) {
|
||||
// else there would be no '@'
|
||||
@ -1175,17 +1175,27 @@ public class JavacParser implements Parser {
|
||||
|
||||
if ((mode & TYPE) == 0) {
|
||||
// Type annotations on class literals no longer legal
|
||||
if (!expr.hasTag(Tag.SELECT)) {
|
||||
switch (expr.getTag()) {
|
||||
case REFERENCE: {
|
||||
JCMemberReference mref = (JCMemberReference) expr;
|
||||
mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
|
||||
t = mref;
|
||||
break;
|
||||
}
|
||||
case SELECT: {
|
||||
JCFieldAccess sel = (JCFieldAccess) expr;
|
||||
|
||||
if (sel.name != names._class) {
|
||||
return illegal();
|
||||
} else {
|
||||
log.error(token.pos, "no.annotations.on.dot.class");
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return illegal(typeAnnos.head.pos);
|
||||
}
|
||||
JCFieldAccess sel = (JCFieldAccess)expr;
|
||||
|
||||
if (sel.name != names._class) {
|
||||
return illegal();
|
||||
} else {
|
||||
log.error(token.pos, "no.annotations.on.dot.class");
|
||||
return expr;
|
||||
}
|
||||
} else {
|
||||
// Type annotations targeting a cast
|
||||
t = insertAnnotationsToMostInner(expr, typeAnnos, false);
|
||||
@ -1457,18 +1467,40 @@ public class JavacParser implements Parser {
|
||||
/**
|
||||
* If we see an identifier followed by a '<' it could be an unbound
|
||||
* method reference or a binary expression. To disambiguate, look for a
|
||||
* matching '>' and see if the subsequent terminal is either '.' or '#'.
|
||||
* matching '>' and see if the subsequent terminal is either '.' or '::'.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
boolean isUnboundMemberRef() {
|
||||
int pos = 0, depth = 0;
|
||||
for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
|
||||
outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
|
||||
switch (t.kind) {
|
||||
case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
|
||||
case DOT: case RBRACKET: case LBRACKET: case COMMA:
|
||||
case BYTE: case SHORT: case INT: case LONG: case FLOAT:
|
||||
case DOUBLE: case BOOLEAN: case CHAR:
|
||||
case MONKEYS_AT:
|
||||
break;
|
||||
|
||||
case LPAREN:
|
||||
// skip annotation values
|
||||
int nesting = 0;
|
||||
for (; ; pos++) {
|
||||
TokenKind tk2 = S.token(pos).kind;
|
||||
switch (tk2) {
|
||||
case EOF:
|
||||
return false;
|
||||
case LPAREN:
|
||||
nesting++;
|
||||
break;
|
||||
case RPAREN:
|
||||
nesting--;
|
||||
if (nesting == 0) {
|
||||
continue outer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case LT:
|
||||
depth++; break;
|
||||
case GTGTGT:
|
||||
@ -1494,7 +1526,7 @@ public class JavacParser implements Parser {
|
||||
/**
|
||||
* If we see an identifier followed by a '<' it could be an unbound
|
||||
* method reference or a binary expression. To disambiguate, look for a
|
||||
* matching '>' and see if the subsequent terminal is either '.' or '#'.
|
||||
* matching '>' and see if the subsequent terminal is either '.' or '::'.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
ParensResult analyzeParens() {
|
||||
|
@ -235,6 +235,7 @@ public class TreeInfo {
|
||||
switch(tree.getTag()) {
|
||||
case TYPEAPPLY: return ((JCTypeApply)tree).getTypeArguments().isEmpty();
|
||||
case NEWCLASS: return isDiamond(((JCNewClass)tree).clazz);
|
||||
case ANNOTATED_TYPE: return isDiamond(((JCAnnotatedType)tree).underlyingType);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -335,6 +336,8 @@ public class TreeInfo {
|
||||
case TYPEAPPLY:
|
||||
case TYPEARRAY:
|
||||
return true;
|
||||
case ANNOTATED_TYPE:
|
||||
return isStaticSelector(((JCAnnotatedType)base).underlyingType, names);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -91,12 +91,13 @@ public class AnnotationWriter extends BasicWriter {
|
||||
print(pos.type);
|
||||
|
||||
switch (pos.type) {
|
||||
// type cast
|
||||
case CAST:
|
||||
// instanceof
|
||||
case INSTANCEOF:
|
||||
// new expression
|
||||
case NEW:
|
||||
// constructor/method reference receiver
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
if (showOffsets) {
|
||||
print(", offset=");
|
||||
print(pos.offset);
|
||||
@ -162,9 +163,12 @@ public class AnnotationWriter extends BasicWriter {
|
||||
print(", param_index=");
|
||||
print(pos.parameter_index);
|
||||
break;
|
||||
// type cast
|
||||
case CAST:
|
||||
// method/constructor/reference type argument
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
if (showOffsets) {
|
||||
print(", offset=");
|
||||
@ -177,11 +181,6 @@ public class AnnotationWriter extends BasicWriter {
|
||||
case METHOD_RETURN:
|
||||
case FIELD:
|
||||
break;
|
||||
// lambda formal parameter
|
||||
case LAMBDA_FORMAL_PARAMETER:
|
||||
print(", param_index=");
|
||||
print(pos.parameter_index);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!");
|
||||
default:
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 8008077
|
||||
* @summary Type annotations in a lazy constant need to be attributed
|
||||
* in the correct order.
|
||||
* @author Werner Dietl
|
||||
* @compile LazyConstantValue.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
class ClassA {
|
||||
Object o = ClassB.lcv;
|
||||
}
|
||||
|
||||
class ClassB {
|
||||
static final String[] lcv = new @TA String[0];
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TA {}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 8008077
|
||||
* @summary Type annotations on a type variable, where the bound of
|
||||
* the type variable is also annotated, need to be processed correctly.
|
||||
* @author Werner Dietl
|
||||
* @compile TypeVariable.java
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
class TypeVariable {
|
||||
<TV extends @TA Object> TV cast(TV p) {
|
||||
return (@TA TV) p;
|
||||
}
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TA {}
|
||||
|
@ -21,6 +21,8 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6843077 8006775
|
||||
@ -29,7 +31,8 @@
|
||||
* @compile/fail VoidGenericMethod.java
|
||||
*/
|
||||
class VoidGenericMethod {
|
||||
public <T> @A void method() { }
|
||||
public @A <T> void method() { }
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface A { }
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 8008077
|
||||
* @summary new type annotation location: lambda expressions
|
||||
* @compile Lambda.java
|
||||
* @author Werner Dietl
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
public class Lambda {
|
||||
|
||||
interface LambdaInt {
|
||||
<S, T> void generic(S p1, T p2);
|
||||
}
|
||||
|
||||
static class LambdaImpl implements LambdaInt {
|
||||
<S, T> LambdaImpl(S p1, T p2) {}
|
||||
public <S, T> void generic(S p1, T p2) {}
|
||||
}
|
||||
|
||||
LambdaInt getMethodRefTA(LambdaImpl r) {
|
||||
return r::<@TA Object, @TB Object>generic;
|
||||
}
|
||||
|
||||
LambdaInt getConstructorRefTA() {
|
||||
return LambdaImpl::<@TA Object, @TB Object>new;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TA { }
|
||||
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface TB { }
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* 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 8008077
|
||||
* @summary Test population of reference info for lambda expressions
|
||||
* @compile -g Driver.java ReferenceInfoUtil.java Lambda.java
|
||||
* @run main Driver Lambda
|
||||
* @author Werner Dietl
|
||||
*/
|
||||
|
||||
import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
|
||||
|
||||
public class Lambda {
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String returnMethodRef1() {
|
||||
return
|
||||
"class Lambda {" +
|
||||
" public String getName() { return \"Lambda!\"; }" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" java.util.function.Function<Lambda, String> lambda() {" +
|
||||
" return @TA @TB Lambda::getName;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "TC", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "TD", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 }),
|
||||
@TADescription(annotation = "TE", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 })
|
||||
})
|
||||
public String returnMethodRef2() {
|
||||
return
|
||||
"class Lambda<S, T> {" +
|
||||
" public String getName() { return \"Lambda!\"; }" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" java.util.function.Function<Lambda<Integer, Float>, String> lambda() {" +
|
||||
" return @TA Lambda<@TB @TC Integer, @TD @TE Float>::getName;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "CTA", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "CTB", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "CTC", type = METHOD_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 })
|
||||
})
|
||||
public String returnMethodRef3() {
|
||||
return
|
||||
"class Lambda<S, T> {" +
|
||||
" public String getName() { return \"Lambda!\"; }" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTA {" +
|
||||
" String value();" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTB {" +
|
||||
" int age();" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTC {" +
|
||||
" String name();" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" java.util.function.Function<Lambda<Integer, Float>, String> lambda() {" +
|
||||
" return @CTA(\"x\") Lambda<@CTB(age = 5) Integer, @CTC(name = \"y\") Float>::getName;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
})
|
||||
public String returnConstructorRef1() {
|
||||
return
|
||||
"class Lambda {" +
|
||||
" Lambda() { }" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" Runnable lambda() {" +
|
||||
" return @TA @TB Lambda::new;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TB", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "TC", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "TD", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 }),
|
||||
@TADescription(annotation = "TE", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 })
|
||||
})
|
||||
public String returnConstructorRef2() {
|
||||
return
|
||||
"class Lambda<S, T> {" +
|
||||
" Lambda() { }" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" Runnable lambda() {" +
|
||||
" return @TA Lambda<@TB @TC Integer, @TD @TE Float>::new;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "CTA", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "CTB", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 0 }),
|
||||
@TADescription(annotation = "CTC", type = CONSTRUCTOR_REFERENCE,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
genericLocation = { 3, 1 })
|
||||
})
|
||||
public String returnConstructorRef3() {
|
||||
return
|
||||
"class Lambda<S, T> {" +
|
||||
" Lambda() { }" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTA {" +
|
||||
" String value();" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTB {" +
|
||||
" int age();" +
|
||||
"}" +
|
||||
|
||||
"@Target(ElementType.TYPE_USE)" +
|
||||
"@interface CTC {" +
|
||||
" String name();" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" Runnable lambda() {" +
|
||||
" return @CTA(\"x\") Lambda<@CTB(age = 5) Integer, @CTC(name = \"y\") Float>::new;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_REFERENCE_TYPE_ARGUMENT,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = METHOD_REFERENCE_TYPE_ARGUMENT,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 1)
|
||||
})
|
||||
public String returnMethodRefTA1() {
|
||||
return
|
||||
"interface Lambda {" +
|
||||
" <S, T> void generic(S p1, T p2);" +
|
||||
"}" +
|
||||
|
||||
"class LambdaImpl implements Lambda {" +
|
||||
" public <S, T> void generic(S p1, T p2) {}" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" Lambda lambda(LambdaImpl r) {" +
|
||||
" return r::<@TA Object, @TB Object>generic;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 1)
|
||||
})
|
||||
public String returnConstructorRefTA2() {
|
||||
return
|
||||
"interface Lambda {" +
|
||||
" <S, T> void generic(S p1, T p2);" +
|
||||
"}" +
|
||||
|
||||
"class LambdaImpl implements Lambda {" +
|
||||
" <S, T> LambdaImpl(S p1, T p2) {}" +
|
||||
" public <S, T> void generic(S p1, T p2) {}" +
|
||||
"}" +
|
||||
|
||||
"class Test {" +
|
||||
" Lambda lambda() {" +
|
||||
" return LambdaImpl::<@TA Object, @TB Object>new;" +
|
||||
" }" +
|
||||
"}";
|
||||
}
|
||||
|
||||
}
|
@ -92,6 +92,28 @@ public class MethodParameters {
|
||||
return "void test(Object b, @TC String @TA [] @TB [] a) { }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER,
|
||||
genericLocation = { 0, 0 }, paramIndex = 1),
|
||||
@TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER,
|
||||
genericLocation = { 0, 0 }, paramIndex = 1)
|
||||
})
|
||||
public String methodParamAsArray2() {
|
||||
return "void test(Object b, @TA @TB String [] a) { }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER,
|
||||
genericLocation = { 0, 0 }, paramIndex = 1),
|
||||
@TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER,
|
||||
genericLocation = { 0, 0 }, paramIndex = 1),
|
||||
@TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER,
|
||||
genericLocation = { 0, 0 }, paramIndex = 1)
|
||||
})
|
||||
public String methodParamAsArray3() {
|
||||
return "void test(Object b, @TA @TB @TC String [] a) { }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = METHOD_FORMAL_PARAMETER, paramIndex = 1),
|
||||
@TADescription(annotation = "TB", type = METHOD_FORMAL_PARAMETER,
|
||||
|
@ -31,118 +31,170 @@ import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
|
||||
*/
|
||||
public class TypeCasts {
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
public String returnObject() {
|
||||
return "Object returnObject() { return (@TA String)null; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TC", type = CAST,
|
||||
genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0, 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String returnObjectArray() {
|
||||
return "Object returnObjectArray() { return (@TC String @TA [] @TB [])null; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String returnObjectGeneric() {
|
||||
return "Object returnObjectGeneric() { return (@TA List<@TB String>)null; }";
|
||||
}
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
public String returnPrim() {
|
||||
return "Object returnPrim() { return (@TA int)0; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String returnPrimArray() {
|
||||
return "Object returnPrimArray() { return (@TB int @TA [])null; }";
|
||||
}
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
public String initObject() {
|
||||
return "void initObject() { Object a = (@TA String)null; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String initObjectArray() {
|
||||
return "void initObjectArray() { Object a = (@TB String @TA [])null; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String initObjectGeneric() {
|
||||
return "void initObjectGeneric() { Object a = (@TA List<@TB String>)null; }";
|
||||
}
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
public String initPrim() {
|
||||
return "void initPrim() { Object a = (@TA int)0; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String initPrimArray() {
|
||||
return "void initPrimArray() { Object a = (@TB int @TA [])null; }";
|
||||
}
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
public String eqtestObject() {
|
||||
return "void eqtestObject() { if (null == (@TA String)null); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String eqtestObjectArray() {
|
||||
return "void eqtestObjectArray() { if (null == (@TB String @TA [])null); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 3, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String eqtestObjectGeneric() {
|
||||
return "void eqtestObjectGeneric() { if (null == (@TA List<@TB String >)null); }";
|
||||
}
|
||||
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
// compiler optimizes away compile time constants casts
|
||||
public String eqtestPrim() {
|
||||
return "void eqtestPrim(int a) { if (0 == (@TA int)a); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE),
|
||||
@TADescription(annotation = "TA", type = CAST, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE)
|
||||
genericLocation = { 0, 0 }, offset = ReferenceInfoUtil.IGNORE_VALUE,
|
||||
typeIndex = 0)
|
||||
})
|
||||
public String eqtestPrimArray() {
|
||||
return "void eqtestPrimArray() { if (null == (@TB int @TA [])null); }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 1),
|
||||
@TADescription(annotation = "TC", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 1,
|
||||
genericLocation = {3, 0})
|
||||
})
|
||||
public String intersection1() {
|
||||
return "void intersection() { Object o = (@TA String & @TB Comparable<@TC String>) null; }";
|
||||
}
|
||||
|
||||
@TADescriptions({
|
||||
@TADescription(annotation = "TA", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 0),
|
||||
@TADescription(annotation = "TB", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 1),
|
||||
@TADescription(annotation = "TC", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 1,
|
||||
genericLocation = {3, 0}),
|
||||
@TADescription(annotation = "TD", type = CAST,
|
||||
offset = ReferenceInfoUtil.IGNORE_VALUE, typeIndex = 2),
|
||||
})
|
||||
public String intersection2() {
|
||||
return "void intersection() { Object o = (@TA String & @TB Comparable<@TC String> & @TD CharSequence) null; }";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user