8074977: Constructor.getAnnotatedParameterTypes returns wrong value
Summary: Additional comments from plevart and forax
Reviewed-by: mchung, alanb
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java Tue May 23 16:14:02 2017 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java Tue May 23 14:34:45 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -588,19 +588,18 @@
}
@Override
- void handleParameterNumberMismatch(int resultLength, int numParameters) {
+ boolean handleParameterNumberMismatch(int resultLength, int numParameters) {
Class<?> declaringClass = getDeclaringClass();
if (declaringClass.isEnum() ||
declaringClass.isAnonymousClass() ||
declaringClass.isLocalClass() )
- return ; // Can't do reliable parameter counting
+ return false; // Can't do reliable parameter counting
else {
- if (!declaringClass.isMemberClass() || // top-level
- // Check for the enclosing instance parameter for
- // non-static member classes
- (declaringClass.isMemberClass() &&
- ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
- resultLength + 1 != numParameters) ) {
+ if (declaringClass.isMemberClass() &&
+ ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
+ resultLength + 1 == numParameters) {
+ return true;
+ } else {
throw new AnnotationFormatError(
"Parameter annotations don't match number of parameters");
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java Tue May 23 16:14:02 2017 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java Tue May 23 14:34:45 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -551,12 +551,18 @@
Annotation[][] result = parseParameterAnnotations(parameterAnnotations);
- if (result.length != numParameters)
- handleParameterNumberMismatch(result.length, numParameters);
+ if (result.length != numParameters &&
+ handleParameterNumberMismatch(result.length, numParameters)) {
+ Annotation[][] tmp = new Annotation[result.length+1][];
+ // Shift annotations down one to account for an implicit leading parameter
+ System.arraycopy(result, 0, tmp, 1, result.length);
+ tmp[0] = new Annotation[0];
+ result = tmp;
+ }
return result;
}
- abstract void handleParameterNumberMismatch(int resultLength, int numParameters);
+ abstract boolean handleParameterNumberMismatch(int resultLength, int numParameters);
/**
* {@inheritDoc}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java Tue May 23 16:14:02 2017 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java Tue May 23 14:34:45 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -719,7 +719,7 @@
}
@Override
- void handleParameterNumberMismatch(int resultLength, int numParameters) {
+ boolean handleParameterNumberMismatch(int resultLength, int numParameters) {
throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
}
}
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Tue May 23 16:14:02 2017 -0400
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Tue May 23 14:34:45 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -123,9 +123,30 @@
tmp.add(t);
}
}
+ // If a constructor has a mandated outer this, that parameter
+ // has no annotations and the annotations to parameter mapping
+ // should be offset by 1.
+ boolean offset = false;
+ if (decl instanceof Constructor) {
+ Constructor<?> ctor = (Constructor<?>) decl;
+ Class<?> declaringClass = ctor.getDeclaringClass();
+ if (!declaringClass.isEnum() &&
+ (declaringClass.isMemberClass() &&
+ (declaringClass.getModifiers() & Modifier.STATIC) == 0) ) {
+ offset = true;
+ }
+ }
for (int i = 0; i < size; i++) {
- @SuppressWarnings("unchecked")
- ArrayList<TypeAnnotation> list = l[i];
+ ArrayList<TypeAnnotation> list;
+ if (offset) {
+ @SuppressWarnings("unchecked")
+ ArrayList<TypeAnnotation> tmp = (i == 0) ? null : l[i - 1];
+ list = tmp;
+ } else {
+ @SuppressWarnings("unchecked")
+ ArrayList<TypeAnnotation> tmp = l[i];
+ list = tmp;
+ }
TypeAnnotation[] typeAnnotations;
if (list != null) {
typeAnnotations = list.toArray(new TypeAnnotation[list.size()]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/TestConstructorParameterAnnotations.java Tue May 23 14:34:45 2017 -0700
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2017, 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 8074977
+ * @summary Test consistency of annotations on constructor parameters
+ * @compile TestConstructorParameterAnnotations.java
+ * @run main TestConstructorParameterAnnotations
+ * @compile -parameters TestConstructorParameterAnnotations.java
+ * @run main TestConstructorParameterAnnotations
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/*
+ * Some constructor parameters are <em>mandated</em>; that is, they
+ * are not explicitly present in the source code, but required to be
+ * present by the Java Language Specification. In other cases, some
+ * constructor parameters are not present in the source, but are
+ * synthesized by the compiler as an implementation artifact. There is
+ * not a reliable mechanism to consistently determine whether or not
+ * a parameter is implicit or not.
+ *
+ * (Using the "-parameters" option to javac does emit the information
+ * needed to make a reliably determination, but the information is not
+ * present by default.)
+ *
+ * The lack of such a mechanism causes complications reading parameter
+ * annotations in some cases since annotations for parameters are
+ * written out for the parameters in the source code, but when reading
+ * annotations at runtime all the parameters, including implicit ones,
+ * are present.
+ */
+public class TestConstructorParameterAnnotations {
+ public static void main(String... args) {
+ int errors = 0;
+ Class<?>[] classes = {NestedClass0.class,
+ NestedClass1.class,
+ NestedClass2.class,
+ NestedClass3.class,
+ NestedClass4.class,
+ StaticNestedClass0.class,
+ StaticNestedClass1.class,
+ StaticNestedClass2.class,
+ StaticNestedClass3.class,
+ StaticNestedClass4.class};
+
+ for (Class<?> clazz : classes) {
+ for (Constructor<?> ctor : clazz.getConstructors()) {
+ System.out.println(ctor);
+ errors += checkGetParameterAnnotations(clazz, ctor);
+ errors += checkGetParametersGetAnnotation(clazz, ctor);
+ }
+ }
+
+ if (errors > 0)
+ throw new RuntimeException(errors + " errors.");
+ return;
+ }
+
+ private static int checkGetParameterAnnotations(Class<?> clazz,
+ Constructor<?> ctor) {
+ String annotationString =
+ Arrays.deepToString(ctor.getParameterAnnotations());
+ String expectedString =
+ clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
+
+ if (!Objects.equals(annotationString, expectedString)) {
+ System.err.println("Annotation mismatch on " + ctor +
+ "\n\tExpected:" + expectedString +
+ "\n\tActual: " + annotationString);
+ return 1;
+ }
+ return 0;
+ }
+
+ private static int checkGetParametersGetAnnotation(Class<?> clazz,
+ Constructor<?> ctor) {
+ int errors = 0;
+ int i = 0;
+ ExpectedParameterAnnotations epa =
+ clazz.getAnnotation(ExpectedParameterAnnotations.class);
+
+ for (Parameter param : ctor.getParameters() ) {
+ String annotationString =
+ Objects.toString(param.getAnnotation(MarkerAnnotation.class));
+ String expectedString = epa.value()[i];
+
+ if (!Objects.equals(annotationString, expectedString)) {
+ System.err.println("Annotation mismatch on " + ctor +
+ " on param " + param +
+ "\n\tExpected:" + expectedString +
+ "\n\tActual: " + annotationString);
+ errors++;
+ }
+ i++;
+ }
+ return errors;
+ }
+
+ @ExpectedGetParameterAnnotations("[[]]")
+ @ExpectedParameterAnnotations({"null"})
+ public class NestedClass0 {
+ public NestedClass0() {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[], " +
+ "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)]]")
+ @ExpectedParameterAnnotations({
+ "null",
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)"})
+ public class NestedClass1 {
+ public NestedClass1(@MarkerAnnotation(1) int parameter) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[], " +
+ "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "null",
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)",
+ "null"})
+ public class NestedClass2 {
+ public NestedClass2(@MarkerAnnotation(2) int parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[], " +
+ "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "null",
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)",
+ "null"})
+ public class NestedClass3 {
+ public <P> NestedClass3(@MarkerAnnotation(3) P parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[], " +
+ "[@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "null",
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)",
+ "null"})
+ public class NestedClass4 {
+ public <P, Q> NestedClass4(@MarkerAnnotation(4) P parameter1,
+ Q parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[]")
+ @ExpectedParameterAnnotations({"null"})
+ public static class StaticNestedClass0 {
+ public StaticNestedClass0() {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)]]")
+ @ExpectedParameterAnnotations({
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=1)"})
+ public static class StaticNestedClass1 {
+ public StaticNestedClass1(@MarkerAnnotation(1) int parameter) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=2)",
+ "null"})
+ public static class StaticNestedClass2 {
+ public StaticNestedClass2(@MarkerAnnotation(2) int parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=3)",
+ "null"})
+ public static class StaticNestedClass3 {
+ public <P> StaticNestedClass3(@MarkerAnnotation(3) P parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations(
+ "[[@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)], " +
+ "[]]")
+ @ExpectedParameterAnnotations({
+ "@TestConstructorParameterAnnotations$MarkerAnnotation(value=4)",
+ "null"})
+ public static class StaticNestedClass4 {
+ public <P, Q> StaticNestedClass4(@MarkerAnnotation(4) P parameter1,
+ Q parameter2) {}
+ }
+
+ @Target(ElementType.PARAMETER)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface MarkerAnnotation {
+ int value();
+ }
+
+ /**
+ * String form of expected value of calling
+ * getParameterAnnotations on a constructor.
+ */
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface ExpectedGetParameterAnnotations {
+ String value();
+ }
+
+ /**
+ * String form of expected value of calling
+ * getAnnotation(MarkerAnnotation.class) on each element of the
+ * result of getParameters() on a constructor.
+ */
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface ExpectedParameterAnnotations {
+ String[] value();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/TestConstructorParameterTypeAnnotations.java Tue May 23 14:34:45 2017 -0700
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2017, 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 8074977
+ * @summary Test consistency of annotations on constructor parameters
+ * @compile TestConstructorParameterTypeAnnotations.java
+ * @run main TestConstructorParameterTypeAnnotations
+ * @compile -parameters TestConstructorParameterTypeAnnotations.java
+ * @run main TestConstructorParameterTypeAnnotations
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/*
+ * Some constructor parameters are <em>mandated</em>; that is, they
+ * are not explicitly present in the source code, but required to be
+ * present by the Java Language Specification. In other cases, some
+ * constructor parameters are not present in the source, but are
+ * synthesized by the compiler as an implementation artifact. There is
+ * not a reliable mechanism to consistently determine whether or not
+ * a parameter is implicit or not.
+ *
+ * (Using the "-parameters" option to javac does emit the information
+ * needed to make a reliably determination, but the information is not
+ * present by default.)
+ *
+ * The lack of such a mechanism causes complications reading parameter
+ * annotations in some cases since annotations for parameters are
+ * written out for the parameters in the source code, but when reading
+ * annotations at runtime all the parameters, including implicit ones,
+ * are present.
+ */
+public class TestConstructorParameterTypeAnnotations {
+ public static void main(String... args) {
+ int errors = 0;
+ Class<?>[] classes = {NestedClass0.class,
+ NestedClass1.class,
+ NestedClass2.class,
+ NestedClass3.class,
+ NestedClass4.class,
+ StaticNestedClass0.class,
+ StaticNestedClass1.class,
+ StaticNestedClass2.class };
+
+ for (Class<?> clazz : classes) {
+ for (Constructor<?> ctor : clazz.getConstructors()) {
+ System.out.println(ctor);
+ errors += checkGetParameterAnnotations(clazz, ctor);
+ errors += checkGetAnnotatedParametersGetAnnotation(clazz, ctor);
+ }
+ }
+
+ if (errors > 0)
+ throw new RuntimeException(errors + " errors.");
+ return;
+ }
+
+ private static int checkGetParameterAnnotations(Class<?> clazz,
+ Constructor<?> ctor) {
+ String annotationString =
+ Arrays.deepToString(ctor.getParameterAnnotations());
+ String expectedString =
+ clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
+
+ if (!Objects.equals(annotationString, expectedString)) {
+ System.err.println("Annotation mismatch on " + ctor +
+ "\n\tExpected:" + expectedString +
+ "\n\tActual: " + annotationString);
+ return 1;
+ }
+ return 0;
+ }
+
+ private static int checkGetAnnotatedParametersGetAnnotation(Class<?> clazz,
+ Constructor<?> ctor) {
+ int errors = 0;
+ int i = 0;
+ ExpectedParameterTypeAnnotations epa =
+ clazz.getAnnotation(ExpectedParameterTypeAnnotations.class);
+
+ for (AnnotatedType param : ctor.getAnnotatedParameterTypes() ) {
+ String annotationString =
+ Objects.toString(param.getAnnotation(MarkerTypeAnnotation.class));
+ String expectedString = epa.value()[i];
+
+ if (!Objects.equals(annotationString, expectedString)) {
+ System.err.println("Annotation mismatch on " + ctor +
+ " on param " + param +
+ "\n\tExpected:" + expectedString +
+ "\n\tActual: " + annotationString);
+ errors++;
+ }
+ i++;
+ }
+ return errors;
+ }
+
+ @ExpectedGetParameterAnnotations("[[]]")
+ @ExpectedParameterTypeAnnotations({"null"})
+ public class NestedClass0 {
+ public NestedClass0() {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], []]")
+ @ExpectedParameterTypeAnnotations({
+ "null",
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=1)"})
+ public class NestedClass1 {
+ public NestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], [], []]")
+ @ExpectedParameterTypeAnnotations({
+ "null",
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=2)",
+ "null"})
+ public class NestedClass2 {
+ public NestedClass2(@MarkerTypeAnnotation(2) int parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], [], []]")
+ @ExpectedParameterTypeAnnotations({
+ "null",
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=3)",
+ "null"})
+ public class NestedClass3 {
+ public <P> NestedClass3(@MarkerTypeAnnotation(3) P parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], [], []]")
+ @ExpectedParameterTypeAnnotations({
+ "null",
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=4)",
+ "null"})
+ public class NestedClass4 {
+ public <P, Q> NestedClass4(@MarkerTypeAnnotation(4) P parameter1,
+ Q parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[]")
+ @ExpectedParameterTypeAnnotations({"null"})
+ public static class StaticNestedClass0 {
+ public StaticNestedClass0() {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[]]")
+ @ExpectedParameterTypeAnnotations({
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=1)"})
+ public static class StaticNestedClass1 {
+ public StaticNestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], []]")
+ @ExpectedParameterTypeAnnotations({
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=2)",
+ "null"})
+ public static class StaticNestedClass2 {
+ public StaticNestedClass2(@MarkerTypeAnnotation(2) int parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], []]")
+ @ExpectedParameterTypeAnnotations({
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=3)",
+ "null"})
+ public static class StaticNestedClass3 {
+ public <P> StaticNestedClass3(@MarkerTypeAnnotation(3) P parameter1,
+ int parameter2) {}
+ }
+
+ @ExpectedGetParameterAnnotations("[[], []]")
+ @ExpectedParameterTypeAnnotations({
+ "@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(value=4)",
+ "null"})
+ public static class StaticNestedClass4 {
+ public <P, Q> StaticNestedClass4(@MarkerTypeAnnotation(4) P parameter1,
+ Q parameter2) {}
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface MarkerTypeAnnotation {
+ int value();
+ }
+
+ /**
+ * String form of expected value of calling
+ * getParameterAnnotations on a constructor.
+ */
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface ExpectedGetParameterAnnotations {
+ String value();
+ }
+
+ /**
+ * String form of expected value of calling
+ * getAnnotation(MarkerTypeAnnotation.class) on each element of the
+ * result of getParameters() on a constructor.
+ */
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface ExpectedParameterTypeAnnotations {
+ String[] value();
+ }
+}