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