diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java index 0f3f73e8b65..9628b961f79 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java @@ -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: diff --git a/langtools/src/share/classes/com/sun/tools/classfile/TypeAnnotation.java b/langtools/src/share/classes/com/sun/tools/classfile/TypeAnnotation.java index 0b1a40d6d12..ec842d0e3c1 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/TypeAnnotation.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/TypeAnnotation.java @@ -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; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java b/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java index 59228c9c109..08767493354 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java @@ -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; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index 32a6ffdc8f4..d61a9f66c04 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -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; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index b438b2f1e93..a7ce49e470f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -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 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 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 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 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); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index cc4625635f5..4ade2344b58 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -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); } }; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index c6807953006..0095c48fa14 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -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; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 4061471be55..c0352ea7958 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -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: diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 8c1e3204c5d..f36d161c39e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -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: diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 3d75cee7acb..87441e82b58 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -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 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() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 36e3a100729..3991aaeb55a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -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; } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java index 6f894e7cb62..99aa17a668f 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java @@ -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: diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/LazyConstantValue.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LazyConstantValue.java new file mode 100644 index 00000000000..337ac8bbe75 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/LazyConstantValue.java @@ -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 {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeVariable.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeVariable.java new file mode 100644 index 00000000000..2c83bfef7e0 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/TypeVariable.java @@ -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 cast(TV p) { + return (@TA TV) p; + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) +@interface TA {} + diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java index 38a0395ffab..3650d117ad0 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java @@ -21,6 +21,8 @@ * questions. */ +import java.lang.annotation.*; + /* * @test * @bug 6843077 8006775 @@ -29,7 +31,8 @@ * @compile/fail VoidGenericMethod.java */ class VoidGenericMethod { - public @A void method() { } + public @A void method() { } } +@Target(ElementType.TYPE_USE) @interface A { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Lambda.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Lambda.java new file mode 100644 index 00000000000..2a99420e3ad --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Lambda.java @@ -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 { + void generic(S p1, T p2); + } + + static class LambdaImpl implements LambdaInt { + LambdaImpl(S p1, T p2) {} + public 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 { } diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Lambda.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Lambda.java new file mode 100644 index 00000000000..ddeeb943018 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Lambda.java @@ -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() {" + + " 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 {" + + " public String getName() { return \"Lambda!\"; }" + + "}" + + + "class Test {" + + " java.util.function.Function, 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 {" + + " 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, 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 {" + + " 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 {" + + " 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 {" + + " void generic(S p1, T p2);" + + "}" + + + "class LambdaImpl implements Lambda {" + + " public 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 {" + + " void generic(S p1, T p2);" + + "}" + + + "class LambdaImpl implements Lambda {" + + " LambdaImpl(S p1, T p2) {}" + + " public void generic(S p1, T p2) {}" + + "}" + + + "class Test {" + + " Lambda lambda() {" + + " return LambdaImpl::<@TA Object, @TB Object>new;" + + " }" + + "}"; + } + +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java index c23636c2f82..eb238386127 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java @@ -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, diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java index 84e5e01b358..a50a96411e6 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java @@ -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; }"; + } }