提交 c603f18b 编写于 作者: J jfranck

8007073: Implement Core Reflection for Type Annotations on parameters

Reviewed-by: darcy, abuckley
上级 fa79aa0a
......@@ -510,12 +510,12 @@ public abstract class Executable extends AccessibleObject
*/
AnnotatedType getAnnotatedReturnType0(Type returnType) {
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
returnType,
TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE);
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
returnType,
TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN);
}
/**
......@@ -535,12 +535,12 @@ public abstract class Executable extends AccessibleObject
*/
public AnnotatedType getAnnotatedReceiverType() {
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getDeclaringClass(),
TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getDeclaringClass(),
TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
}
/**
......@@ -556,7 +556,13 @@ public abstract class Executable extends AccessibleObject
* @since 1.8
*/
public AnnotatedType[] getAnnotatedParameterTypes() {
throw new UnsupportedOperationException("Not yet");
return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getParameterTypes(),
TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
}
/**
......@@ -573,12 +579,12 @@ public abstract class Executable extends AccessibleObject
*/
public AnnotatedType[] getAnnotatedExceptionTypes() {
return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getGenericExceptionTypes(),
TypeAnnotation.TypeAnnotationTarget.THROWS);
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
this,
getDeclaringClass(),
getGenericExceptionTypes(),
TypeAnnotation.TypeAnnotationTarget.THROWS);
}
}
......@@ -1161,6 +1161,6 @@ class Field extends AccessibleObject implements Member {
this,
getDeclaringClass(),
getGenericType(),
TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE);
TypeAnnotation.TypeAnnotationTarget.FIELD);
}
}
......@@ -200,6 +200,19 @@ public final class Parameter implements AnnotatedElement {
return tmp;
}
/**
* Returns an AnnotatedType object that represents the use of a type to
* specify the type of the formal parameter represented by this Parameter.
*
* @return an {@code AnnotatedType} object representing the use of a type
* to specify the type of the formal parameter represented by this
* Parameter
*/
public AnnotatedType getAnnotatedType() {
// no caching for now
return executable.getAnnotatedParameterTypes()[index];
}
private transient volatile Class<?> parameterClassCache = null;
/**
......
......@@ -83,12 +83,13 @@ public class TypeAnnotation {
CLASS_TYPE_PARAMETER,
METHOD_TYPE_PARAMETER,
CLASS_EXTENDS,
CLASS_IMPLEMENTS,
CLASS_PARAMETER_BOUND,
METHOD_PARAMETER_BOUND,
METHOD_RETURN_TYPE,
METHOD_RECEIVER_TYPE,
FIELD_TYPE,
CLASS_IMPLEMENTS, // Not in the spec
CLASS_TYPE_PARAMETER_BOUND,
METHOD_TYPE_PARAMETER_BOUND,
FIELD,
METHOD_RETURN,
METHOD_RECEIVER,
METHOD_FORMAL_PARAMETER,
THROWS;
}
public static class TypeAnnotationTargetInfo {
......
......@@ -282,10 +282,10 @@ public class TypeAnnotationParser {
AnnotatedElement boundsDecl;
TypeAnnotationTarget target;
if (decl instanceof Class) {
target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND;
target = TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND;
boundsDecl = (Class)decl;
} else {
target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND;
target = TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND;
boundsDecl = (Executable)decl;
}
return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target);
......@@ -371,14 +371,15 @@ public class TypeAnnotationParser {
private static final byte LOCAL_VARIABLE = (byte)0x40;
private static final byte RESOURCE_VARIABLE = (byte)0x41;
private static final byte EXCEPTION_PARAMETER = (byte)0x42;
private static final byte CAST = (byte)0x43;
private static final byte INSTANCEOF = (byte)0x44;
private static final byte NEW = (byte)0x45;
private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46;
private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47;
private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48;
private static final byte METHOD_REFERENCE = (byte)0x49;
private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50;
private static final byte INSTANCEOF = (byte)0x43;
private static final byte NEW = (byte)0x44;
private static final byte CONSTRUCTOR_REFERENCE = (byte)0x45;
private static final byte METHOD_REFERENCE = (byte)0x46;
private static final byte CAST = (byte)0x47;
private static final byte CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = (byte)0x48;
private static final byte METHOD_INVOCATION_TYPE_ARGUMENT = (byte)0x49;
private static final byte CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = (byte)0x4A;
private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x4B;
private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
ConstantPool cp,
......@@ -417,19 +418,20 @@ public class TypeAnnotationParser {
return res;
}} break;
case CLASS_TYPE_PARAMETER_BOUND:
return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf);
return parse2ByteTarget(TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND, buf);
case METHOD_TYPE_PARAMETER_BOUND:
return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf);
return parse2ByteTarget(TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND, buf);
case FIELD:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE);
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD);
case METHOD_RETURN:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE);
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN);
case METHOD_RECEIVER:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE);
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER);
case METHOD_FORMAL_PARAMETER: {
// Todo
byte index = buf.get();
} break;
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_FORMAL_PARAMETER,
index);
} //unreachable break;
case THROWS:
return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
......@@ -445,30 +447,27 @@ public class TypeAnnotationParser {
short varLength = buf.getShort();
short index = buf.getShort();
}
break;
return null;
case EXCEPTION_PARAMETER: {
byte index = buf.get();
} break;
case CAST:
}
return null;
case INSTANCEOF:
case NEW: {
short offset = buf.getShort();
} break;
case CONSTRUCTOR_REFERENCE_RECEIVER:
case METHOD_REFERENCE_RECEIVER: {
case NEW:
case CONSTRUCTOR_REFERENCE:
case METHOD_REFERENCE: {
short offset = buf.getShort();
byte index = buf.get();
} break;
case LAMBDA_FORMAL_PARAMETER: {
byte index = buf.get();
} break;
case METHOD_REFERENCE:
// This one isn't in the spec yet
break;
}
return null;
case CAST:
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT: {
short offset = buf.getShort();
byte index = buf.get();
} break;
}
return null;
default:
// will throw error below
......
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 8004698
* @bug 8004698 8007073
* @summary Unit test for type annotations
*/
......@@ -48,6 +48,8 @@ public class TypeAnnotationReflection {
testParameterizedType();
testNestedParameterizedType();
testWildcardType();
testParameterTypes();
testParameterType();
}
private static void check(boolean b) {
......@@ -359,6 +361,154 @@ public class TypeAnnotationReflection {
t = w.getAnnotatedLowerBounds();
check(t.length == 1);
}
private static void testParameterTypes() throws Exception {
// NO PARAMS
Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
AnnotatedType[] t = m.getAnnotatedParameterTypes();
check(t.length == 0);
// ONLY ANNOTATED PARAM TYPES
Class[] argsArr = {String.class, String.class, String.class};
m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 1);
check(t[0].getAnnotation(TypeAnno.class) != null);
check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t[1].getAnnotations().length == 1);
check(t[1].getAnnotation(TypeAnno.class) != null);
check(t[1].getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
check(t[2].getAnnotations().length == 2);
check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t[2].getAnnotation(TypeAnno.class) != null);
check(t[2].getAnnotation(TypeAnno2.class) != null);
check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// MIXED ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 1);
check(t[0].getAnnotation(TypeAnno.class) != null);
check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t[1].getAnnotations().length == 0);
check(t[1].getAnnotation(TypeAnno.class) == null);
check(t[1].getAnnotation(TypeAnno2.class) == null);
check(t[2].getAnnotations().length == 2);
check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t[2].getAnnotation(TypeAnno.class) != null);
check(t[2].getAnnotation(TypeAnno2.class) != null);
check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// NO ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 0);
check(t[0].getAnnotation(TypeAnno.class) == null);
check(t[0].getAnnotation(TypeAnno2.class) == null);
check(t[1].getAnnotations().length == 0);
check(t[1].getAnnotation(TypeAnno.class) == null);
check(t[1].getAnnotation(TypeAnno2.class) == null);
check(t[2].getAnnotations().length == 0);
check(t[2].getAnnotation(TypeAnno.class) == null);
check(t[2].getAnnotation(TypeAnno2.class) == null);
}
private static void testParameterType() throws Exception {
// NO PARAMS
Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
Parameter[] p = m.getParameters();
check(p.length == 0);
// ONLY ANNOTATED PARAM TYPES
Class[] argsArr = {String.class, String.class, String.class};
m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
AnnotatedType t0 = p[0].getAnnotatedType();
AnnotatedType t1 = p[1].getAnnotatedType();
AnnotatedType t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 1);
check(t0.getAnnotation(TypeAnno.class) != null);
check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t1.getAnnotations().length == 1);
check(t1.getAnnotation(TypeAnno.class) != null);
check(t1.getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
check(t2.getAnnotations().length == 2);
check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t2.getAnnotation(TypeAnno.class) != null);
check(t2.getAnnotation(TypeAnno2.class) != null);
check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// MIXED ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
t0 = p[0].getAnnotatedType();
t1 = p[1].getAnnotatedType();
t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 1);
check(t0.getAnnotation(TypeAnno.class) != null);
check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t1.getAnnotations().length == 0);
check(t1.getAnnotation(TypeAnno.class) == null);
check(t1.getAnnotation(TypeAnno2.class) == null);
check(t2.getAnnotations().length == 2);
check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t2.getAnnotation(TypeAnno.class) != null);
check(t2.getAnnotation(TypeAnno2.class) != null);
check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// NO ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
t0 = p[0].getAnnotatedType();
t1 = p[1].getAnnotatedType();
t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 0);
check(t0.getAnnotation(TypeAnno.class) == null);
check(t0.getAnnotation(TypeAnno2.class) == null);
check(t1.getAnnotations().length == 0);
check(t1.getAnnotation(TypeAnno.class) == null);
check(t1.getAnnotation(TypeAnno2.class) == null);
check(t2.getAnnotations().length == 0);
check(t2.getAnnotation(TypeAnno.class) == null);
check(t2.getAnnotation(TypeAnno2.class) == null);
}
}
class Params {
public void noParams() {}
public void onlyAnnotated(@TypeAnno("1") String s1, @TypeAnno("2") String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
public void mixed(@TypeAnno("1") String s1, String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
public void unAnnotated(String s1, String s2, String s3) {}
}
abstract class TestWildcardType {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册