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