ClassfileInspector.java revision 3792:d516975e8110
1251875Speter/* 2251875Speter * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3251875Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4251875Speter * 5251875Speter * This code is free software; you can redistribute it and/or modify it 6251875Speter * under the terms of the GNU General Public License version 2 only, as 7251875Speter * published by the Free Software Foundation. 8251875Speter * 9251875Speter * This code is distributed in the hope that it will be useful, but WITHOUT 10251875Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11251875Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12251875Speter * version 2 for more details (a copy is included in the LICENSE file that 13251875Speter * accompanied this code). 14251875Speter * 15251875Speter * You should have received a copy of the GNU General Public License version 16251875Speter * 2 along with this work; if not, write to the Free Software Foundation, 17251875Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18251875Speter * 19251875Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20251875Speter * or visit www.oracle.com if you need additional information or have any 21251875Speter * questions. 22251875Speter */ 23251875Speter 24251875Speterpackage annotations.classfile; 25251875Speter 26251875Speterimport java.io.*; 27251875Speterimport java.net.URL; 28251875Speter 29251875Speterimport com.sun.tools.classfile.*; 30251875Speterimport com.sun.tools.classfile.ConstantPool.InvalidIndex; 31251875Speterimport com.sun.tools.classfile.ConstantPool.UnexpectedEntry; 32251875Speter 33251875Speter/** 34251875Speter * A class providing utilities for writing tests that inspect class 35251875Speter * files directly, looking for specific type annotations. 36251875Speter * 37251875Speter * Note: this framework does not currently handle repeating 38251875Speter * annotations. 39251875Speter */ 40251875Speterpublic class ClassfileInspector { 41251875Speter 42251875Speter /** 43251875Speter * A group of expected annotations to be found in a given class. 44251875Speter * If the class name is null, then the template will be applied to 45251875Speter * every class. 46251875Speter */ 47251875Speter public static class Expected { 48251875Speter /** 49251875Speter * The name of the class. If {@code null} this template will 50251875Speter * apply to every class; otherwise, it will only be applied to 51251875Speter * the named class. 52251875Speter */ 53251875Speter public final String classname; 54251875Speter 55251875Speter /** 56251875Speter * The expected class annotations. These will be checked 57251875Speter * against the class' attributes. 58251875Speter */ 59251875Speter public final ExpectedAnnotation[] classAnnos; 60251875Speter 61251875Speter /** 62251875Speter * The expected method annotations. These will be checked 63251875Speter * against all methods in the class. 64251875Speter */ 65251875Speter public final ExpectedMethodAnnotation[] methodAnnos; 66251875Speter 67251875Speter /** 68251875Speter * The expected method parameter annotations. These will be checked 69251875Speter * against all methods in the class. 70251875Speter */ 71251875Speter public final ExpectedParameterAnnotation[] methodParamAnnos; 72251875Speter 73251875Speter /** 74251875Speter * The expected field type annotations. These will be checked 75251875Speter * against all fields in the class. 76251875Speter */ 77251875Speter public final ExpectedFieldAnnotation[] fieldAnnos; 78251875Speter 79251875Speter /** 80251875Speter * The expected class type annotations. These will be checked 81251875Speter * against the class' attributes. 82251875Speter */ 83251875Speter public final ExpectedTypeAnnotation[] classTypeAnnos; 84251875Speter 85251875Speter /** 86251875Speter * The expected method type annotations. These will be checked 87251875Speter * against all methods in the class. 88251875Speter */ 89251875Speter public final ExpectedMethodTypeAnnotation[] methodTypeAnnos; 90251875Speter 91251875Speter /** 92251875Speter * The expected field type annotations. These will be checked 93251875Speter * against all fields in the class. 94251875Speter */ 95251875Speter public final ExpectedFieldTypeAnnotation[] fieldTypeAnnos; 96251875Speter 97251875Speter /** 98251875Speter * Create an {@code Expected} from all components. 99251875Speter * 100251875Speter * @param classname The name of the class to match, or {@code 101251875Speter * null} for all classes. 102251875Speter * @param classAnnos The expected class annotations. 103251875Speter * @param methodAnnos The expected method annotations. 104251875Speter * @param methodParamAnnos The expected method parameter annotations. 105251875Speter * @param fieldAnnos The expected field annotations. 106251875Speter * @param classTypeAnnos The expected class type annotations. 107251875Speter * @param methodTypeAnnos The expected method type annotations. 108251875Speter * @param fieldTypeAnnos The expected field type annotations. 109251875Speter */ 110251875Speter public Expected(String classname, 111251875Speter ExpectedAnnotation[] classAnnos, 112251875Speter ExpectedMethodAnnotation[] methodAnnos, 113251875Speter ExpectedParameterAnnotation[] methodParamAnnos, 114251875Speter ExpectedFieldAnnotation[] fieldAnnos, 115251875Speter ExpectedTypeAnnotation[] classTypeAnnos, 116251875Speter ExpectedMethodTypeAnnotation[] methodTypeAnnos, 117251875Speter ExpectedFieldTypeAnnotation[] fieldTypeAnnos) { 118251875Speter this.classname = classname; 119251875Speter this.classAnnos = classAnnos; 120251875Speter this.methodAnnos = methodAnnos; 121251875Speter this.methodParamAnnos = methodParamAnnos; 122251875Speter this.fieldAnnos = fieldAnnos; 123251875Speter this.classTypeAnnos = classTypeAnnos; 124251875Speter this.methodTypeAnnos = methodTypeAnnos; 125251875Speter this.fieldTypeAnnos = fieldTypeAnnos; 126251875Speter } 127251875Speter 128251875Speter /** 129251875Speter * Create an {@code Expected} from regular annotation components. 130251875Speter * 131251875Speter * @param classname The name of the class to match, or {@code 132251875Speter * null} for all classes. 133251875Speter * @param classAnnos The expected class annotations. 134251875Speter * @param methodAnnos The expected method annotations. 135251875Speter * @param methodParamAnnos The expected method parameter annotations. 136251875Speter * @param fieldAnnos The expected field annotations. 137251875Speter */ 138251875Speter public Expected(String classname, 139251875Speter ExpectedAnnotation[] classAnnos, 140251875Speter ExpectedMethodAnnotation[] methodAnnos, 141251875Speter ExpectedParameterAnnotation[] methodParamAnnos, 142251875Speter ExpectedFieldAnnotation[] fieldAnnos) { 143251875Speter this(classname, classAnnos, methodAnnos, methodParamAnnos, 144251875Speter fieldAnnos, null, null, null); 145251875Speter } 146251875Speter 147251875Speter /** 148251875Speter * Create an {@code Expected} from type annotation components. 149251875Speter * 150251875Speter * @param classname The name of the class to match, or {@code 151251875Speter * null} for all classes. 152251875Speter * @param classTypeAnnos The expected class type annotations. 153251875Speter * @param methodTypeAnnos The expected method type annotations. 154251875Speter * @param fieldTypeAnnos The expected field type annotations. 155251875Speter */ 156251875Speter public Expected(String classname, 157251875Speter ExpectedTypeAnnotation[] classTypeAnnos, 158251875Speter ExpectedMethodTypeAnnotation[] methodTypeAnnos, 159251875Speter ExpectedFieldTypeAnnotation[] fieldTypeAnnos) { 160251875Speter this(classname, null, null, null, null, 161251875Speter classTypeAnnos, methodTypeAnnos, fieldTypeAnnos); 162251875Speter } 163251875Speter 164251875Speter @Override 165251875Speter public String toString() { 166251875Speter final StringBuilder sb = new StringBuilder(); 167251875Speter final String newline = System.lineSeparator(); 168251875Speter sb.append("Expected on class ").append(classname); 169251875Speter if (null != classAnnos) { 170251875Speter sb.append(newline).append("Class annotations:").append(newline); 171251875Speter for(ExpectedAnnotation anno : classAnnos) { 172251875Speter sb.append(anno).append(newline); 173251875Speter } 174251875Speter } 175251875Speter if (null != methodAnnos) { 176251875Speter sb.append(newline).append("Method annotations:").append(newline); 177253734Speter for(ExpectedAnnotation anno : methodAnnos) { 178253734Speter sb.append(anno).append(newline); 179253734Speter } 180253734Speter } 181253734Speter if (null != methodParamAnnos) { 182253734Speter sb.append(newline).append("Method param annotations:").append(newline); 183253734Speter for(ExpectedAnnotation anno : methodParamAnnos) { 184253734Speter sb.append(anno).append(newline); 185251875Speter } 186251875Speter } 187251875Speter if (null != fieldAnnos) { 188251875Speter sb.append(newline).append("Field annotations:").append(newline); 189251875Speter for(ExpectedAnnotation anno : fieldAnnos) { 190251875Speter sb.append(anno).append(newline); 191251875Speter } 192251875Speter } 193251875Speter if (null != classTypeAnnos) { 194251875Speter sb.append(newline).append("Class type annotations:").append(newline); 195251875Speter for(ExpectedAnnotation anno : classTypeAnnos) { 196251875Speter sb.append(anno).append(newline); 197251875Speter } 198251875Speter } 199251875Speter if (null != methodTypeAnnos) { 200251875Speter sb.append(newline).append("Method type annotations:").append(newline); 201251875Speter for(ExpectedAnnotation anno : methodTypeAnnos) { 202251875Speter sb.append(anno).append(newline); 203251875Speter } 204251875Speter } 205251875Speter if (null != fieldTypeAnnos) { 206251875Speter sb.append(newline).append("Field type annotations:").append(newline); 207251875Speter for(ExpectedAnnotation anno : fieldTypeAnnos) { 208251875Speter sb.append(anno).append(newline); 209251875Speter } 210251875Speter } 211251875Speter return sb.toString(); 212251875Speter } 213251875Speter 214251875Speter /** 215251875Speter * See if this template applies to a class. 216251875Speter * 217251875Speter * @param classname The classname to check. 218251875Speter * @return Whether or not this template should apply. 219251875Speter */ 220251875Speter public boolean matchClassName(String classname) { 221251875Speter return this.classname == null || this.classname.equals(classname); 222251875Speter } 223251875Speter 224251875Speter /** 225251875Speter * After applying the template to all classes, check to see if 226251875Speter * any of the expected annotations weren't matched. 227251875Speter * 228251875Speter * @return The number of missed matches. 229251875Speter */ 230251875Speter public int check() { 231251875Speter int count = 0; 232251875Speter if (classAnnos != null) { 233251875Speter for(ExpectedAnnotation expected : classAnnos) { 234251875Speter if (!expected.check()) { 235251875Speter count++; 236251875Speter } 237251875Speter } 238251875Speter } 239251875Speter if (methodAnnos != null) { 240251875Speter for(ExpectedAnnotation expected : methodAnnos) { 241251875Speter if (!expected.check()) { 242251875Speter count++; 243251875Speter } 244251875Speter } 245251875Speter } 246251875Speter if (methodParamAnnos != null) { 247251875Speter for(ExpectedAnnotation expected : methodParamAnnos) { 248251875Speter if (!expected.check()) { 249251875Speter count++; 250251875Speter } 251251875Speter } 252251875Speter } 253251875Speter if (fieldAnnos != null) { 254251875Speter for(ExpectedAnnotation expected : fieldAnnos) { 255253734Speter if (!expected.check()) { 256251875Speter count++; 257251875Speter } 258251875Speter } 259251875Speter } 260251875Speter if (classTypeAnnos != null) { 261251875Speter for(ExpectedAnnotation expected : classTypeAnnos) { 262251875Speter if (!expected.check()) { 263251875Speter count++; 264251875Speter } 265251875Speter } 266251875Speter } 267251875Speter if (methodTypeAnnos != null) { 268251875Speter for(ExpectedAnnotation expected : methodTypeAnnos) { 269251875Speter if (!expected.check()) { 270251875Speter count++; 271251875Speter } 272251875Speter } 273251875Speter } 274251875Speter if (fieldTypeAnnos != null) { 275251875Speter for(ExpectedAnnotation expected : fieldTypeAnnos) { 276251875Speter if (!expected.check()) { 277251875Speter count++; 278251875Speter } 279251875Speter } 280251875Speter } 281251875Speter return count; 282251875Speter } 283251875Speter } 284251875Speter 285251875Speter /** 286251875Speter * An expected annotation. This is both a superclass for 287251875Speter * method, field, and type annotations, as well as a class for 288251875Speter * annotations on a class. 289251875Speter */ 290251875Speter public static class ExpectedAnnotation { 291251875Speter protected int count = 0; 292251875Speter protected final String expectedName; 293251875Speter protected final int expectedCount; 294251875Speter protected final boolean visibility; 295251875Speter 296251875Speter /** 297251875Speter * Create an {@code ExpectedAnnotation} from its 298251875Speter * components. It is usually a better idea to use a {@code 299251875Speter * Builder} to do this. 300251875Speter * 301251875Speter * @param expectedName The expected annotation name. 302251875Speter * @param visibility Whether this annotation should be runtime-visible. 303251875Speter * @param expectedCount The number of annotations that should 304251875Speter * be seen. If 0, this asserts that the 305251875Speter * described annotation is not present. 306251875Speter */ 307251875Speter public ExpectedAnnotation(String expectedName, 308251875Speter boolean visibility, 309251875Speter int expectedCount) { 310251875Speter this.expectedName = expectedName; 311251875Speter this.visibility = visibility; 312251875Speter this.expectedCount = expectedCount; 313251875Speter } 314251875Speter 315251875Speter @Override 316251875Speter public String toString() { 317251875Speter final StringBuilder sb = new StringBuilder(); 318251875Speter sb.append("Expected "); 319251875Speter sb.append(expectedCount); 320251875Speter sb.append(" annotation "); 321251875Speter sb.append(expectedName); 322251875Speter sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 323251875Speter return sb.toString(); 324251875Speter } 325251875Speter 326251875Speter /** 327251875Speter * See if this template matches the given visibility. 328251875Speter * 329251875Speter * @param Whether or not the annotation is visible at runtime. 330251875Speter * @return Whether or not this template matches the visibility. 331251875Speter */ 332251875Speter public boolean matchVisibility(boolean visibility) { 333251875Speter return this.visibility == visibility; 334251875Speter } 335251875Speter 336251875Speter /** 337251875Speter * Attempty to match this template against an annotation. If 338251875Speter * it does match, then the match count for the template will 339251875Speter * be incremented. Otherwise, nothing will be done. 340251875Speter * 341251875Speter * @param anno The annotation to attempt to match. 342251875Speter */ 343251875Speter public void matchAnnotation(ConstantPool cpool, 344251875Speter Annotation anno) { 345251875Speter if (checkMatch(cpool, anno)) { 346251875Speter count++; 347251875Speter } 348251875Speter } 349251875Speter 350251875Speter /** 351251875Speter * Indicate whether an annotation matches this expected 352251875Speter * annotation. 353251875Speter * 354251875Speter * @param ConstantPool The constant pool to use. 355251875Speter * @param anno The annotation to check. 356251875Speter * @return Whether the annotation matches. 357251875Speter */ 358251875Speter protected boolean checkMatch(ConstantPool cpool, 359251875Speter Annotation anno) { 360251875Speter try { 361251875Speter return cpool.getUTF8Info(anno.type_index).value.equals("L" + expectedName + ";"); 362251875Speter } catch (InvalidIndex | UnexpectedEntry e) { 363251875Speter return false; 364251875Speter } 365251875Speter } 366251875Speter 367251875Speter /** 368251875Speter * After all matching, check to see if the expected number of 369251875Speter * matches equals the actual number. If not, then print a 370251875Speter * failure message and return {@code false}. 371251875Speter * 372251875Speter * @return Whether or not the expected number of matched 373251875Speter * equals the actual number. 374251875Speter */ 375251875Speter public boolean check() { 376251875Speter if (count != expectedCount) { 377251875Speter System.err.println(this + ", but saw " + count); 378251875Speter return false; 379251875Speter } else { 380251875Speter return true; 381251875Speter } 382251875Speter } 383251875Speter } 384251875Speter 385251875Speter /** 386251875Speter * An annotation found on a method. 387251875Speter */ 388251875Speter public static class ExpectedMethodAnnotation extends ExpectedAnnotation { 389251875Speter protected final String methodname; 390251875Speter 391251875Speter /** 392251875Speter * Create an {@code ExpectedMethodAnnotation} from its 393251875Speter * components. It is usually a better idea to use a {@code 394251875Speter * Builder} to do this. 395251875Speter * 396251875Speter * @param methodname The expected method name. 397251875Speter * @param expectedName The expected annotation name. 398251875Speter * @param visibility Whether this annotation should be runtime-visible. 399251875Speter * @param expectedCount The number of annotations that should be seen. 400251875Speter */ 401251875Speter public ExpectedMethodAnnotation(String methodname, 402251875Speter String expectedName, 403251875Speter boolean visibility, 404251875Speter int expectedCount) { 405251875Speter super(expectedName, visibility, expectedCount); 406251875Speter this.methodname = methodname; 407251875Speter } 408251875Speter 409251875Speter @Override 410251875Speter public String toString() { 411251875Speter final StringBuilder sb = new StringBuilder(); 412251875Speter sb.append("Expected "); 413251875Speter sb.append(expectedCount); 414251875Speter sb.append(" annotation "); 415251875Speter sb.append(expectedName); 416251875Speter sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 417251875Speter sb.append(" on method "); 418251875Speter sb.append(methodname); 419251875Speter return sb.toString(); 420251875Speter } 421251875Speter 422251875Speter /** 423251875Speter * See if this template applies to a method. 424251875Speter * 425251875Speter * @param methodname The method name to check. 426251875Speter * @return Whether or not this template should apply. 427251875Speter */ 428251875Speter public boolean matchMethodName(String methodname) { 429251875Speter return this.methodname.equals(methodname); 430251875Speter } 431251875Speter 432251875Speter } 433251875Speter 434251875Speter /** 435251875Speter * An annotation found on a method parameter. 436251875Speter */ 437251875Speter public static class ExpectedParameterAnnotation 438251875Speter extends ExpectedMethodAnnotation { 439251875Speter protected final int index; 440251875Speter 441251875Speter /** 442251875Speter * Create an {@code ExpectedParameterAnnotation} from its 443251875Speter * components. It is usually a better idea to use a {@code 444251875Speter * Builder} to do this. 445251875Speter * 446251875Speter * @param methodname The expected method name. 447251875Speter * @param index The parameter index. 448251875Speter * @param expectedName The expected annotation name. 449251875Speter * @param visibility Whether this annotation should be runtime-visible. 450251875Speter * @param expectedCount The number of annotations that should be seen. 451251875Speter */ 452251875Speter public ExpectedParameterAnnotation(String methodname, 453251875Speter int index, 454251875Speter String expectedName, 455251875Speter boolean visibility, 456251875Speter int expectedCount) { 457251875Speter super(methodname, expectedName, visibility, expectedCount); 458251875Speter this.index = index; 459251875Speter } 460251875Speter 461251875Speter @Override 462251875Speter public String toString() { 463251875Speter final StringBuilder sb = new StringBuilder(); 464251875Speter sb.append("Expected "); 465251875Speter sb.append(expectedCount); 466251875Speter sb.append(" annotation "); 467251875Speter sb.append(expectedName); 468251875Speter sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 469251875Speter sb.append(" on method "); 470251875Speter sb.append(methodname); 471251875Speter sb.append(" parameter "); 472251875Speter sb.append(index); 473251875Speter return sb.toString(); 474251875Speter } 475251875Speter 476251875Speter } 477251875Speter 478251875Speter /** 479251875Speter * An annotation found on a field. 480251875Speter */ 481251875Speter public static class ExpectedFieldAnnotation extends ExpectedAnnotation { 482251875Speter private final String fieldname; 483251875Speter 484251875Speter /** 485251875Speter * Create an {@code ExpectedFieldAnnotation} from its 486251875Speter * components. It is usually a better idea to use a {@code 487251875Speter * Builder} to do this. 488251875Speter * 489251875Speter * @param fieldname The expected field name. 490251875Speter * @param expectedName The expected annotation name. 491251875Speter * @param visibility Whether this annotation should be runtime-visible. 492251875Speter * @param expectedCount The number of annotations that should be seen. 493251875Speter */ 494251875Speter public ExpectedFieldAnnotation(String fieldname, 495251875Speter String expectedName, 496251875Speter boolean visibility, 497251875Speter int expectedCount) { 498251875Speter super(expectedName, visibility, expectedCount); 499251875Speter this.fieldname = fieldname; 500251875Speter } 501251875Speter 502251875Speter @Override 503251875Speter public String toString() { 504251875Speter final StringBuilder sb = new StringBuilder(); 505251875Speter sb.append("Expected ").append(expectedCount) 506251875Speter .append(" annotation ").append(expectedName) 507251875Speter .append(visibility ? ", runtime visibile " : ", runtime invisibile ") 508251875Speter .append(" on field ").append(fieldname); 509251875Speter return sb.toString(); 510251875Speter } 511251875Speter 512251875Speter /** 513251875Speter * See if this template applies to a field. 514251875Speter * 515251875Speter * @param fieldname The field name to check. 516251875Speter * @return Whether or not this template should apply. 517251875Speter */ 518251875Speter public boolean matchFieldName(String fieldname) { 519251875Speter return this.fieldname.equals(fieldname); 520251875Speter } 521251875Speter 522251875Speter } 523251875Speter 524251875Speter /** 525251875Speter * An expected type annotation. This is both a superclass for 526251875Speter * method and field type annotations, as well as a class for type 527251875Speter * annotations on a class. 528251875Speter */ 529251875Speter public static class ExpectedTypeAnnotation extends ExpectedAnnotation { 530251875Speter protected final TypeAnnotation.TargetType targetType; 531251875Speter protected final int bound_index; 532251875Speter protected final int parameter_index; 533251875Speter protected final int type_index; 534251875Speter protected final int exception_index; 535251875Speter protected final TypeAnnotation.Position.TypePathEntry[] typePath; 536251875Speter 537251875Speter /** 538251875Speter * Create an {@code ExpectedTypeAnnotation} from its 539251875Speter * components. It is usually a better idea to use a {@code 540251875Speter * Builder} to do this. 541251875Speter * 542251875Speter * @param expectedName The expected annotation name. 543251875Speter * @param visibility Whether this annotation should be runtime-visible. 544251875Speter * @param expectedCount The number of annotations that should 545251875Speter * be seen. If 0, this asserts that the 546251875Speter * described annotation is not present. 547251875Speter * @param targetType The expected target type. 548251875Speter * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 549251875Speter * @param parameter_index The expected parameter index, or 550251875Speter * {@code Integer.MIN_VALUE}. 551251875Speter * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 552251875Speter * @param exception_index The expected exception index, or 553251875Speter * {@code Integer.MIN_VALUE}. 554251875Speter * @param typePath The expected type path. 555266735Speter */ 556251875Speter public ExpectedTypeAnnotation(String expectedName, 557251875Speter boolean visibility, 558251875Speter int expectedCount, 559251875Speter TypeAnnotation.TargetType targetType, 560251875Speter int bound_index, 561251875Speter int parameter_index, 562251875Speter int type_index, 563251875Speter int exception_index, 564251875Speter TypeAnnotation.Position.TypePathEntry... typePath) { 565251875Speter super(expectedName, visibility, expectedCount); 566251875Speter this.targetType = targetType; 567251875Speter this.bound_index = bound_index; 568251875Speter this.parameter_index = parameter_index; 569251875Speter this.type_index = type_index; 570251875Speter this.exception_index = exception_index; 571251875Speter this.typePath = typePath; 572251875Speter } 573251875Speter 574251875Speter @Override 575251875Speter public String toString() { 576251875Speter final StringBuilder sb = new StringBuilder(); 577251875Speter sb.append("Expected "); 578251875Speter sb.append(expectedCount); 579251875Speter sb.append(" annotation "); 580251875Speter sb.append(expectedName); 581251875Speter sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 582251875Speter sb.append(targetType); 583251875Speter sb.append(", bound_index = "); 584251875Speter sb.append(bound_index); 585251875Speter sb.append(", parameter_index = "); 586251875Speter sb.append(parameter_index); 587251875Speter sb.append(", type_index = "); 588251875Speter sb.append(type_index); 589251875Speter sb.append(", exception_index = "); 590251875Speter sb.append(exception_index); 591251875Speter sb.append(", type_path = ["); 592251875Speter for(int i = 0; i < typePath.length; i++) { 593251875Speter if (i != 0) { 594251875Speter sb.append(", "); 595251875Speter } 596251875Speter sb.append(typePath[i]); 597251875Speter } 598251875Speter sb.append("]"); 599251875Speter return sb.toString(); 600251875Speter } 601251875Speter 602251875Speter @Override 603251875Speter public void matchAnnotation(ConstantPool cpool, 604251875Speter Annotation anno) {} 605251875Speter 606251875Speter public void matchAnnotation(TypeAnnotation anno) { 607251875Speter if (checkMatch(anno)) { 608251875Speter count++; 609251875Speter } 610251875Speter } 611251875Speter 612251875Speter public boolean checkMatch(TypeAnnotation anno) { 613251875Speter boolean matches = checkMatch(anno.constant_pool, anno.annotation); 614251875Speter 615251875Speter matches = matches && anno.position.type == targetType; 616251875Speter matches = matches && anno.position.bound_index == bound_index; 617251875Speter matches = matches && anno.position.parameter_index == parameter_index; 618251875Speter matches = matches && anno.position.type_index == type_index; 619251875Speter matches = matches && anno.position.exception_index == exception_index; 620251875Speter matches = matches && anno.position.location.size() == typePath.length; 621251875Speter 622251875Speter if (matches) { 623251875Speter int i = 0; 624251875Speter for(TypeAnnotation.Position.TypePathEntry entry : 625251875Speter anno.position.location) { 626251875Speter matches = matches && typePath[i++].equals(entry); 627251875Speter } 628251875Speter } 629251875Speter 630251875Speter return matches; 631251875Speter } 632251875Speter 633251875Speter /** 634251875Speter * A builder class for creating {@code 635251875Speter * ExpectedTypeAnnotation}s in a more convenient fashion. The 636251875Speter * constructor for {@code ExpectedTypeAnnotation} takes a 637251875Speter * large number of parameters (by necessity). This class 638251875Speter * allows users to construct a {@code ExpectedTypeAnnotation}s 639251875Speter * using only the ones they need. 640251875Speter */ 641251875Speter public static class Builder { 642251875Speter protected final String expectedName; 643251875Speter protected final boolean visibility; 644251875Speter protected final int expectedCount; 645251875Speter protected final TypeAnnotation.TargetType targetType; 646251875Speter protected int bound_index = Integer.MIN_VALUE; 647251875Speter protected int parameter_index = Integer.MIN_VALUE; 648251875Speter protected int type_index = Integer.MIN_VALUE; 649251875Speter protected int exception_index = Integer.MIN_VALUE; 650251875Speter protected TypeAnnotation.Position.TypePathEntry[] typePath = 651251875Speter new TypeAnnotation.Position.TypePathEntry[0]; 652251875Speter 653251875Speter /** 654251875Speter * Create a {@code Builder} from the mandatory parameters. 655251875Speter * 656251875Speter * @param expectedName The expected annotation name. 657251875Speter * @param targetType The expected target type. 658251875Speter * @param visibility Whether this annotation should be runtime-visible. 659251875Speter * @param expectedCount The number of annotations that should be seen. 660251875Speter */ 661251875Speter public Builder(String expectedName, 662251875Speter TypeAnnotation.TargetType targetType, 663251875Speter boolean visibility, 664251875Speter int expectedCount) { 665251875Speter this.expectedName = expectedName; 666251875Speter this.visibility = visibility; 667251875Speter this.expectedCount = expectedCount; 668251875Speter this.targetType = targetType; 669251875Speter } 670251875Speter 671251875Speter /** 672251875Speter * Create an {@code ExpectedTypeAnnotation} from all 673251875Speter * parameters that have been provided. The default values 674251875Speter * will be used for those that have not. 675251875Speter * 676251875Speter * @return The cretaed {@code ExpectedTypeAnnotation}. 677251875Speter */ 678251875Speter public ExpectedTypeAnnotation build() { 679251875Speter return new ExpectedTypeAnnotation(expectedName, visibility, 680251875Speter expectedCount, targetType, 681251875Speter bound_index, parameter_index, 682251875Speter type_index, exception_index, 683251875Speter typePath); 684251875Speter } 685251875Speter 686251875Speter /** 687251875Speter * Provide a bound index parameter. 688251875Speter * 689251875Speter * @param bound_index The bound_index value. 690251875Speter */ 691251875Speter public Builder setBoundIndex(int bound_index) { 692251875Speter this.bound_index = bound_index; 693251875Speter return this; 694251875Speter } 695251875Speter 696251875Speter /** 697251875Speter * Provide a parameter index parameter. 698251875Speter * 699251875Speter * @param bound_index The parameter_index value. 700251875Speter */ 701251875Speter public Builder setParameterIndex(int parameter_index) { 702251875Speter this.parameter_index = parameter_index; 703251875Speter return this; 704251875Speter } 705251875Speter 706251875Speter /** 707251875Speter * Provide a type index parameter. 708251875Speter * 709251875Speter * @param type_index The type_index value. 710251875Speter */ 711251875Speter public Builder setTypeIndex(int type_index) { 712251875Speter this.type_index = type_index; 713251875Speter return this; 714251875Speter } 715251875Speter 716251875Speter /** 717251875Speter * Provide an exception index parameter. 718251875Speter * 719251875Speter * @param exception_index The exception_index value. 720251875Speter */ 721251875Speter public Builder setExceptionIndex(int exception_index) { 722251875Speter this.exception_index = exception_index; 723251875Speter return this; 724251875Speter } 725251875Speter 726251875Speter /** 727251875Speter * Provide a type path parameter. 728251875Speter * 729251875Speter * @param typePath The type path value. 730251875Speter */ 731251875Speter public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) { 732251875Speter this.typePath = typePath; 733251875Speter return this; 734251875Speter } 735251875Speter } 736251875Speter } 737251875Speter 738251875Speter /** 739251875Speter * A type annotation found on a method. 740251875Speter */ 741251875Speter public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation { 742251875Speter private final String methodname; 743251875Speter 744251875Speter /** 745251875Speter * Create an {@code ExpectedMethodTypeAnnotation} from its 746251875Speter * components. It is usually a better idea to use a {@code 747251875Speter * Builder} to do this. 748251875Speter * 749251875Speter * @param methodname The expected method name. 750251875Speter * @param expectedName The expected annotation name. 751251875Speter * @param visibility Whether this annotation should be runtime-visible. 752251875Speter * @param expectedCount The number of annotations that should be seen. 753251875Speter * @param targetType The expected target type. 754251875Speter * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 755251875Speter * @param parameter_index The expected parameter index, or 756251875Speter * {@code Integer.MIN_VALUE}. 757251875Speter * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 758251875Speter * @param exception_index The expected exception index, or 759251875Speter * {@code Integer.MIN_VALUE}. 760251875Speter * @param typePath The expected type path. 761251875Speter */ 762251875Speter public ExpectedMethodTypeAnnotation(String methodname, 763251875Speter String expectedName, 764251875Speter boolean visibility, 765251875Speter int expectedCount, 766251875Speter TypeAnnotation.TargetType targetType, 767251875Speter int bound_index, 768251875Speter int parameter_index, 769251875Speter int type_index, 770251875Speter int exception_index, 771251875Speter TypeAnnotation.Position.TypePathEntry... typePath) { 772251875Speter super(expectedName, visibility, expectedCount, targetType, bound_index, 773251875Speter parameter_index, type_index, exception_index, typePath); 774251875Speter this.methodname = methodname; 775251875Speter } 776251875Speter 777251875Speter @Override 778251875Speter public String toString() { 779251875Speter final StringBuilder sb = new StringBuilder(); 780251875Speter sb.append("Expected "); 781251875Speter sb.append(expectedCount); 782251875Speter sb.append(" annotation "); 783251875Speter sb.append(expectedName); 784251875Speter sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); 785251875Speter sb.append(targetType); 786251875Speter sb.append(", bound_index = "); 787251875Speter sb.append(bound_index); 788251875Speter sb.append(", parameter_index = "); 789251875Speter sb.append(parameter_index); 790251875Speter sb.append(", type_index = "); 791251875Speter sb.append(type_index); 792251875Speter sb.append(", exception_index = "); 793251875Speter sb.append(exception_index); 794251875Speter sb.append(", type_path = ["); 795251875Speter for(int i = 0; i < typePath.length; i++) { 796251875Speter if (i != 0) { 797251875Speter sb.append(", "); 798251875Speter } 799251875Speter sb.append(typePath[i]); 800251875Speter } 801251875Speter sb.append("]"); 802251875Speter sb.append(" on method "); 803251875Speter sb.append(methodname); 804251875Speter return sb.toString(); 805251875Speter } 806251875Speter 807251875Speter /** 808251875Speter * See if this template applies to a method. 809251875Speter * 810251875Speter * @param methodname The method name to check. 811251875Speter * @return Whether or not this template should apply. 812251875Speter */ 813251875Speter public boolean matchMethodName(String methodname) { 814251875Speter return this.methodname.equals(methodname); 815251875Speter } 816251875Speter 817251875Speter /** 818251875Speter * A builder class for creating {@code 819251875Speter * ExpectedMethodTypeAnnotation}s in a more convenient fashion. The 820251875Speter * constructor for {@code ExpectedMethodTypeAnnotation} takes a 821251875Speter * large number of parameters (by necessity). This class 822251875Speter * allows users to construct a {@code ExpectedMethodTypeAnnotation}s 823251875Speter * using only the ones they need. 824251875Speter */ 825251875Speter public static class Builder extends ExpectedTypeAnnotation.Builder { 826251875Speter protected final String methodname; 827251875Speter 828251875Speter /** 829251875Speter * Create a {@code Builder} from the mandatory parameters. 830251875Speter * 831251875Speter * @param methodname The expected method name. 832251875Speter * @param expectedName The expected annotation name. 833251875Speter * @param targetType The expected target type. 834251875Speter * @param visibility Whether this annotation should be runtime-visible. 835251875Speter * @param expectedCount The number of annotations that should be seen. 836251875Speter */ 837251875Speter public Builder(String methodname, 838251875Speter String expectedName, 839251875Speter TypeAnnotation.TargetType targetType, 840251875Speter boolean visibility, 841251875Speter int expectedCount) { 842251875Speter super(expectedName, targetType, visibility, expectedCount); 843251875Speter this.methodname = methodname; 844251875Speter } 845251875Speter 846251875Speter /** 847251875Speter * Create an {@code ExpectedMethodTypeAnnotation} from all 848251875Speter * parameters that have been provided. The default values 849251875Speter * will be used for those that have not. 850251875Speter * 851251875Speter * @return The created {@code ExpectedMethodTypeAnnotation}. 852251875Speter */ 853251875Speter @Override 854251875Speter public ExpectedMethodTypeAnnotation build() { 855251875Speter return new ExpectedMethodTypeAnnotation(methodname, expectedName, 856251875Speter visibility, expectedCount, 857251875Speter targetType, bound_index, 858251875Speter parameter_index, type_index, 859251875Speter exception_index, typePath); 860251875Speter } 861251875Speter } 862251875Speter } 863251875Speter 864251875Speter /** 865251875Speter * A type annotation found on a field. 866251875Speter */ 867251875Speter public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation { 868251875Speter private final String fieldname; 869251875Speter 870251875Speter /** 871251875Speter * Create an {@code ExpectedFieldTypeAnnotation} from its 872251875Speter * components. It is usually a better idea to use a {@code 873251875Speter * Builder} to do this. 874251875Speter * 875251875Speter * @param fieldname The expected field name. 876251875Speter * @param expectedName The expected annotation name. 877251875Speter * @param visibility Whether this annotation should be runtime-visible. 878251875Speter * @param expectedCount The number of annotations that should be seen. 879251875Speter * @param targetType The expected target type. 880251875Speter * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. 881251875Speter * @param parameter_index The expected parameter index, or 882251875Speter * {@code Integer.MIN_VALUE}. 883251875Speter * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. 884251875Speter * @param exception_index The expected exception index, or 885251875Speter * {@code Integer.MIN_VALUE}. 886251875Speter * @param typePath The expected type path. 887251875Speter */ 888251875Speter public ExpectedFieldTypeAnnotation(String fieldname, 889251875Speter String expectedName, 890251875Speter boolean visibility, 891251875Speter int expectedCount, 892251875Speter TypeAnnotation.TargetType targetType, 893251875Speter int bound_index, 894251875Speter int parameter_index, 895251875Speter int type_index, 896251875Speter int exception_index, 897251875Speter TypeAnnotation.Position.TypePathEntry... typePath) { 898251875Speter super(expectedName, visibility, expectedCount, targetType, bound_index, 899251875Speter parameter_index, type_index, exception_index, typePath); 900251875Speter this.fieldname = fieldname; 901251875Speter } 902251875Speter 903251875Speter @Override 904251875Speter public String toString() { 905251875Speter final StringBuilder sb = new StringBuilder(); 906251875Speter sb.append("Expected ").append(expectedCount) 907251875Speter .append(" annotation ").append(expectedName) 908251875Speter .append(visibility ? ", runtime visibile " : ", runtime invisibile ") 909251875Speter .append(targetType) 910251875Speter .append(", bound_index = ").append(bound_index) 911251875Speter .append(", parameter_index = ").append(parameter_index) 912251875Speter .append(", type_index = ").append(type_index) 913251875Speter .append(", exception_index = ").append(exception_index) 914251875Speter .append(", type_path = ["); 915251875Speter 916251875Speter for(int i = 0; i < typePath.length; i++) { 917251875Speter if (i != 0) { 918251875Speter sb.append(", "); 919251875Speter } 920251875Speter sb.append(typePath[i]); 921251875Speter } 922251875Speter sb.append("]") 923251875Speter .append(" on field ").append(fieldname); 924251875Speter return sb.toString(); 925251875Speter } 926251875Speter 927251875Speter /** 928251875Speter * See if this template applies to a field. 929251875Speter * 930251875Speter * @param fieldname The field name to check. 931251875Speter * @return Whether or not this template should apply. 932251875Speter */ 933251875Speter public boolean matchFieldName(String fieldname) { 934251875Speter return this.fieldname.equals(fieldname); 935251875Speter } 936251875Speter 937251875Speter /** 938251875Speter * A builder class for creating {@code 939251875Speter * ExpectedFieldTypeAnnotation}s in a more convenient fashion. The 940251875Speter * constructor for {@code ExpectedFieldTypeAnnotation} takes a 941251875Speter * large number of parameters (by necessity). This class 942251875Speter * allows users to construct a {@code ExpectedFieldTypeAnnotation}s 943251875Speter * using only the ones they need. 944251875Speter */ 945251875Speter public static class Builder extends ExpectedTypeAnnotation.Builder { 946251875Speter protected final String fieldname; 947251875Speter 948251875Speter /** 949251875Speter * Create a {@code Builder} from the mandatory parameters. 950251875Speter * 951251875Speter * @param fieldname The expected field name. 952251875Speter * @param expectedName The expected annotation name. 953251875Speter * @param targetType The expected target type. 954251875Speter * @param visibility Whether this annotation should be runtime-visible. 955251875Speter * @param expectedCount The number of annotations that should be seen. 956251875Speter */ 957251875Speter public Builder(String fieldname, 958251875Speter String expectedName, 959251875Speter TypeAnnotation.TargetType targetType, 960251875Speter boolean visibility, 961251875Speter int expectedCount) { 962251875Speter super(expectedName, targetType, visibility, expectedCount); 963251875Speter this.fieldname = fieldname; 964251875Speter } 965251875Speter 966251875Speter /** 967251875Speter * Create an {@code ExpectedFieldTypeAnnotation} from all 968251875Speter * parameters that have been provided. The default values 969251875Speter * will be used for those that have not. 970251875Speter * 971251875Speter * @return The created {@code ExpectedFieldTypeAnnotation}. 972251875Speter */ 973251875Speter @Override 974251875Speter public ExpectedFieldTypeAnnotation build() { 975251875Speter return new ExpectedFieldTypeAnnotation(fieldname, expectedName, 976251875Speter visibility, expectedCount, 977251875Speter targetType, bound_index, 978251875Speter parameter_index, type_index, 979251875Speter exception_index, typePath); 980251875Speter } 981251875Speter } 982251875Speter } 983251875Speter 984251875Speter private void matchClassAnnotation(ClassFile classfile, 985251875Speter ExpectedAnnotation expected) 986251875Speter throws ConstantPoolException { 987251875Speter for(Attribute attr : classfile.attributes) { 988251875Speter attr.accept(annoMatcher(classfile.constant_pool), expected); 989251875Speter } 990251875Speter } 991251875Speter 992251875Speter private void matchMethodAnnotation(ClassFile classfile, 993251875Speter ExpectedMethodAnnotation expected) 994251875Speter throws ConstantPoolException { 995251875Speter for(Method meth : classfile.methods) { 996251875Speter if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { 997251875Speter for(Attribute attr : meth.attributes) { 998251875Speter attr.accept(annoMatcher(classfile.constant_pool), expected); 999251875Speter } 1000251875Speter } 1001251875Speter } 1002251875Speter } 1003251875Speter 1004251875Speter private void matchParameterAnnotation(ClassFile classfile, 1005251875Speter ExpectedParameterAnnotation expected) 1006251875Speter throws ConstantPoolException { 1007251875Speter for(Method meth : classfile.methods) { 1008251875Speter if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { 1009251875Speter for(Attribute attr : meth.attributes) { 1010251875Speter attr.accept(paramMatcher(classfile.constant_pool), expected); 1011251875Speter } 1012251875Speter } 1013251875Speter } 1014251875Speter } 1015251875Speter 1016251875Speter private void matchFieldAnnotation(ClassFile classfile, 1017251875Speter ExpectedFieldAnnotation expected) 1018251875Speter throws ConstantPoolException { 1019251875Speter for(Field field : classfile.fields) { 1020251875Speter if (expected.matchFieldName(field.getName(classfile.constant_pool))) { 1021251875Speter for(Attribute attr : field.attributes) { 1022251875Speter attr.accept(annoMatcher(classfile.constant_pool), expected); 1023251875Speter } 1024251875Speter } 1025251875Speter } 1026251875Speter } 1027251875Speter 1028251875Speter private void matchClassTypeAnnotation(ClassFile classfile, 1029251875Speter ExpectedTypeAnnotation expected) 1030251875Speter throws ConstantPoolException { 1031251875Speter for(Attribute attr : classfile.attributes) { 1032251875Speter attr.accept(typeAnnoMatcher, expected); 1033251875Speter } 1034251875Speter } 1035251875Speter 1036251875Speter private void matchMethodTypeAnnotation(ClassFile classfile, 1037251875Speter ExpectedMethodTypeAnnotation expected) 1038251875Speter throws ConstantPoolException { 1039251875Speter for(Method meth : classfile.methods) { 1040251875Speter if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { 1041251875Speter for(Attribute attr : meth.attributes) { 1042251875Speter attr.accept(typeAnnoMatcher, expected); 1043251875Speter } 1044251875Speter } 1045251875Speter } 1046251875Speter } 1047251875Speter 1048251875Speter private void matchFieldTypeAnnotation(ClassFile classfile, 1049251875Speter ExpectedFieldTypeAnnotation expected) 1050251875Speter throws ConstantPoolException { 1051251875Speter for(Field field : classfile.fields) { 1052251875Speter if (expected.matchFieldName(field.getName(classfile.constant_pool))) { 1053251875Speter for(Attribute attr : field.attributes) { 1054251875Speter attr.accept(typeAnnoMatcher, expected); 1055251875Speter } 1056251875Speter } 1057251875Speter } 1058251875Speter } 1059251875Speter 1060251875Speter private void matchClassAnnotations(ClassFile classfile, 1061251875Speter ExpectedAnnotation[] expected) 1062251875Speter throws ConstantPoolException { 1063251875Speter for(ExpectedAnnotation one : expected) { 1064251875Speter matchClassAnnotation(classfile, one); 1065251875Speter } 1066251875Speter } 1067251875Speter 1068251875Speter private void matchMethodAnnotations(ClassFile classfile, 1069251875Speter ExpectedMethodAnnotation[] expected) 1070251875Speter throws ConstantPoolException { 1071251875Speter for(ExpectedMethodAnnotation one : expected) { 1072251875Speter matchMethodAnnotation(classfile, one); 1073251875Speter } 1074251875Speter } 1075251875Speter 1076251875Speter private void matchParameterAnnotations(ClassFile classfile, 1077251875Speter ExpectedParameterAnnotation[] expected) 1078251875Speter throws ConstantPoolException { 1079251875Speter for(ExpectedParameterAnnotation one : expected) { 1080251875Speter matchParameterAnnotation(classfile, one); 1081251875Speter } 1082251875Speter } 1083251875Speter 1084251875Speter private void matchFieldAnnotations(ClassFile classfile, 1085251875Speter ExpectedFieldAnnotation[] expected) 1086251875Speter throws ConstantPoolException { 1087251875Speter for(ExpectedFieldAnnotation one : expected) { 1088251875Speter matchFieldAnnotation(classfile, one); 1089251875Speter } 1090251875Speter } 1091251875Speter 1092251875Speter private void matchClassTypeAnnotations(ClassFile classfile, 1093251875Speter ExpectedTypeAnnotation[] expected) 1094251875Speter throws ConstantPoolException { 1095251875Speter for(ExpectedTypeAnnotation one : expected) { 1096251875Speter matchClassTypeAnnotation(classfile, one); 1097251875Speter } 1098251875Speter } 1099251875Speter 1100251875Speter private void matchMethodTypeAnnotations(ClassFile classfile, 1101251875Speter ExpectedMethodTypeAnnotation[] expected) 1102251875Speter throws ConstantPoolException { 1103251875Speter for(ExpectedMethodTypeAnnotation one : expected) { 1104251875Speter matchMethodTypeAnnotation(classfile, one); 1105251875Speter } 1106251875Speter } 1107251875Speter 1108251875Speter private void matchFieldTypeAnnotations(ClassFile classfile, 1109251875Speter ExpectedFieldTypeAnnotation[] expected) 1110251875Speter throws ConstantPoolException { 1111 for(ExpectedFieldTypeAnnotation one : expected) { 1112 matchFieldTypeAnnotation(classfile, one); 1113 } 1114 } 1115 1116 /** 1117 * Run a template on a single {@code ClassFile}. 1118 * 1119 * @param classfile The {@code ClassFile} on which to run tests. 1120 * @param expected The expected annotation template. 1121 */ 1122 public void run(ClassFile classfile, 1123 Expected... expected) 1124 throws ConstantPoolException { 1125 run(new ClassFile[] { classfile }, expected); 1126 } 1127 1128 /** 1129 * Run a template on multiple {@code ClassFile}s. 1130 * 1131 * @param classfile The {@code ClassFile}s on which to run tests. 1132 * @param expected The expected annotation template. 1133 */ 1134 public void run(ClassFile[] classfiles, 1135 Expected... expected) 1136 throws ConstantPoolException { 1137 for(ClassFile classfile : classfiles) { 1138 for(Expected one : expected) { 1139 if (one.matchClassName(classfile.getName())) { 1140 if (one.classAnnos != null) 1141 matchClassAnnotations(classfile, one.classAnnos); 1142 if (one.methodAnnos != null) 1143 matchMethodAnnotations(classfile, one.methodAnnos); 1144 if (one.methodParamAnnos != null) 1145 matchParameterAnnotations(classfile, one.methodParamAnnos); 1146 if (one.fieldAnnos != null) 1147 matchFieldAnnotations(classfile, one.fieldAnnos); 1148 if (one.classTypeAnnos != null) 1149 matchClassTypeAnnotations(classfile, one.classTypeAnnos); 1150 if (one.methodTypeAnnos != null) 1151 matchMethodTypeAnnotations(classfile, one.methodTypeAnnos); 1152 if (one.fieldTypeAnnos != null) 1153 matchFieldTypeAnnotations(classfile, one.fieldTypeAnnos); 1154 } 1155 } 1156 } 1157 int count = 0; 1158 for (Expected one : expected) { 1159 count += one.check(); 1160 } 1161 1162 if (count != 0) { 1163 throw new RuntimeException(count + " errors occurred in test"); 1164 } 1165 } 1166 1167 /** 1168 * Get a {@code ClassFile} from its file name. 1169 * 1170 * @param name The class' file name. 1171 * @param host A class in the same package. 1172 * @return The {@code ClassFile} 1173 */ 1174 public static ClassFile getClassFile(String name, 1175 Class<?> host) 1176 throws IOException, ConstantPoolException { 1177 final URL url = host.getResource(name); 1178 try (InputStream in = url.openStream()) { 1179 return ClassFile.read(in); 1180 } 1181 } 1182 1183 private static class AbstractAttributeVisitor<T> implements Attribute.Visitor<Void, T> { 1184 1185 @Override 1186 public Void visitBootstrapMethods(BootstrapMethods_attribute attr, T p) { 1187 return null; 1188 } 1189 1190 @Override 1191 public Void visitModulePackages(ModulePackages_attribute attr, T p) { 1192 return null; 1193 } 1194 1195 @Override 1196 public Void visitDefault(DefaultAttribute attr, T p) { 1197 return null; 1198 } 1199 1200 @Override 1201 public Void visitAnnotationDefault(AnnotationDefault_attribute attr, T p) { 1202 return null; 1203 } 1204 1205 @Override 1206 public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, T p) { 1207 return null; 1208 } 1209 1210 @Override 1211 public Void visitCode(Code_attribute attr, T p) { 1212 return null; 1213 } 1214 1215 @Override 1216 public Void visitCompilationID(CompilationID_attribute attr, T p) { 1217 return null; 1218 } 1219 1220 @Override 1221 public Void visitConstantValue(ConstantValue_attribute attr, T p) { 1222 return null; 1223 } 1224 1225 @Override 1226 public Void visitDeprecated(Deprecated_attribute attr, T p) { 1227 return null; 1228 } 1229 1230 @Override 1231 public Void visitEnclosingMethod(EnclosingMethod_attribute attr, T p) { 1232 return null; 1233 } 1234 1235 @Override 1236 public Void visitExceptions(Exceptions_attribute attr, T p) { 1237 return null; 1238 } 1239 1240 @Override 1241 public Void visitModuleHashes(ModuleHashes_attribute attr, T p) { 1242 return null; 1243 } 1244 1245 @Override 1246 public Void visitInnerClasses(InnerClasses_attribute attr, T p) { 1247 return null; 1248 } 1249 1250 @Override 1251 public Void visitLineNumberTable(LineNumberTable_attribute attr, T p) { 1252 return null; 1253 } 1254 1255 @Override 1256 public Void visitLocalVariableTable(LocalVariableTable_attribute attr, T p) { 1257 return null; 1258 } 1259 1260 @Override 1261 public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, T p) { 1262 return null; 1263 } 1264 1265 @Override 1266 public Void visitModuleMainClass(ModuleMainClass_attribute attr, T p) { 1267 return null; 1268 } 1269 1270 @Override 1271 public Void visitMethodParameters(MethodParameters_attribute attr, T p) { 1272 return null; 1273 } 1274 1275 @Override 1276 public Void visitModule(Module_attribute attr, T p) { 1277 return null; 1278 } 1279 1280 @Override 1281 public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, T p) { 1282 return null; 1283 } 1284 1285 @Override 1286 public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, T p) { 1287 return null; 1288 } 1289 1290 @Override 1291 public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, T p) { 1292 return null; 1293 } 1294 1295 @Override 1296 public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, T p) { 1297 return null; 1298 } 1299 1300 @Override 1301 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, T p) { 1302 return null; 1303 } 1304 1305 @Override 1306 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, T p) { 1307 return null; 1308 } 1309 1310 @Override 1311 public Void visitSignature(Signature_attribute attr, T p) { 1312 return null; 1313 } 1314 1315 @Override 1316 public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, T p) { 1317 return null; 1318 } 1319 1320 @Override 1321 public Void visitSourceFile(SourceFile_attribute attr, T p) { 1322 return null; 1323 } 1324 1325 @Override 1326 public Void visitSourceID(SourceID_attribute attr, T p) { 1327 return null; 1328 } 1329 1330 @Override 1331 public Void visitStackMap(StackMap_attribute attr, T p) { 1332 return null; 1333 } 1334 1335 @Override 1336 public Void visitStackMapTable(StackMapTable_attribute attr, T p) { 1337 return null; 1338 } 1339 1340 @Override 1341 public Void visitSynthetic(Synthetic_attribute attr, T p) { 1342 return null; 1343 } 1344 1345 @Override 1346 public Void visitModuleTarget(ModuleTarget_attribute attr, T p) { 1347 return null; 1348 } 1349 1350 @Override 1351 public Void visitModuleVersion(ModuleVersion_attribute attr, T p) { 1352 return null; 1353 } 1354 1355 } 1356 1357 private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher 1358 = new AbstractAttributeVisitor<ExpectedTypeAnnotation>() { 1359 1360 @Override 1361 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, 1362 ExpectedTypeAnnotation expected) { 1363 if (expected.matchVisibility(true)) { 1364 for (TypeAnnotation anno : attr.annotations) { 1365 expected.matchAnnotation(anno); 1366 } 1367 } 1368 1369 return null; 1370 } 1371 1372 @Override 1373 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, 1374 ExpectedTypeAnnotation expected) { 1375 if (expected.matchVisibility(false)) { 1376 for (TypeAnnotation anno : attr.annotations) { 1377 expected.matchAnnotation(anno); 1378 } 1379 } 1380 1381 return null; 1382 } 1383 }; 1384 1385 private static Attribute.Visitor<Void, ExpectedAnnotation> annoMatcher(ConstantPool cpool) { 1386 return new AbstractAttributeVisitor<ExpectedAnnotation>() { 1387 1388 @Override 1389 public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, 1390 ExpectedAnnotation expected) { 1391 if (expected.matchVisibility(true)) { 1392 for(Annotation anno : attr.annotations) { 1393 expected.matchAnnotation(cpool, anno); 1394 } 1395 } 1396 1397 return null; 1398 } 1399 1400 @Override 1401 public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, 1402 ExpectedAnnotation expected) { 1403 if (expected.matchVisibility(false)) { 1404 for(Annotation anno : attr.annotations) { 1405 expected.matchAnnotation(cpool, anno); 1406 } 1407 } 1408 1409 return null; 1410 } 1411 }; 1412 } 1413 1414 private static Attribute.Visitor<Void, ExpectedParameterAnnotation> paramMatcher(ConstantPool cpool) { 1415 return new AbstractAttributeVisitor<ExpectedParameterAnnotation>() { 1416 1417 @Override 1418 public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, 1419 ExpectedParameterAnnotation expected) { 1420 if (expected.matchVisibility(true)) { 1421 if (expected.index < attr.parameter_annotations.length) { 1422 for(Annotation anno : 1423 attr.parameter_annotations[expected.index]) { 1424 expected.matchAnnotation(cpool, anno); 1425 } 1426 } 1427 } 1428 1429 return null; 1430 } 1431 1432 @Override 1433 public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, 1434 ExpectedParameterAnnotation expected) { 1435 if (expected.matchVisibility(false)) { 1436 if (expected.index < attr.parameter_annotations.length) { 1437 for(Annotation anno : 1438 attr.parameter_annotations[expected.index]) { 1439 expected.matchAnnotation(cpool, anno); 1440 } 1441 } 1442 } 1443 1444 return null; 1445 } 1446 }; 1447 } 1448} 1449