1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.java.lang.reflect.annotations;
18 
19 import junit.framework.TestCase;
20 
21 import java.lang.annotation.Annotation;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Executable;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Parameter;
26 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationA;
27 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
28 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
29 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
30 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
31 import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
32 
33 import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
34 import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
35 import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
36 import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
37 
38 /**
39  * Tests for the {@link java.lang.reflect.AnnotatedElement} methods from the {@link Parameter}
40  * objects obtained from both {@link Constructor} and {@link Method}.
41  */
42 public class AnnotatedElementParameterTest extends TestCase {
43 
44     private static class MethodClass {
methodWithoutAnnotatedParameters(String parameter1, String parameter2)45         public void methodWithoutAnnotatedParameters(String parameter1, String parameter2) {}
46 
methodWithAnnotatedParameters(@nnotationB @nnotationD String parameter1, @AnnotationC @AnnotationD String parameter2)47         public void methodWithAnnotatedParameters(@AnnotationB @AnnotationD String parameter1,
48                 @AnnotationC @AnnotationD String parameter2) {}
49     }
50 
testMethodParameterAnnotations()51     public void testMethodParameterAnnotations() throws Exception {
52         Class<?> c = MethodClass.class;
53         {
54             Parameter[] parameters = c.getDeclaredMethod(
55                     "methodWithoutAnnotatedParameters", String.class, String.class).getParameters();
56             Parameter parameter0 = parameters[0];
57             checkAnnotatedElementPresentMethods(parameter0);
58 
59             Parameter parameter1 = parameters[1];
60             checkAnnotatedElementPresentMethods(parameter1);
61         }
62         {
63             Parameter[] parameters = c.getDeclaredMethod(
64                     "methodWithAnnotatedParameters", String.class, String.class).getParameters();
65 
66             Parameter parameter0 = parameters[0];
67             checkAnnotatedElementPresentMethods(parameter0, AnnotationB.class, AnnotationD.class);
68 
69             Parameter parameter1 = parameters[1];
70             checkAnnotatedElementPresentMethods(parameter1, AnnotationC.class, AnnotationD.class);
71         }
72     }
73 
74     private static class ConstructorClass {
75         // No annotations.
ConstructorClass(Integer parameter1, Integer parameter2)76         public ConstructorClass(Integer parameter1, Integer parameter2) {}
77 
78         // Annotations.
ConstructorClass(@nnotationB @nnotationD String parameter1, @AnnotationC @AnnotationD String parameter2)79         public ConstructorClass(@AnnotationB @AnnotationD String parameter1,
80                 @AnnotationC @AnnotationD String parameter2) {}
81     }
82 
testConstructorParameterAnnotations()83     public void testConstructorParameterAnnotations() throws Exception {
84         Class<?> c = ConstructorClass.class;
85         {
86             Parameter[] parameters =
87                     c.getDeclaredConstructor(Integer.class, Integer.class).getParameters();
88             Parameter parameter0 = parameters[0];
89             checkAnnotatedElementPresentMethods(parameter0);
90 
91             Parameter parameter1 = parameters[1];
92             checkAnnotatedElementPresentMethods(parameter1);
93         }
94         {
95             Parameter[] parameters =
96                     c.getDeclaredConstructor(String.class, String.class).getParameters();
97 
98             Parameter parameter0 = parameters[0];
99             checkAnnotatedElementPresentMethods(parameter0, AnnotationB.class, AnnotationD.class);
100 
101             Parameter parameter1 = parameters[1];
102             checkAnnotatedElementPresentMethods(parameter1, AnnotationC.class, AnnotationD.class);
103         }
104     }
105 
106     private static class AnnotatedMethodClass {
noAnnotation(String p0)107         void noAnnotation(String p0) {}
108 
multipleAnnotationOddity( @epeated1) @ontainer{@Repeated(2), @Repeated(3)}) String p0)109         void multipleAnnotationOddity(
110                 @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) String p0) {}
111 
multipleAnnotationExplicitSingle(@ontainer{@Repeated(1)}) String p0)112         void multipleAnnotationExplicitSingle(@Container({@Repeated(1)}) String p0) {}
113 
multipleAnnotation(@epeated1) @epeated2) String p0)114         void multipleAnnotation(@Repeated(1) @Repeated(2) String p0) {}
115 
singleAnnotation(@epeated1) String p0)116         void singleAnnotation(@Repeated(1) String p0) {}
117 
staticSingleAnnotation(@epeated1) String p0)118         static void staticSingleAnnotation(@Repeated(1) String p0) {}
119 
getMethodWithoutAnnotations()120         static Method getMethodWithoutAnnotations() throws Exception {
121             return AnnotatedMethodClass.class.getDeclaredMethod("noAnnotation", String.class);
122         }
123 
getMethodMultipleAnnotationOddity()124         static Method getMethodMultipleAnnotationOddity() throws Exception {
125             return AnnotatedMethodClass.class.getDeclaredMethod(
126                     "multipleAnnotationOddity", String.class);
127         }
128 
getMethodMultipleAnnotationExplicitSingle()129         static Method getMethodMultipleAnnotationExplicitSingle() throws Exception {
130             return AnnotatedMethodClass.class.getDeclaredMethod(
131                     "multipleAnnotationExplicitSingle", String.class);
132         }
133 
getMethodMultipleAnnotation()134         static Method getMethodMultipleAnnotation() throws Exception {
135             return AnnotatedMethodClass.class.getDeclaredMethod("multipleAnnotation", String.class);
136         }
137 
getMethodSingleAnnotation()138         static Method getMethodSingleAnnotation() throws Exception {
139             return AnnotatedMethodClass.class.getDeclaredMethod("singleAnnotation", String.class);
140         }
141 
getMethodStaticSingleAnnotation()142         static Method getMethodStaticSingleAnnotation() throws Exception {
143             return AnnotatedMethodClass.class.getDeclaredMethod("staticSingleAnnotation",
144                     String.class);
145         }
146     }
147 
148     private static abstract class AnnotatedMethodAbstractClass {
abstractSingleAnnotation(@epeated1) String p0)149         abstract void abstractSingleAnnotation(@Repeated(1) String p0);
150 
getMethodAbstractSingleAnnotation()151         static Method getMethodAbstractSingleAnnotation() throws Exception {
152             return AnnotatedMethodAbstractClass.class.getDeclaredMethod(
153                     "abstractSingleAnnotation", String.class);
154         }
155     }
156 
157     // Tests for isAnnotationPresent and getDeclaredAnnotation.
testMethodDeclaredAnnotation_repeated()158     public void testMethodDeclaredAnnotation_repeated() throws Exception {
159         Class<? extends Annotation> repeated = Repeated.class;
160         checkParameter0DeclaredAnnotation(
161                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
162                 repeated, null);
163         checkParameter0DeclaredAnnotation(
164                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
165                 repeated, "@Repeated(1)");
166         checkParameter0DeclaredAnnotation(
167                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
168                 repeated, null);
169         checkParameter0DeclaredAnnotation(
170                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
171                 repeated, null);
172         checkParameter0DeclaredAnnotation(
173                 AnnotatedMethodClass.getMethodSingleAnnotation(),
174                 repeated, "@Repeated(1)");
175         checkParameter0DeclaredAnnotation(
176                 AnnotatedMethodClass.getMethodStaticSingleAnnotation(),
177                 repeated, "@Repeated(1)");
178         checkParameter0DeclaredAnnotation(
179                 AnnotatedMethodAbstractClass.getMethodAbstractSingleAnnotation(),
180                 repeated, "@Repeated(1)");
181 
182         Class<? extends Annotation> container = Container.class;
183         checkParameter0DeclaredAnnotation(
184                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
185                 container, null);
186         checkParameter0DeclaredAnnotation(
187                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
188                 container, "@Container({@Repeated(2), @Repeated(3)})");
189         checkParameter0DeclaredAnnotation(
190                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
191                 container, "@Container({@Repeated(1)})");
192         checkParameter0DeclaredAnnotation(
193                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
194                 container, "@Container({@Repeated(1), @Repeated(2)})");
195         checkParameter0DeclaredAnnotation(
196                 AnnotatedMethodClass.getMethodSingleAnnotation(),
197                 container, null);
198     }
199 
200     private static class AnnotatedConstructorClass {
AnnotatedConstructorClass(Boolean p0)201         public AnnotatedConstructorClass(Boolean p0) {}
202 
AnnotatedConstructorClass( @epeated1) @ontainer{@Repeated(2), @Repeated(3)}) Long p0)203         public AnnotatedConstructorClass(
204                 @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) Long p0) {}
205 
AnnotatedConstructorClass(@ontainer{@Repeated(1)}) Double p0)206         public AnnotatedConstructorClass(@Container({@Repeated(1)}) Double p0) {}
207 
AnnotatedConstructorClass(@epeated1) @epeated2) Integer p0)208         public AnnotatedConstructorClass(@Repeated(1) @Repeated(2) Integer p0) {}
209 
AnnotatedConstructorClass(@epeated1) String p0)210         public AnnotatedConstructorClass(@Repeated(1) String p0) {}
211 
getConstructorWithoutAnnotations()212         static Constructor<?> getConstructorWithoutAnnotations() throws Exception {
213             return AnnotatedConstructorClass.class.getDeclaredConstructor(Boolean.class);
214         }
215 
getConstructorMultipleAnnotationOddity()216         static Constructor<?> getConstructorMultipleAnnotationOddity() throws Exception {
217             return AnnotatedConstructorClass.class.getDeclaredConstructor(Long.class);
218         }
219 
getConstructorMultipleAnnotationExplicitSingle()220         static Constructor<?> getConstructorMultipleAnnotationExplicitSingle()
221                 throws Exception {
222             return AnnotatedConstructorClass.class.getDeclaredConstructor(Double.class);
223         }
224 
getConstructorSingleAnnotation()225         static Constructor<?> getConstructorSingleAnnotation() throws Exception {
226             return AnnotatedConstructorClass.class.getDeclaredConstructor(String.class);
227         }
228 
getConstructorMultipleAnnotation()229         static Constructor<?> getConstructorMultipleAnnotation() throws Exception {
230             return AnnotatedConstructorClass.class.getDeclaredConstructor(Integer.class);
231         }
232     }
233 
234     // Tests for isAnnotationPresent and getDeclaredAnnotation.
testConstructorDeclaredAnnotation_repeated()235     public void testConstructorDeclaredAnnotation_repeated() throws Exception {
236         Class<? extends Annotation> repeated = Repeated.class;
237         checkParameter0DeclaredAnnotation(
238                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
239                 repeated, null);
240         checkParameter0DeclaredAnnotation(
241                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
242                 repeated, "@Repeated(1)");
243         checkParameter0DeclaredAnnotation(
244                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
245                 repeated, null);
246         checkParameter0DeclaredAnnotation(
247                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
248                 repeated, null);
249         checkParameter0DeclaredAnnotation(
250                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
251                 repeated, "@Repeated(1)");
252 
253         Class<? extends Annotation> container = Container.class;
254         checkParameter0DeclaredAnnotation(
255                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
256                 container, null);
257         checkParameter0DeclaredAnnotation(
258                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
259                 container, "@Container({@Repeated(2), @Repeated(3)})");
260         checkParameter0DeclaredAnnotation(
261                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
262                 container, "@Container({@Repeated(1)})");
263         checkParameter0DeclaredAnnotation(
264                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
265                 container, "@Container({@Repeated(1), @Repeated(2)})");
266         checkParameter0DeclaredAnnotation(
267                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
268                 container, null);
269     }
270 
checkParameter0DeclaredAnnotation( Executable executable, Class<? extends Annotation> annotationType, String expectedAnnotationString)271     private static void checkParameter0DeclaredAnnotation(
272             Executable executable, Class<? extends Annotation> annotationType,
273             String expectedAnnotationString) throws Exception {
274         Parameter parameter = executable.getParameters()[0];
275 
276         // isAnnotationPresent
277         assertIsAnnotationPresent(parameter, annotationType, expectedAnnotationString != null);
278 
279         // getDeclaredAnnotation
280         assertGetDeclaredAnnotation(parameter, annotationType, expectedAnnotationString);
281     }
282 
testMethodGetDeclaredAnnotationsByType_repeated()283     public void testMethodGetDeclaredAnnotationsByType_repeated() throws Exception {
284         Class<? extends Annotation> repeated = Repeated.class;
285         checkParameter0GetDeclaredAnnotationsByType(
286                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
287                 repeated, EXPECT_EMPTY);
288         checkParameter0GetDeclaredAnnotationsByType(
289                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
290                 repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
291         checkParameter0GetDeclaredAnnotationsByType(
292                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
293                 repeated, "@Repeated(1)");
294         checkParameter0GetDeclaredAnnotationsByType(
295                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
296                 repeated, "@Repeated(1)", "@Repeated(2)");
297         checkParameter0GetDeclaredAnnotationsByType(
298                 AnnotatedMethodClass.getMethodSingleAnnotation(),
299                 repeated, "@Repeated(1)");
300 
301         Class<? extends Annotation> container = Container.class;
302         checkParameter0GetDeclaredAnnotationsByType(
303                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
304                 container, EXPECT_EMPTY);
305         checkParameter0GetDeclaredAnnotationsByType(
306                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
307                 container, "@Container({@Repeated(2), @Repeated(3)})");
308         checkParameter0GetDeclaredAnnotationsByType(
309                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
310                 container, "@Container({@Repeated(1)})");
311         checkParameter0GetDeclaredAnnotationsByType(
312                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
313                 container, "@Container({@Repeated(1), @Repeated(2)})");
314         checkParameter0GetDeclaredAnnotationsByType(
315                 AnnotatedMethodClass.getMethodSingleAnnotation(),
316                 container, EXPECT_EMPTY);
317     }
318 
testConstructorGetDeclaredAnnotationsByType_repeated()319     public void testConstructorGetDeclaredAnnotationsByType_repeated() throws Exception {
320         Class<? extends Annotation> repeated = Repeated.class;
321         checkParameter0GetDeclaredAnnotationsByType(
322                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
323                 repeated, EXPECT_EMPTY);
324         checkParameter0GetDeclaredAnnotationsByType(
325                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
326                 repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
327         checkParameter0GetDeclaredAnnotationsByType(
328                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
329                 repeated, "@Repeated(1)");
330         checkParameter0GetDeclaredAnnotationsByType(
331                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
332                 repeated, "@Repeated(1)", "@Repeated(2)");
333         checkParameter0GetDeclaredAnnotationsByType(
334                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
335                 repeated, "@Repeated(1)");
336 
337         Class<? extends Annotation> container = Container.class;
338         checkParameter0GetDeclaredAnnotationsByType(
339                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
340                 container, EXPECT_EMPTY);
341         checkParameter0GetDeclaredAnnotationsByType(
342                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
343                 container, "@Container({@Repeated(2), @Repeated(3)})");
344         checkParameter0GetDeclaredAnnotationsByType(
345                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
346                 container, "@Container({@Repeated(1)})");
347         checkParameter0GetDeclaredAnnotationsByType(
348                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
349                 container, "@Container({@Repeated(1), @Repeated(2)})");
350         checkParameter0GetDeclaredAnnotationsByType(
351                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
352                 container, EXPECT_EMPTY);
353     }
354 
checkParameter0GetDeclaredAnnotationsByType( Executable executable, Class<? extends Annotation> annotationType, String... expectedAnnotationStrings)355     private static void checkParameter0GetDeclaredAnnotationsByType(
356             Executable executable, Class<? extends Annotation> annotationType,
357             String... expectedAnnotationStrings) throws Exception {
358         Parameter parameter = executable.getParameters()[0];
359         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
360                 parameter, annotationType, expectedAnnotationStrings);
361     }
362 
testMethodGetAnnotationsByType_repeated()363     public void testMethodGetAnnotationsByType_repeated() throws Exception {
364         Class<? extends Annotation> repeated = Repeated.class;
365         checkParameter0GetAnnotationsByType(
366                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
367                 repeated, EXPECT_EMPTY);
368         checkParameter0GetAnnotationsByType(
369                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
370                 repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
371         checkParameter0GetAnnotationsByType(
372                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
373                 repeated, "@Repeated(1)");
374         checkParameter0GetAnnotationsByType(
375                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
376                 repeated, "@Repeated(1)", "@Repeated(2)");
377         checkParameter0GetAnnotationsByType(
378                 AnnotatedMethodClass.getMethodSingleAnnotation(),
379                 repeated, "@Repeated(1)");
380 
381         Class<? extends Annotation> container = Container.class;
382         checkParameter0GetAnnotationsByType(
383                 AnnotatedMethodClass.getMethodWithoutAnnotations(),
384                 container, EXPECT_EMPTY);
385         checkParameter0GetAnnotationsByType(
386                 AnnotatedMethodClass.getMethodMultipleAnnotationOddity(),
387                 container, "@Container({@Repeated(2), @Repeated(3)})");
388         checkParameter0GetAnnotationsByType(
389                 AnnotatedMethodClass.getMethodMultipleAnnotationExplicitSingle(),
390                 container, "@Container({@Repeated(1)})");
391         checkParameter0GetAnnotationsByType(
392                 AnnotatedMethodClass.getMethodMultipleAnnotation(),
393                 container, "@Container({@Repeated(1), @Repeated(2)})");
394         checkParameter0GetAnnotationsByType(
395                 AnnotatedMethodClass.getMethodSingleAnnotation(),
396                 container, EXPECT_EMPTY);
397     }
398 
testConstructorGetAnnotationsByType_repeated()399     public void testConstructorGetAnnotationsByType_repeated() throws Exception {
400         Class<? extends Annotation> repeated = Repeated.class;
401         checkParameter0GetAnnotationsByType(
402                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
403                 repeated, EXPECT_EMPTY);
404         checkParameter0GetAnnotationsByType(
405                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
406                 repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
407         checkParameter0GetAnnotationsByType(
408                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
409                 repeated, "@Repeated(1)");
410         checkParameter0GetAnnotationsByType(
411                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
412                 repeated, "@Repeated(1)", "@Repeated(2)");
413         checkParameter0GetAnnotationsByType(
414                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
415                 repeated, "@Repeated(1)");
416 
417         Class<? extends Annotation> container = Container.class;
418         checkParameter0GetAnnotationsByType(
419                 AnnotatedConstructorClass.getConstructorWithoutAnnotations(),
420                 container, EXPECT_EMPTY);
421         checkParameter0GetAnnotationsByType(
422                 AnnotatedConstructorClass.getConstructorMultipleAnnotationOddity(),
423                 container, "@Container({@Repeated(2), @Repeated(3)})");
424         checkParameter0GetAnnotationsByType(
425                 AnnotatedConstructorClass.getConstructorMultipleAnnotationExplicitSingle(),
426                 container, "@Container({@Repeated(1)})");
427         checkParameter0GetAnnotationsByType(
428                 AnnotatedConstructorClass.getConstructorMultipleAnnotation(),
429                 container, "@Container({@Repeated(1), @Repeated(2)})");
430         checkParameter0GetAnnotationsByType(
431                 AnnotatedConstructorClass.getConstructorSingleAnnotation(),
432                 container, EXPECT_EMPTY);
433     }
434 
checkParameter0GetAnnotationsByType( Executable executable, Class<? extends Annotation> annotationType, String... expectedAnnotationStrings)435     private static void checkParameter0GetAnnotationsByType(
436             Executable executable, Class<? extends Annotation> annotationType,
437             String... expectedAnnotationStrings) throws Exception {
438         Parameter parameter = executable.getParameters()[0];
439         AnnotatedElementTestSupport.assertGetAnnotationsByType(
440                 parameter, annotationType, expectedAnnotationStrings);
441     }
442 
443     /**
444      * As an inner class the constructor will actually have two parameters: the first, referencing
445      * the enclosing object, is inserted by the compiler.
446      */
447     class InnerClass {
InnerClass(@nnotationA String p1)448         InnerClass(@AnnotationA String p1) {}
449     }
450 
451     /** Special case testing for a compiler-generated constructor parameter. JLS 8.8.1, JLS 13.1. */
testImplicitConstructorParameters_innerClass()452     public void testImplicitConstructorParameters_innerClass() throws Exception {
453         Constructor<InnerClass> constructor =
454                 InnerClass.class.getDeclaredConstructor(
455                         AnnotatedElementParameterTest.class, String.class);
456         Parameter[] parameters = constructor.getParameters();
457 
458         // The parameter annotation code behaves as if there are two parameters.
459 
460         // The compiler-generated constructor should have no annotations.
461         Parameter parameter0 = parameters[0];
462         AnnotatedElementTestSupport.assertGetAnnotationsByType(
463                 parameter0, AnnotationA.class, new String[0]);
464         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
465                 parameter0, AnnotationA.class, new String[0]);
466         AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
467                 parameter0, AnnotationA.class, null);
468         AnnotatedElementTestSupport.assertIsAnnotationPresent(parameter0, AnnotationA.class, false);
469 
470         // The annotation should remain on the correct parameter.
471         Parameter parameter1 = parameters[1];
472         AnnotatedElementTestSupport.assertGetAnnotationsByType(
473                 parameter1, AnnotationA.class, new String[] {"@AnnotationA"});
474         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
475                 parameter1, AnnotationA.class, new String[] {"@AnnotationA"});
476         AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
477                 parameter1, AnnotationA.class, "@AnnotationA");
478         AnnotatedElementTestSupport.assertIsAnnotationPresent(
479                 parameter1, AnnotationA.class, true);
480     }
481 
482     static abstract class AnonymousBaseClass {
AnonymousBaseClass(@nnotationA String p1)483         public AnonymousBaseClass(@AnnotationA String p1) {}
484     }
485 
486     /** Special case testing for a compiler-generated constructor parameter. JLS 13.1 */
testImplicitConstructorParameters_anonymousClass()487     public void testImplicitConstructorParameters_anonymousClass() throws Exception {
488         /*
489          * As an anonymous class the constructor will actually have two parameters: the first,
490          * referencing the enclosing object, is inserted by the compiler.
491          */
492         AnonymousBaseClass anonymousClassInstance = new AnonymousBaseClass("p1") {};
493 
494         Constructor<? extends AnonymousBaseClass> constructor =
495                 anonymousClassInstance.getClass().getDeclaredConstructor(
496                         AnnotatedElementParameterTest.class, String.class);
497         Parameter[] parameters = constructor.getParameters();
498         assertEquals(2, parameters.length);
499 
500         // The parameter annotation code behaves as if there are two parameters.
501 
502         // This is the synthetic parameter.
503         Parameter parameter0 = parameters[0];
504         AnnotatedElementTestSupport.assertGetAnnotationsByType(
505                 parameter0, AnnotationA.class, new String[0]);
506         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
507                 parameter0, AnnotationA.class, new String[0]);
508         AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
509                 parameter0, AnnotationA.class, null);
510         AnnotatedElementTestSupport.assertIsAnnotationPresent(parameter0, AnnotationA.class, false);
511 
512         // There's no annotation since we cannot annotate the parameter on the anonymous class.
513         Parameter parameter1 = parameters[1];
514         AnnotatedElementTestSupport.assertGetAnnotationsByType(
515                 parameter1, AnnotationA.class, new String[0]);
516         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
517                 parameter1, AnnotationA.class, new String[0]);
518         AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
519                 parameter1, AnnotationA.class, null);
520         AnnotatedElementTestSupport.assertIsAnnotationPresent(parameter1, AnnotationA.class, false);
521     }
522 
523     /**
524      * A static inner / nested member class will not have synthetic parameters and should behave
525      * like a top-level class.
526      */
527     static class StaticInnerClass {
StaticInnerClass(@nnotationA String p1)528         StaticInnerClass(@AnnotationA String p1) {}
529     }
530 
531     /** Special case testing for a compiler-generated constructor parameter. */
testImplicitConstructorParameters_staticInnerClass()532     public void testImplicitConstructorParameters_staticInnerClass() throws Exception {
533         Constructor<StaticInnerClass> constructor =
534                 StaticInnerClass.class.getDeclaredConstructor(String.class);
535         Parameter[] parameters = constructor.getParameters();
536         assertEquals(1, parameters.length);
537 
538         Parameter parameter0 = parameters[0];
539         AnnotatedElementTestSupport.assertGetAnnotationsByType(
540                 parameter0, AnnotationA.class, new String[] {"@AnnotationA"});
541         AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
542                 parameter0, AnnotationA.class, new String[] {"@AnnotationA"});
543         AnnotatedElementTestSupport.assertGetDeclaredAnnotation(
544                 parameter0, AnnotationA.class, "@AnnotationA");
545         AnnotatedElementTestSupport.assertIsAnnotationPresent(
546                 parameter0, AnnotationA.class, true);
547     }
548 }
549