1 /*
2  * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package annotations.classfile;
25 
26 import java.io.*;
27 import java.net.URL;
28 
29 import com.sun.tools.classfile.*;
30 import com.sun.tools.classfile.ConstantPool.InvalidIndex;
31 import com.sun.tools.classfile.ConstantPool.UnexpectedEntry;
32 
33 /**
34  * A class providing utilities for writing tests that inspect class
35  * files directly, looking for specific type annotations.
36  *
37  * Note: this framework does not currently handle repeating
38  * annotations.
39  */
40 public class ClassfileInspector {
41 
42     /**
43      * A group of expected annotations to be found in a given class.
44      * If the class name is null, then the template will be applied to
45      * every class.
46      */
47     public static class Expected {
testMethod()48         /**
49          * The name of the class.  If {@code null} this template will
50          * apply to every class; otherwise, it will only be applied to
51          * the named class.
52          */
53         public final String classname;
54 
55         /**
56          * The expected class annotations.  These will be checked
57          * against the class' attributes.
58          */
59         public final ExpectedAnnotation[] classAnnos;
60 
61         /**
62          * The expected method annotations.  These will be checked
63          * against all methods in the class.
64          */
65         public final ExpectedMethodAnnotation[] methodAnnos;
testMethodCorralled()66 
67         /**
68          * The expected method parameter annotations.  These will be checked
69          * against all methods in the class.
70          */
71         public final ExpectedParameterAnnotation[] methodParamAnnos;
72 
73         /**
74          * The expected field type annotations.  These will be checked
75          * against all fields in the class.
76          */
77         public final ExpectedFieldAnnotation[] fieldAnnos;
testClassCorralled0()78 
79         /**
80          * The expected class type annotations.  These will be checked
81          * against the class' attributes.
82          */
83         public final ExpectedTypeAnnotation[] classTypeAnnos;
84 
85         /**
86          * The expected method type annotations.  These will be checked
87          * against all methods in the class.
88          */
89         public final ExpectedMethodTypeAnnotation[] methodTypeAnnos;
90 
91         /**
92          * The expected field type annotations.  These will be checked
93          * against all fields in the class.
testClassCorralled()94          */
95         public final ExpectedFieldTypeAnnotation[] fieldTypeAnnos;
96 
97         /**
98          * Create an {@code Expected} from all components.
99          *
100          * @param classname The name of the class to match, or {@code
101          *                  null} for all classes.
102          * @param classAnnos The expected class annotations.
103          * @param methodAnnos The expected method annotations.
104          * @param methodParamAnnos The expected method parameter annotations.
105          * @param fieldAnnos The expected field annotations.
106          * @param classTypeAnnos The expected class type annotations.
107          * @param methodTypeAnnos The expected method type annotations.
108          * @param fieldTypeAnnos The expected field type annotations.
109          */
110         public Expected(String classname,
111                         ExpectedAnnotation[] classAnnos,
testClassWithConstructorCorralled()112                         ExpectedMethodAnnotation[] methodAnnos,
113                         ExpectedParameterAnnotation[] methodParamAnnos,
114                         ExpectedFieldAnnotation[] fieldAnnos,
115                         ExpectedTypeAnnotation[] classTypeAnnos,
116                         ExpectedMethodTypeAnnotation[] methodTypeAnnos,
117                         ExpectedFieldTypeAnnotation[] fieldTypeAnnos) {
118             this.classname = classname;
119             this.classAnnos = classAnnos;
120             this.methodAnnos = methodAnnos;
121             this.methodParamAnnos = methodParamAnnos;
122             this.fieldAnnos = fieldAnnos;
123             this.classTypeAnnos = classTypeAnnos;
124             this.methodTypeAnnos = methodTypeAnnos;
125             this.fieldTypeAnnos = fieldTypeAnnos;
126         }
127 
128         /**
129          * Create an {@code Expected} from regular annotation components.
130          *
131          * @param classname The name of the class to match, or {@code
132          *                  null} for all classes.
testInterfaceCorralled()133          * @param classAnnos The expected class annotations.
134          * @param methodAnnos The expected method annotations.
135          * @param methodParamAnnos The expected method parameter annotations.
136          * @param fieldAnnos The expected field annotations.
137          */
138         public Expected(String classname,
139                         ExpectedAnnotation[] classAnnos,
140                         ExpectedMethodAnnotation[] methodAnnos,
141                         ExpectedParameterAnnotation[] methodParamAnnos,
142                         ExpectedFieldAnnotation[] fieldAnnos) {
143             this(classname, classAnnos, methodAnnos, methodParamAnnos,
144                  fieldAnnos, null, null, null);
145         }
146 
147         /**
148          * Create an {@code Expected} from type annotation components.
149          *
testEnumCorralled()150          * @param classname The name of the class to match, or {@code
151          *                  null} for all classes.
152          * @param classTypeAnnos The expected class type annotations.
153          * @param methodTypeAnnos The expected method type annotations.
154          * @param fieldTypeAnnos The expected field type annotations.
155          */
156         public Expected(String classname,
157                         ExpectedTypeAnnotation[] classTypeAnnos,
158                         ExpectedMethodTypeAnnotation[] methodTypeAnnos,
159                         ExpectedFieldTypeAnnotation[] fieldTypeAnnos) {
160             this(classname, null, null, null, null,
161                  classTypeAnnos, methodTypeAnnos, fieldTypeAnnos);
162         }
163 
164         @Override
165         public String toString() {
166             final StringBuilder sb = new StringBuilder();
167             final String newline = System.lineSeparator();
168             sb.append("Expected on class ").append(classname);
169             if (null != classAnnos) {
170                 sb.append(newline).append("Class annotations:").append(newline);
171                 for(ExpectedAnnotation anno : classAnnos) {
172                     sb.append(anno).append(newline);
173                 }
174             }
175             if (null != methodAnnos) {
176                 sb.append(newline).append("Method annotations:").append(newline);
177                 for(ExpectedAnnotation anno : methodAnnos) {
178                     sb.append(anno).append(newline);
179                 }
180             }
181             if (null != methodParamAnnos) {
182                 sb.append(newline).append("Method param annotations:").append(newline);
183                 for(ExpectedAnnotation anno : methodParamAnnos) {
184                     sb.append(anno).append(newline);
testMethodBad()185                 }
186             }
187             if (null != fieldAnnos) {
188                 sb.append(newline).append("Field annotations:").append(newline);
189                 for(ExpectedAnnotation anno : fieldAnnos) {
190                     sb.append(anno).append(newline);
191                 }
192             }
193             if (null != classTypeAnnos) {
194                 sb.append(newline).append("Class type annotations:").append(newline);
195                 for(ExpectedAnnotation anno : classTypeAnnos) {
196                     sb.append(anno).append(newline);
197                 }
198             }
199             if (null != methodTypeAnnos) {
testVar()200                 sb.append(newline).append("Method type annotations:").append(newline);
201                 for(ExpectedAnnotation anno : methodTypeAnnos) {
202                     sb.append(anno).append(newline);
203                 }
204             }
205             if (null != fieldTypeAnnos) {
206                 sb.append(newline).append("Field type annotations:").append(newline);
207                 for(ExpectedAnnotation anno : fieldTypeAnnos) {
208                     sb.append(anno).append(newline);
209                 }
210             }
211             return sb.toString();
212         }
testVarBad()213 
214         /**
215          * See if this template applies to a class.
216          *
217          * @param classname The classname to check.
218          * @return Whether or not this template should apply.
219          */
220         public boolean matchClassName(String classname) {
221             return this.classname == null || this.classname.equals(classname);
222         }
223 
224         /**
225          * After applying the template to all classes, check to see if
226          * any of the expected annotations weren't matched.
227          *
testImport()228          * @return The number of missed matches.
229          */
230         public int check() {
231             int count = 0;
232             if (classAnnos != null) {
233                 for(ExpectedAnnotation expected : classAnnos) {
234                     if (!expected.check()) {
235                         count++;
236                     }
237                 }
238             }
239             if (methodAnnos != null) {
240                 for(ExpectedAnnotation expected : methodAnnos) {
241                     if (!expected.check()) {
242                         count++;
243                     }
244                 }
245             }
246             if (methodParamAnnos != null) {
247                 for(ExpectedAnnotation expected : methodParamAnnos) {
248                     if (!expected.check()) {
249                         count++;
250                     }
251                 }
252             }
253             if (fieldAnnos != null) {
254                 for(ExpectedAnnotation expected : fieldAnnos) {
255                     if (!expected.check()) {
256                         count++;
257                     }
258                 }
259             }
260             if (classTypeAnnos != null) {
261                 for(ExpectedAnnotation expected : classTypeAnnos) {
262                     if (!expected.check()) {
263                         count++;
264                     }
265                 }
266             }
267             if (methodTypeAnnos != null) {
268                 for(ExpectedAnnotation expected : methodTypeAnnos) {
269                     if (!expected.check()) {
270                         count++;
271                     }
272                 }
273             }
274             if (fieldTypeAnnos != null) {
275                 for(ExpectedAnnotation expected : fieldTypeAnnos) {
276                     if (!expected.check()) {
277                         count++;
278                     }
279                 }
280             }
281             return count;
282         }
283     }
284 
285     /**
286      * An expected annotation.  This is both a superclass for
287      * method, field, and type annotations, as well as a class for
288      * annotations on a class.
289      */
290     public static class ExpectedAnnotation {
291         protected int count = 0;
292         protected final String expectedName;
assertWrapperHas(SnippetWrapper sw, String source, Kind kind, String... has)293         protected final int expectedCount;
294         protected final boolean visibility;
295 
296         /**
297          * Create an {@code ExpectedAnnotation} from its
298          * components.  It is usually a better idea to use a {@code
299          * Builder} to do this.
300          *
301          * @param expectedName The expected annotation name.
302          * @param visibility Whether this annotation should be runtime-visible.
303          * @param expectedCount The number of annotations that should
304          *                      be seen.  If 0, this asserts that the
305          *                      described annotation is not present.
306          */
307         public ExpectedAnnotation(String expectedName,
308                                   boolean visibility,
309                                   int expectedCount) {
assertHas(String s, String has)310             this.expectedName = expectedName;
311             this.visibility = visibility;
312             this.expectedCount = expectedCount;
313         }
assertPosition(SnippetWrapper sw, String source, int start, int length)314 
315         @Override
316         public String toString() {
317             final StringBuilder sb = new StringBuilder();
318             sb.append("Expected ");
319             sb.append(expectedCount);
320             sb.append(" annotation ");
321             sb.append(expectedName);
322             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
323             return sb.toString();
324         }
325 
326         /**
327          * See if this template matches the given visibility.
328          *
329          * @param Whether or not the annotation is visible at runtime.
330          * @return Whether or not this template matches the visibility.
331          */
332         public boolean matchVisibility(boolean visibility) {
333             return this.visibility == visibility;
334         }
335 
336         /**
337          * Attempty to match this template against an annotation.  If
338          * it does match, then the match count for the template will
339          * be incremented.  Otherwise, nothing will be done.
340          *
341          * @param anno The annotation to attempt to match.
342          */
343         public void matchAnnotation(ConstantPool cpool,
344                                     Annotation anno) {
345             if (checkMatch(cpool, anno)) {
346                 count++;
347             }
348         }
349 
350         /**
351          * Indicate whether an annotation matches this expected
352          * annotation.
353          *
354          * @param ConstantPool The constant pool to use.
355          * @param anno The annotation to check.
356          * @return Whether the annotation matches.
357          */
358         protected boolean checkMatch(ConstantPool cpool,
359                                      Annotation anno) {
360             try {
361                 return cpool.getUTF8Info(anno.type_index).value.equals("L" + expectedName + ";");
362             } catch (InvalidIndex | UnexpectedEntry e) {
363                 return false;
364             }
365         }
366 
367         /**
368          * After all matching, check to see if the expected number of
369          * matches equals the actual number.  If not, then print a
370          * failure message and return {@code false}.
371          *
372          * @return Whether or not the expected number of matched
373          *         equals the actual number.
374          */
375         public boolean check() {
376             if (count != expectedCount) {
377                 System.err.println(this + ", but saw " + count);
378                 return false;
379             } else {
380                 return true;
381             }
382         }
383     }
384 
385     /**
386      * An annotation found on a method.
387      */
388     public static class ExpectedMethodAnnotation extends ExpectedAnnotation {
389         protected final String methodname;
390 
391         /**
392          * Create an {@code ExpectedMethodAnnotation} from its
393          * components.  It is usually a better idea to use a {@code
394          * Builder} to do this.
395          *
396          * @param methodname The expected method name.
397          * @param expectedName The expected annotation name.
398          * @param visibility Whether this annotation should be runtime-visible.
399          * @param expectedCount The number of annotations that should be seen.
400          */
401         public ExpectedMethodAnnotation(String methodname,
402                                         String expectedName,
403                                         boolean visibility,
404                                         int expectedCount) {
405             super(expectedName, visibility, expectedCount);
406             this.methodname = methodname;
407         }
408 
409         @Override
410         public String toString() {
411             final StringBuilder sb = new StringBuilder();
412             sb.append("Expected ");
413             sb.append(expectedCount);
414             sb.append(" annotation ");
415             sb.append(expectedName);
416             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
417             sb.append(" on method ");
418             sb.append(methodname);
419             return sb.toString();
420         }
421 
422         /**
423          * See if this template applies to a method.
424          *
425          * @param methodname The method name to check.
426          * @return Whether or not this template should apply.
427          */
428         public boolean matchMethodName(String methodname) {
429             return this.methodname.equals(methodname);
430         }
431 
432     }
433 
434     /**
435      * An annotation found on a method parameter.
436      */
437     public static class ExpectedParameterAnnotation
438         extends ExpectedMethodAnnotation {
439         protected final int index;
440 
441         /**
442          * Create an {@code ExpectedParameterAnnotation} from its
443          * components.  It is usually a better idea to use a {@code
444          * Builder} to do this.
445          *
446          * @param methodname The expected method name.
447          * @param index The parameter index.
448          * @param expectedName The expected annotation name.
449          * @param visibility Whether this annotation should be runtime-visible.
450          * @param expectedCount The number of annotations that should be seen.
451          */
452         public ExpectedParameterAnnotation(String methodname,
453                                            int index,
454                                            String expectedName,
455                                            boolean visibility,
456                                            int expectedCount) {
457             super(methodname, expectedName, visibility, expectedCount);
458             this.index = index;
459         }
460 
461         @Override
462         public String toString() {
463             final StringBuilder sb = new StringBuilder();
464             sb.append("Expected ");
465             sb.append(expectedCount);
466             sb.append(" annotation ");
467             sb.append(expectedName);
468             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
469             sb.append(" on method ");
470             sb.append(methodname);
471             sb.append(" parameter ");
472             sb.append(index);
473             return sb.toString();
474         }
475 
476     }
477 
478     /**
479      * An annotation found on a field.
480      */
481     public static class ExpectedFieldAnnotation extends ExpectedAnnotation {
482         private final String fieldname;
483 
484         /**
485          * Create an {@code ExpectedFieldAnnotation} from its
486          * components.  It is usually a better idea to use a {@code
487          * Builder} to do this.
488          *
489          * @param fieldname The expected field name.
490          * @param expectedName The expected annotation name.
491          * @param visibility Whether this annotation should be runtime-visible.
492          * @param expectedCount The number of annotations that should be seen.
493          */
494         public ExpectedFieldAnnotation(String fieldname,
495                                        String expectedName,
496                                        boolean visibility,
497                                        int expectedCount) {
498             super(expectedName, visibility, expectedCount);
499             this.fieldname = fieldname;
500         }
501 
502         @Override
503         public String toString() {
504             final StringBuilder sb = new StringBuilder();
505             sb.append("Expected ").append(expectedCount)
506             .append(" annotation ").append(expectedName)
507             .append(visibility ? ", runtime visibile " : ", runtime invisibile ")
508             .append(" on field ").append(fieldname);
509             return sb.toString();
510         }
511 
512         /**
513          * See if this template applies to a field.
514          *
515          * @param fieldname The field name to check.
516          * @return Whether or not this template should apply.
517          */
518         public boolean matchFieldName(String fieldname) {
519             return this.fieldname.equals(fieldname);
520         }
521 
522     }
523 
524     /**
525      * An expected type annotation.  This is both a superclass for
526      * method and field type annotations, as well as a class for type
527      * annotations on a class.
528      */
529     public static class ExpectedTypeAnnotation extends ExpectedAnnotation {
530         protected final TypeAnnotation.TargetType targetType;
531         protected final int bound_index;
532         protected final int parameter_index;
533         protected final int type_index;
534         protected final int exception_index;
535         protected final TypeAnnotation.Position.TypePathEntry[] typePath;
536 
537         /**
538          * Create an {@code ExpectedTypeAnnotation} from its
539          * components.  It is usually a better idea to use a {@code
540          * Builder} to do this.
541          *
542          * @param expectedName The expected annotation name.
543          * @param visibility Whether this annotation should be runtime-visible.
544          * @param expectedCount The number of annotations that should
545          *                      be seen.  If 0, this asserts that the
546          *                      described annotation is not present.
547          * @param targetType The expected target type.
548          * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
549          * @param parameter_index The expected parameter index, or
550          *                        {@code Integer.MIN_VALUE}.
551          * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
552          * @param exception_index The expected exception index, or
553          *                        {@code Integer.MIN_VALUE}.
554          * @param typePath The expected type path.
555          */
556         public ExpectedTypeAnnotation(String expectedName,
557                                       boolean visibility,
558                                       int expectedCount,
559                                       TypeAnnotation.TargetType targetType,
560                                       int bound_index,
561                                       int parameter_index,
562                                       int type_index,
563                                       int exception_index,
564                                       TypeAnnotation.Position.TypePathEntry... typePath) {
565             super(expectedName, visibility, expectedCount);
566             this.targetType = targetType;
567             this.bound_index = bound_index;
568             this.parameter_index = parameter_index;
569             this.type_index = type_index;
570             this.exception_index = exception_index;
571             this.typePath = typePath;
572         }
573 
574         @Override
575         public String toString() {
576             final StringBuilder sb = new StringBuilder();
577             sb.append("Expected ");
578             sb.append(expectedCount);
579             sb.append(" annotation ");
580             sb.append(expectedName);
581             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
582             sb.append(targetType);
583             sb.append(", bound_index = ");
584             sb.append(bound_index);
585             sb.append(", parameter_index = ");
586             sb.append(parameter_index);
587             sb.append(", type_index = ");
588             sb.append(type_index);
589             sb.append(", exception_index = ");
590             sb.append(exception_index);
591             sb.append(", type_path = [");
592             for(int i = 0; i < typePath.length; i++) {
593                 if (i != 0) {
594                     sb.append(", ");
595                 }
596                 sb.append(typePath[i]);
597             }
598             sb.append("]");
599             return sb.toString();
600         }
601 
602         @Override
603         public void matchAnnotation(ConstantPool cpool,
604                                     Annotation anno) {}
605 
606         public void matchAnnotation(TypeAnnotation anno) {
607             if (checkMatch(anno)) {
608                 count++;
609             }
610         }
611 
612         public boolean checkMatch(TypeAnnotation anno) {
613             boolean matches = checkMatch(anno.constant_pool, anno.annotation);
614 
615             matches = matches && anno.position.type == targetType;
616             matches = matches && anno.position.bound_index == bound_index;
617             matches = matches && anno.position.parameter_index == parameter_index;
618             matches = matches && anno.position.type_index == type_index;
619             matches = matches && anno.position.exception_index == exception_index;
620             matches = matches && anno.position.location.size() == typePath.length;
621 
622             if (matches) {
623                 int i = 0;
624                 for(TypeAnnotation.Position.TypePathEntry entry :
625                          anno.position.location) {
626                     matches = matches && typePath[i++].equals(entry);
627                 }
628             }
629 
630             return matches;
631         }
632 
633         /**
634          * A builder class for creating {@code
635          * ExpectedTypeAnnotation}s in a more convenient fashion.  The
636          * constructor for {@code ExpectedTypeAnnotation} takes a
637          * large number of parameters (by necessity).  This class
638          * allows users to construct a {@code ExpectedTypeAnnotation}s
639          * using only the ones they need.
640          */
641         public static class Builder {
642             protected final String expectedName;
643             protected final boolean visibility;
644             protected final int expectedCount;
645             protected final TypeAnnotation.TargetType targetType;
646             protected int bound_index = Integer.MIN_VALUE;
647             protected int parameter_index = Integer.MIN_VALUE;
648             protected int type_index = Integer.MIN_VALUE;
649             protected int exception_index = Integer.MIN_VALUE;
650             protected TypeAnnotation.Position.TypePathEntry[] typePath =
651                 new TypeAnnotation.Position.TypePathEntry[0];
652 
653             /**
654              * Create a {@code Builder} from the mandatory parameters.
655              *
656              * @param expectedName The expected annotation name.
657              * @param targetType The expected target type.
658              * @param visibility Whether this annotation should be runtime-visible.
659              * @param expectedCount The number of annotations that should be seen.
660              */
661             public Builder(String expectedName,
662                            TypeAnnotation.TargetType targetType,
663                            boolean visibility,
664                            int expectedCount) {
665                 this.expectedName = expectedName;
666                 this.visibility = visibility;
667                 this.expectedCount = expectedCount;
668                 this.targetType = targetType;
669             }
670 
671             /**
672              * Create an {@code ExpectedTypeAnnotation} from all
673              * parameters that have been provided.  The default values
674              * will be used for those that have not.
675              *
676              * @return The cretaed {@code ExpectedTypeAnnotation}.
677              */
678             public ExpectedTypeAnnotation build() {
679                 return new ExpectedTypeAnnotation(expectedName, visibility,
680                                                   expectedCount, targetType,
681                                                   bound_index, parameter_index,
682                                                   type_index, exception_index,
683                                                   typePath);
684             }
685 
686             /**
687              * Provide a bound index parameter.
688              *
689              * @param bound_index The bound_index value.
690              */
691             public Builder setBoundIndex(int bound_index) {
692                 this.bound_index = bound_index;
693                 return this;
694             }
695 
696             /**
697              * Provide a parameter index parameter.
698              *
699              * @param bound_index The parameter_index value.
700              */
701             public Builder setParameterIndex(int parameter_index) {
702                 this.parameter_index = parameter_index;
703                 return this;
704             }
705 
706             /**
707              * Provide a type index parameter.
708              *
709              * @param type_index The type_index value.
710              */
711             public Builder setTypeIndex(int type_index) {
712                 this.type_index = type_index;
713                 return this;
714             }
715 
716             /**
717              * Provide an exception index parameter.
718              *
719              * @param exception_index The exception_index value.
720              */
721             public Builder setExceptionIndex(int exception_index) {
722                 this.exception_index = exception_index;
723                 return this;
724             }
725 
726             /**
727              * Provide a type path parameter.
728              *
729              * @param typePath The type path value.
730              */
731             public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) {
732                 this.typePath = typePath;
733                 return this;
734             }
735         }
736     }
737 
738     /**
739      * A type annotation found on a method.
740      */
741     public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation {
742         private final String methodname;
743 
744         /**
745          * Create an {@code ExpectedMethodTypeAnnotation} from its
746          * components.  It is usually a better idea to use a {@code
747          * Builder} to do this.
748          *
749          * @param methodname The expected method name.
750          * @param expectedName The expected annotation name.
751          * @param visibility Whether this annotation should be runtime-visible.
752          * @param expectedCount The number of annotations that should be seen.
753          * @param targetType The expected target type.
754          * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
755          * @param parameter_index The expected parameter index, or
756          *                        {@code Integer.MIN_VALUE}.
757          * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
758          * @param exception_index The expected exception index, or
759          *                        {@code Integer.MIN_VALUE}.
760          * @param typePath The expected type path.
761          */
762         public ExpectedMethodTypeAnnotation(String methodname,
763                                             String expectedName,
764                                             boolean visibility,
765                                             int expectedCount,
766                                             TypeAnnotation.TargetType targetType,
767                                             int bound_index,
768                                             int parameter_index,
769                                             int type_index,
770                                             int exception_index,
771                                             TypeAnnotation.Position.TypePathEntry... typePath) {
772             super(expectedName, visibility, expectedCount, targetType, bound_index,
773                   parameter_index, type_index, exception_index, typePath);
774             this.methodname = methodname;
775         }
776 
777         @Override
778         public String toString() {
779             final StringBuilder sb = new StringBuilder();
780             sb.append("Expected ");
781             sb.append(expectedCount);
782             sb.append(" annotation ");
783             sb.append(expectedName);
784             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
785             sb.append(targetType);
786             sb.append(", bound_index = ");
787             sb.append(bound_index);
788             sb.append(", parameter_index = ");
789             sb.append(parameter_index);
790             sb.append(", type_index = ");
791             sb.append(type_index);
792             sb.append(", exception_index = ");
793             sb.append(exception_index);
794             sb.append(", type_path = [");
795             for(int i = 0; i < typePath.length; i++) {
796                 if (i != 0) {
797                     sb.append(", ");
798                 }
799                 sb.append(typePath[i]);
800             }
801             sb.append("]");
802             sb.append(" on method ");
803             sb.append(methodname);
804             return sb.toString();
805         }
806 
807         /**
808          * See if this template applies to a method.
809          *
810          * @param methodname The method name to check.
811          * @return Whether or not this template should apply.
812          */
813         public boolean matchMethodName(String methodname) {
814             return this.methodname.equals(methodname);
815         }
816 
817         /**
818          * A builder class for creating {@code
819          * ExpectedMethodTypeAnnotation}s in a more convenient fashion.  The
820          * constructor for {@code ExpectedMethodTypeAnnotation} takes a
821          * large number of parameters (by necessity).  This class
822          * allows users to construct a {@code ExpectedMethodTypeAnnotation}s
823          * using only the ones they need.
824          */
825         public static class Builder extends ExpectedTypeAnnotation.Builder {
826             protected final String methodname;
827 
828             /**
829              * Create a {@code Builder} from the mandatory parameters.
830              *
831              * @param methodname The expected method name.
832              * @param expectedName The expected annotation name.
833              * @param targetType The expected target type.
834              * @param visibility Whether this annotation should be runtime-visible.
835              * @param expectedCount The number of annotations that should be seen.
836              */
837             public Builder(String methodname,
838                            String expectedName,
839                            TypeAnnotation.TargetType targetType,
840                            boolean visibility,
841                            int expectedCount) {
842                 super(expectedName, targetType, visibility, expectedCount);
843                 this.methodname = methodname;
844             }
845 
846             /**
847              * Create an {@code ExpectedMethodTypeAnnotation} from all
848              * parameters that have been provided.  The default values
849              * will be used for those that have not.
850              *
851              * @return The created {@code ExpectedMethodTypeAnnotation}.
852              */
853             @Override
854             public ExpectedMethodTypeAnnotation build() {
855                 return new ExpectedMethodTypeAnnotation(methodname, expectedName,
856                                                         visibility, expectedCount,
857                                                         targetType, bound_index,
858                                                         parameter_index, type_index,
859                                                         exception_index, typePath);
860             }
861         }
862     }
863 
864     /**
865      * A type annotation found on a field.
866      */
867     public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation {
868         private final String fieldname;
869 
870         /**
871          * Create an {@code ExpectedFieldTypeAnnotation} from its
872          * components.  It is usually a better idea to use a {@code
873          * Builder} to do this.
874          *
875          * @param fieldname The expected field name.
876          * @param expectedName The expected annotation name.
877          * @param visibility Whether this annotation should be runtime-visible.
878          * @param expectedCount The number of annotations that should be seen.
879          * @param targetType The expected target type.
880          * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
881          * @param parameter_index The expected parameter index, or
882          *                        {@code Integer.MIN_VALUE}.
883          * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
884          * @param exception_index The expected exception index, or
885          *                        {@code Integer.MIN_VALUE}.
886          * @param typePath The expected type path.
887          */
888         public ExpectedFieldTypeAnnotation(String fieldname,
889                                            String expectedName,
890                                            boolean visibility,
891                                            int expectedCount,
892                                            TypeAnnotation.TargetType targetType,
893                                            int bound_index,
894                                            int parameter_index,
895                                            int type_index,
896                                            int exception_index,
897                                            TypeAnnotation.Position.TypePathEntry... typePath) {
898             super(expectedName, visibility, expectedCount, targetType, bound_index,
899                   parameter_index, type_index, exception_index, typePath);
900             this.fieldname = fieldname;
901         }
902 
903         @Override
904         public String toString() {
905             final StringBuilder sb = new StringBuilder();
906             sb.append("Expected ").append(expectedCount)
907             .append(" annotation ").append(expectedName)
908             .append(visibility ? ", runtime visibile " : ", runtime invisibile ")
909             .append(targetType)
910             .append(", bound_index = ").append(bound_index)
911             .append(", parameter_index = ").append(parameter_index)
912             .append(", type_index = ").append(type_index)
913             .append(", exception_index = ").append(exception_index)
914             .append(", type_path = [");
915 
916             for(int i = 0; i < typePath.length; i++) {
917                 if (i != 0) {
918                     sb.append(", ");
919                 }
920                 sb.append(typePath[i]);
921             }
922             sb.append("]")
923             .append(" on field ").append(fieldname);
924             return sb.toString();
925         }
926 
927         /**
928          * See if this template applies to a field.
929          *
930          * @param fieldname The field name to check.
931          * @return Whether or not this template should apply.
932          */
933         public boolean matchFieldName(String fieldname) {
934             return this.fieldname.equals(fieldname);
935         }
936 
937         /**
938          * A builder class for creating {@code
939          * ExpectedFieldTypeAnnotation}s in a more convenient fashion.  The
940          * constructor for {@code ExpectedFieldTypeAnnotation} takes a
941          * large number of parameters (by necessity).  This class
942          * allows users to construct a {@code ExpectedFieldTypeAnnotation}s
943          * using only the ones they need.
944          */
945         public static class Builder extends ExpectedTypeAnnotation.Builder {
946             protected final String fieldname;
947 
948             /**
949              * Create a {@code Builder} from the mandatory parameters.
950              *
951              * @param fieldname The expected field name.
952              * @param expectedName The expected annotation name.
953              * @param targetType The expected target type.
954              * @param visibility Whether this annotation should be runtime-visible.
955              * @param expectedCount The number of annotations that should be seen.
956              */
957             public Builder(String fieldname,
958                            String expectedName,
959                            TypeAnnotation.TargetType targetType,
960                            boolean visibility,
961                            int expectedCount) {
962                 super(expectedName, targetType, visibility, expectedCount);
963                 this.fieldname = fieldname;
964             }
965 
966             /**
967              * Create an {@code ExpectedFieldTypeAnnotation} from all
968              * parameters that have been provided.  The default values
969              * will be used for those that have not.
970              *
971              * @return The created {@code ExpectedFieldTypeAnnotation}.
972              */
973             @Override
974             public ExpectedFieldTypeAnnotation build() {
975                 return new ExpectedFieldTypeAnnotation(fieldname, expectedName,
976                                                        visibility, expectedCount,
977                                                        targetType, bound_index,
978                                                        parameter_index, type_index,
979                                                        exception_index, typePath);
980             }
981         }
982     }
983 
984     private void matchClassAnnotation(ClassFile classfile,
985                                       ExpectedAnnotation expected)
986         throws ConstantPoolException {
987         for(Attribute attr : classfile.attributes) {
988             attr.accept(annoMatcher(classfile.constant_pool), expected);
989         }
990     }
991 
992     private void matchMethodAnnotation(ClassFile classfile,
993                                        ExpectedMethodAnnotation expected)
994         throws ConstantPoolException {
995         for(Method meth : classfile.methods) {
996             if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
997                 for(Attribute attr : meth.attributes) {
998                     attr.accept(annoMatcher(classfile.constant_pool), expected);
999                 }
1000             }
1001         }
1002     }
1003 
1004     private void matchParameterAnnotation(ClassFile classfile,
1005                                           ExpectedParameterAnnotation expected)
1006         throws ConstantPoolException {
1007         for(Method meth : classfile.methods) {
1008             if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
1009                 for(Attribute attr : meth.attributes) {
1010                     attr.accept(paramMatcher(classfile.constant_pool), expected);
1011                 }
1012             }
1013         }
1014     }
1015 
1016     private void matchFieldAnnotation(ClassFile classfile,
1017                                       ExpectedFieldAnnotation expected)
1018         throws ConstantPoolException {
1019         for(Field field : classfile.fields) {
1020             if (expected.matchFieldName(field.getName(classfile.constant_pool))) {
1021                 for(Attribute attr : field.attributes) {
1022                     attr.accept(annoMatcher(classfile.constant_pool), expected);
1023                 }
1024             }
1025         }
1026     }
1027 
1028     private void matchClassTypeAnnotation(ClassFile classfile,
1029                                           ExpectedTypeAnnotation expected)
1030         throws ConstantPoolException {
1031         for(Attribute attr : classfile.attributes) {
1032             attr.accept(typeAnnoMatcher, expected);
1033         }
1034     }
1035 
1036     private void matchMethodTypeAnnotation(ClassFile classfile,
1037                                            ExpectedMethodTypeAnnotation expected)
1038         throws ConstantPoolException {
1039         for(Method meth : classfile.methods) {
1040             if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
1041                 for(Attribute attr : meth.attributes) {
1042                     attr.accept(typeAnnoMatcher, expected);
1043                 }
1044             }
1045         }
1046     }
1047 
1048     private void matchFieldTypeAnnotation(ClassFile classfile,
1049                                           ExpectedFieldTypeAnnotation expected)
1050         throws ConstantPoolException {
1051         for(Field field : classfile.fields) {
1052             if (expected.matchFieldName(field.getName(classfile.constant_pool))) {
1053                 for(Attribute attr : field.attributes) {
1054                     attr.accept(typeAnnoMatcher, expected);
1055                 }
1056             }
1057         }
1058     }
1059 
1060     private void matchClassAnnotations(ClassFile classfile,
1061                                        ExpectedAnnotation[] expected)
1062         throws ConstantPoolException {
1063         for(ExpectedAnnotation one : expected) {
1064             matchClassAnnotation(classfile, one);
1065         }
1066     }
1067 
1068     private void matchMethodAnnotations(ClassFile classfile,
1069                                         ExpectedMethodAnnotation[] expected)
1070         throws ConstantPoolException {
1071         for(ExpectedMethodAnnotation one : expected) {
1072             matchMethodAnnotation(classfile, one);
1073         }
1074     }
1075 
1076     private void matchParameterAnnotations(ClassFile classfile,
1077                                            ExpectedParameterAnnotation[] expected)
1078         throws ConstantPoolException {
1079         for(ExpectedParameterAnnotation one : expected) {
1080             matchParameterAnnotation(classfile, one);
1081         }
1082     }
1083 
1084     private void matchFieldAnnotations(ClassFile classfile,
1085                                        ExpectedFieldAnnotation[] expected)
1086         throws ConstantPoolException {
1087         for(ExpectedFieldAnnotation one : expected) {
1088             matchFieldAnnotation(classfile, one);
1089         }
1090     }
1091 
1092     private void matchClassTypeAnnotations(ClassFile classfile,
1093                                            ExpectedTypeAnnotation[] expected)
1094         throws ConstantPoolException {
1095         for(ExpectedTypeAnnotation one : expected) {
1096             matchClassTypeAnnotation(classfile, one);
1097         }
1098     }
1099 
1100     private void matchMethodTypeAnnotations(ClassFile classfile,
1101                                             ExpectedMethodTypeAnnotation[] expected)
1102         throws ConstantPoolException {
1103         for(ExpectedMethodTypeAnnotation one : expected) {
1104             matchMethodTypeAnnotation(classfile, one);
1105         }
1106     }
1107 
1108     private void matchFieldTypeAnnotations(ClassFile classfile,
1109                                            ExpectedFieldTypeAnnotation[] expected)
1110         throws ConstantPoolException {
1111         for(ExpectedFieldTypeAnnotation one : expected) {
1112             matchFieldTypeAnnotation(classfile, one);
1113         }
1114     }
1115 
1116     /**
1117      * Run a template on a single {@code ClassFile}.
1118      *
1119      * @param classfile The {@code ClassFile} on which to run tests.
1120      * @param expected The expected annotation template.
1121      */
1122     public void run(ClassFile classfile,
1123                     Expected... expected)
1124             throws ConstantPoolException {
1125         run(new ClassFile[] { classfile }, expected);
1126     }
1127 
1128     /**
1129      * Run a template on multiple {@code ClassFile}s.
1130      *
1131      * @param classfile The {@code ClassFile}s on which to run tests.
1132      * @param expected The expected annotation template.
1133      */
1134     public void run(ClassFile[] classfiles,
1135                     Expected... expected)
1136             throws ConstantPoolException {
1137         for(ClassFile classfile : classfiles) {
1138             for(Expected one : expected) {
1139                 if (one.matchClassName(classfile.getName())) {
1140                     if (one.classAnnos != null)
1141                         matchClassAnnotations(classfile, one.classAnnos);
1142                     if (one.methodAnnos != null)
1143                         matchMethodAnnotations(classfile, one.methodAnnos);
1144                     if (one.methodParamAnnos != null)
1145                         matchParameterAnnotations(classfile, one.methodParamAnnos);
1146                     if (one.fieldAnnos != null)
1147                         matchFieldAnnotations(classfile, one.fieldAnnos);
1148                     if (one.classTypeAnnos != null)
1149                         matchClassTypeAnnotations(classfile, one.classTypeAnnos);
1150                     if (one.methodTypeAnnos != null)
1151                         matchMethodTypeAnnotations(classfile, one.methodTypeAnnos);
1152                     if (one.fieldTypeAnnos != null)
1153                         matchFieldTypeAnnotations(classfile, one.fieldTypeAnnos);
1154                 }
1155             }
1156         }
1157         int count = 0;
1158         for (Expected one : expected) {
1159             count += one.check();
1160         }
1161 
1162         if (count != 0) {
1163             throw new RuntimeException(count + " errors occurred in test");
1164         }
1165     }
1166 
1167     /**
1168      * Get a {@code ClassFile} from its file name.
1169      *
1170      * @param name The class' file name.
1171      * @param host A class in the same package.
1172      * @return The {@code ClassFile}
1173      */
1174     public static ClassFile getClassFile(String name,
1175                                          Class<?> host)
1176         throws IOException, ConstantPoolException {
1177         final URL url = host.getResource(name);
1178         try (InputStream in = url.openStream()) {
1179             return ClassFile.read(in);
1180         }
1181     }
1182 
1183     private static class AbstractAttributeVisitor<T> implements Attribute.Visitor<Void, T> {
1184 
1185         @Override
1186         public Void visitDefault(DefaultAttribute attr, T p) {
1187             return null;
1188         }
1189 
1190         @Override
1191         public Void visitAnnotationDefault(AnnotationDefault_attribute attr, T p) {
1192             return null;
1193         }
1194 
1195         @Override
1196         public Void visitBootstrapMethods(BootstrapMethods_attribute attr, T p) {
1197             return null;
1198         }
1199 
1200         @Override
1201         public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, T p) {
1202             return null;
1203         }
1204 
1205         @Override
1206         public Void visitCode(Code_attribute attr, T p) {
1207             return null;
1208         }
1209 
1210         @Override
1211         public Void visitCompilationID(CompilationID_attribute attr, T p) {
1212             return null;
1213         }
1214 
1215         @Override
1216         public Void visitConstantValue(ConstantValue_attribute attr, T p) {
1217             return null;
1218         }
1219 
1220         @Override
1221         public Void visitDeprecated(Deprecated_attribute attr, T p) {
1222             return null;
1223         }
1224 
1225         @Override
1226         public Void visitEnclosingMethod(EnclosingMethod_attribute attr, T p) {
1227             return null;
1228         }
1229 
1230         @Override
1231         public Void visitExceptions(Exceptions_attribute attr, T p) {
1232             return null;
1233         }
1234 
1235         @Override
1236         public Void visitInnerClasses(InnerClasses_attribute attr, T p) {
1237             return null;
1238         }
1239 
1240         @Override
1241         public Void visitLineNumberTable(LineNumberTable_attribute attr, T p) {
1242             return null;
1243         }
1244 
1245         @Override
1246         public Void visitLocalVariableTable(LocalVariableTable_attribute attr, T p) {
1247             return null;
1248         }
1249 
1250         @Override
1251         public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, T p) {
1252             return null;
1253         }
1254 
1255         @Override
1256           public Void visitNestHost(NestHost_attribute attr, T p) {
1257             return null;
1258         }
1259 
1260         @Override
1261         public Void visitMethodParameters(MethodParameters_attribute attr, T p) {
1262             return null;
1263         }
1264 
1265         @Override
1266         public Void visitModule(Module_attribute attr, T p) {
1267             return null;
1268         }
1269 
1270         @Override
1271         public Void visitModuleHashes(ModuleHashes_attribute attr, T p) {
1272             return null;
1273         }
1274 
1275         @Override
1276         public Void visitModuleMainClass(ModuleMainClass_attribute attr, T p) {
1277             return null;
1278         }
1279 
1280         @Override
1281         public Void visitModulePackages(ModulePackages_attribute attr, T p) {
1282             return null;
1283         }
1284 
1285         @Override
1286         public Void visitModuleResolution(ModuleResolution_attribute attr, T p) {
1287             return null;
1288         }
1289 
1290         @Override
1291         public Void visitModuleTarget(ModuleTarget_attribute attr, T p) {
1292             return null;
1293         }
1294 
1295         @Override
1296         public Void visitNestMembers(NestMembers_attribute attr, T p) {
1297             return null;
1298         }
1299 
1300         @Override
1301         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, T p) {
1302             return null;
1303         }
1304 
1305         @Override
1306         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, T p) {
1307             return null;
1308         }
1309 
1310         @Override
1311         public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, T p) {
1312             return null;
1313         }
1314 
1315         @Override
1316         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, T p) {
1317             return null;
1318         }
1319 
1320         @Override
1321         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, T p) {
1322             return null;
1323         }
1324 
1325         @Override
1326         public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, T p) {
1327             return null;
1328         }
1329 
1330         @Override
1331         public Void visitSignature(Signature_attribute attr, T p) {
1332             return null;
1333         }
1334 
1335         @Override
1336         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, T p) {
1337             return null;
1338         }
1339 
1340         @Override
1341         public Void visitSourceFile(SourceFile_attribute attr, T p) {
1342             return null;
1343         }
1344 
1345         @Override
1346         public Void visitSourceID(SourceID_attribute attr, T p) {
1347             return null;
1348         }
1349 
1350         @Override
1351         public Void visitStackMap(StackMap_attribute attr, T p) {
1352             return null;
1353         }
1354 
1355         @Override
1356         public Void visitStackMapTable(StackMapTable_attribute attr, T p) {
1357             return null;
1358         }
1359 
1360         @Override
1361         public Void visitSynthetic(Synthetic_attribute attr, T p) {
1362             return null;
1363         }
1364 
1365         @Override
1366         public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, T p) {
1367             return null;
1368         }
1369 
1370         @Override
1371         public Void visitRecord(Record_attribute attr, T p) {
1372             return null;
1373         }
1374     }
1375 
1376     private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher
1377             = new AbstractAttributeVisitor<ExpectedTypeAnnotation>() {
1378 
1379                 @Override
1380                 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
1381                         ExpectedTypeAnnotation expected) {
1382                     if (expected.matchVisibility(true)) {
1383                         for (TypeAnnotation anno : attr.annotations) {
1384                             expected.matchAnnotation(anno);
1385                         }
1386                     }
1387 
1388                     return null;
1389                 }
1390 
1391                 @Override
1392                 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
1393                         ExpectedTypeAnnotation expected) {
1394                     if (expected.matchVisibility(false)) {
1395                         for (TypeAnnotation anno : attr.annotations) {
1396                             expected.matchAnnotation(anno);
1397                         }
1398                     }
1399 
1400                     return null;
1401                 }
1402             };
1403 
1404     private static Attribute.Visitor<Void, ExpectedAnnotation> annoMatcher(ConstantPool cpool) {
1405         return new AbstractAttributeVisitor<ExpectedAnnotation>() {
1406 
1407             @Override
1408             public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
1409                                                        ExpectedAnnotation expected) {
1410                 if (expected.matchVisibility(true)) {
1411                     for(Annotation anno : attr.annotations) {
1412                         expected.matchAnnotation(cpool, anno);
1413                     }
1414                 }
1415 
1416                 return null;
1417             }
1418 
1419             @Override
1420             public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
1421                                                          ExpectedAnnotation expected) {
1422                 if (expected.matchVisibility(false)) {
1423                     for(Annotation anno : attr.annotations) {
1424                         expected.matchAnnotation(cpool, anno);
1425                     }
1426                 }
1427 
1428                 return null;
1429             }
1430         };
1431     }
1432 
1433     private static Attribute.Visitor<Void, ExpectedParameterAnnotation> paramMatcher(ConstantPool cpool) {
1434         return new AbstractAttributeVisitor<ExpectedParameterAnnotation>() {
1435 
1436             @Override
1437             public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
1438                                                                 ExpectedParameterAnnotation expected) {
1439                 if (expected.matchVisibility(true)) {
1440                     if (expected.index < attr.parameter_annotations.length) {
1441                         for(Annotation anno :
1442                                 attr.parameter_annotations[expected.index]) {
1443                             expected.matchAnnotation(cpool, anno);
1444                         }
1445                     }
1446                 }
1447 
1448                 return null;
1449             }
1450 
1451             @Override
1452             public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
1453                                                                   ExpectedParameterAnnotation expected) {
1454                 if (expected.matchVisibility(false)) {
1455                     if (expected.index < attr.parameter_annotations.length) {
1456                         for(Annotation anno :
1457                                 attr.parameter_annotations[expected.index]) {
1458                             expected.matchAnnotation(cpool, anno);
1459                         }
1460                     }
1461                 }
1462 
1463                 return null;
1464             }
1465         };
1466     }
1467 }
1468