001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028package io.ebean.enhance.asm; 029 030/** 031 * A visitor to visit a Java method. The methods of this class must be called in the following 032 * order: ( {@code visitParameter} )* [ {@code visitAnnotationDefault} ] ( {@code visitAnnotation} | 033 * {@code visitAnnotableParameterCount} | {@code visitParameterAnnotation} | {@code 034 * visitTypeAnnotation} | {@code visitAttribute} )* [ {@code visitCode} ( {@code visitFrame} | 035 * {@code visit<i>X</i>Insn} | {@code visitLabel} | {@code visitInsnAnnotation} | {@code 036 * visitTryCatchBlock} | {@code visitTryCatchAnnotation} | {@code visitLocalVariable} | {@code 037 * visitLocalVariableAnnotation} | {@code visitLineNumber} )* {@code visitMaxs} ] {@code visitEnd}. 038 * In addition, the {@code visit<i>X</i>Insn} and {@code visitLabel} methods must be called in the 039 * sequential order of the bytecode instructions of the visited code, {@code visitInsnAnnotation} 040 * must be called <i>after</i> the annotated instruction, {@code visitTryCatchBlock} must be called 041 * <i>before</i> the labels passed as arguments have been visited, {@code 042 * visitTryCatchBlockAnnotation} must be called <i>after</i> the corresponding try catch block has 043 * been visited, and the {@code visitLocalVariable}, {@code visitLocalVariableAnnotation} and {@code 044 * visitLineNumber} methods must be called <i>after</i> the labels passed as arguments have been 045 * visited. 046 * 047 * @author Eric Bruneton 048 */ 049public abstract class MethodVisitor { 050 051 private static final String REQUIRES_ASM5 = "This feature requires ASM5"; 052 053 /** 054 * The ASM API version implemented by this visitor. The value of this field must be one of the 055 * {@code ASM}<i>x</i> values in {@link Opcodes}. 056 */ 057 protected final int api; 058 059 /** 060 * The method visitor to which this visitor must delegate method calls. May be {@literal null}. 061 */ 062 protected MethodVisitor mv; 063 064 /** 065 * Constructs a new {@link MethodVisitor}. 066 * 067 * @param api the ASM API version implemented by this visitor. Must be one of the {@code 068 * ASM}<i>x</i> values in {@link Opcodes}. 069 */ 070 protected MethodVisitor(final int api) { 071 this(api, null); 072 } 073 074 /** 075 * Constructs a new {@link MethodVisitor}. 076 * 077 * @param api the ASM API version implemented by this visitor. Must be one of the {@code 078 * ASM}<i>x</i> values in {@link Opcodes}. 079 * @param methodVisitor the method visitor to which this visitor must delegate method calls. May 080 * be null. 081 */ 082 protected MethodVisitor(final int api, final MethodVisitor methodVisitor) { 083 if (api != Opcodes.ASM9 084 && api != Opcodes.ASM8 085 && api != Opcodes.ASM7 086 && api != Opcodes.ASM6 087 && api != Opcodes.ASM5 088 && api != Opcodes.ASM4 089 && api != Opcodes.ASM10_EXPERIMENTAL) { 090 throw new IllegalArgumentException("Unsupported api " + api); 091 } 092 if (api == Opcodes.ASM10_EXPERIMENTAL) { 093 Constants.checkAsmExperimental(this); 094 } 095 this.api = api; 096 this.mv = methodVisitor; 097 } 098 099 /** 100 * The method visitor to which this visitor must delegate method calls. May be {@literal null}. 101 * 102 * @return the method visitor to which this visitor must delegate method calls, or {@literal 103 * null}. 104 */ 105 public MethodVisitor getDelegate() { 106 return mv; 107 } 108 109 // ----------------------------------------------------------------------------------------------- 110 // Parameters, annotations and non standard attributes 111 // ----------------------------------------------------------------------------------------------- 112 113 /** 114 * Visits a parameter of this method. 115 * 116 * @param name parameter name or {@literal null} if none is provided. 117 * @param access the parameter's access flags, only {@code ACC_FINAL}, {@code ACC_SYNTHETIC} 118 * or/and {@code ACC_MANDATED} are allowed (see {@link Opcodes}). 119 */ 120 public void visitParameter(final String name, final int access) { 121 if (api < Opcodes.ASM5) { 122 throw new UnsupportedOperationException(REQUIRES_ASM5); 123 } 124 if (mv != null) { 125 mv.visitParameter(name, access); 126 } 127 } 128 129 /** 130 * Visits the default value of this annotation interface method. 131 * 132 * @return a visitor to the visit the actual default value of this annotation interface method, or 133 * {@literal null} if this visitor is not interested in visiting this default value. The 134 * 'name' parameters passed to the methods of this annotation visitor are ignored. Moreover, 135 * exactly one visit method must be called on this annotation visitor, followed by visitEnd. 136 */ 137 public AnnotationVisitor visitAnnotationDefault() { 138 if (mv != null) { 139 return mv.visitAnnotationDefault(); 140 } 141 return null; 142 } 143 144 /** 145 * Visits an annotation of this method. 146 * 147 * @param descriptor the class descriptor of the annotation class. 148 * @param visible {@literal true} if the annotation is visible at runtime. 149 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 150 * interested in visiting this annotation. 151 */ 152 public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 153 if (mv != null) { 154 return mv.visitAnnotation(descriptor, visible); 155 } 156 return null; 157 } 158 159 /** 160 * Visits an annotation on a type in the method signature. 161 * 162 * @param typeRef a reference to the annotated type. The sort of this type reference must be 163 * {@link TypeReference#METHOD_TYPE_PARAMETER}, {@link 164 * TypeReference#METHOD_TYPE_PARAMETER_BOUND}, {@link TypeReference#METHOD_RETURN}, {@link 165 * TypeReference#METHOD_RECEIVER}, {@link TypeReference#METHOD_FORMAL_PARAMETER} or {@link 166 * TypeReference#THROWS}. See {@link TypeReference}. 167 * @param typePath the path to the annotated type argument, wildcard bound, array element type, or 168 * static inner type within 'typeRef'. May be {@literal null} if the annotation targets 169 * 'typeRef' as a whole. 170 * @param descriptor the class descriptor of the annotation class. 171 * @param visible {@literal true} if the annotation is visible at runtime. 172 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 173 * interested in visiting this annotation. 174 */ 175 public AnnotationVisitor visitTypeAnnotation( 176 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 177 if (api < Opcodes.ASM5) { 178 throw new UnsupportedOperationException(REQUIRES_ASM5); 179 } 180 if (mv != null) { 181 return mv.visitTypeAnnotation(typeRef, typePath, descriptor, visible); 182 } 183 return null; 184 } 185 186 /** 187 * Visits the number of method parameters that can have annotations. By default (i.e. when this 188 * method is not called), all the method parameters defined by the method descriptor can have 189 * annotations. 190 * 191 * @param parameterCount the number of method parameters than can have annotations. This number 192 * must be less or equal than the number of parameter types in the method descriptor. It can 193 * be strictly less when a method has synthetic parameters and when these parameters are 194 * ignored when computing parameter indices for the purpose of parameter annotations (see 195 * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18). 196 * @param visible {@literal true} to define the number of method parameters that can have 197 * annotations visible at runtime, {@literal false} to define the number of method parameters 198 * that can have annotations invisible at runtime. 199 */ 200 public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) { 201 if (mv != null) { 202 mv.visitAnnotableParameterCount(parameterCount, visible); 203 } 204 } 205 206 /** 207 * Visits an annotation of a parameter this method. 208 * 209 * @param parameter the parameter index. This index must be strictly smaller than the number of 210 * parameters in the method descriptor, and strictly smaller than the parameter count 211 * specified in {@link #visitAnnotableParameterCount}. Important note: <i>a parameter index i 212 * is not required to correspond to the i'th parameter descriptor in the method 213 * descriptor</i>, in particular in case of synthetic parameters (see 214 * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18). 215 * @param descriptor the class descriptor of the annotation class. 216 * @param visible {@literal true} if the annotation is visible at runtime. 217 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 218 * interested in visiting this annotation. 219 */ 220 public AnnotationVisitor visitParameterAnnotation( 221 final int parameter, final String descriptor, final boolean visible) { 222 if (mv != null) { 223 return mv.visitParameterAnnotation(parameter, descriptor, visible); 224 } 225 return null; 226 } 227 228 /** 229 * Visits a non standard attribute of this method. 230 * 231 * @param attribute an attribute. 232 */ 233 public void visitAttribute(final Attribute attribute) { 234 if (mv != null) { 235 mv.visitAttribute(attribute); 236 } 237 } 238 239 /** Starts the visit of the method's code, if any (i.e. non abstract method). */ 240 public void visitCode() { 241 if (mv != null) { 242 mv.visitCode(); 243 } 244 } 245 246 /** 247 * Visits the current state of the local variables and operand stack elements. This method must(*) 248 * be called <i>just before</i> any instruction <b>i</b> that follows an unconditional branch 249 * instruction such as GOTO or THROW, that is the target of a jump instruction, or that starts an 250 * exception handler block. The visited types must describe the values of the local variables and 251 * of the operand stack elements <i>just before</i> <b>i</b> is executed.<br> 252 * <br> 253 * (*) this is mandatory only for classes whose version is greater than or equal to {@link 254 * Opcodes#V1_6}. <br> 255 * <br> 256 * The frames of a method must be given either in expanded form, or in compressed form (all frames 257 * must use the same format, i.e. you must not mix expanded and compressed frames within a single 258 * method): 259 * 260 * <ul> 261 * <li>In expanded form, all frames must have the F_NEW type. 262 * <li>In compressed form, frames are basically "deltas" from the state of the previous frame: 263 * <ul> 264 * <li>{@link Opcodes#F_SAME} representing frame with exactly the same locals as the 265 * previous frame and with the empty stack. 266 * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same locals as the 267 * previous frame and with single value on the stack ( <code>numStack</code> is 1 and 268 * <code>stack[0]</code> contains value for the type of the stack item). 269 * <li>{@link Opcodes#F_APPEND} representing frame with current locals are the same as the 270 * locals in the previous frame, except that additional locals are defined (<code> 271 * numLocal</code> is 1, 2 or 3 and <code>local</code> elements contains values 272 * representing added types). 273 * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the same as the 274 * locals in the previous frame, except that the last 1-3 locals are absent and with 275 * the empty stack (<code>numLocal</code> is 1, 2 or 3). 276 * <li>{@link Opcodes#F_FULL} representing complete frame data. 277 * </ul> 278 * </ul> 279 * 280 * <br> 281 * In both cases the first frame, corresponding to the method's parameters and access flags, is 282 * implicit and must not be visited. Also, it is illegal to visit two or more frames for the same 283 * code location (i.e., at least one instruction must be visited between two calls to visitFrame). 284 * 285 * @param type the type of this stack map frame. Must be {@link Opcodes#F_NEW} for expanded 286 * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link 287 * Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames. 288 * @param numLocal the number of local variables in the visited frame. Long and double values 289 * count for one variable. 290 * @param local the local variable types in this frame. This array must not be modified. Primitive 291 * types are represented by {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link 292 * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL} or 293 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a single element). 294 * Reference types are represented by String objects (representing internal names, see {@link 295 * Type#getInternalName()}), and uninitialized types by Label objects (this label designates 296 * the NEW instruction that created this uninitialized value). 297 * @param numStack the number of operand stack elements in the visited frame. Long and double 298 * values count for one stack element. 299 * @param stack the operand stack types in this frame. This array must not be modified. Its 300 * content has the same format as the "local" array. 301 * @throws IllegalStateException if a frame is visited just after another one, without any 302 * instruction between the two (unless this frame is a Opcodes#F_SAME frame, in which case it 303 * is silently ignored). 304 */ 305 public void visitFrame( 306 final int type, 307 final int numLocal, 308 final Object[] local, 309 final int numStack, 310 final Object[] stack) { 311 if (mv != null) { 312 mv.visitFrame(type, numLocal, local, numStack, stack); 313 } 314 } 315 316 // ----------------------------------------------------------------------------------------------- 317 // Normal instructions 318 // ----------------------------------------------------------------------------------------------- 319 320 /** 321 * Visits a zero operand instruction. 322 * 323 * @param opcode the opcode of the instruction to be visited. This opcode is either NOP, 324 * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, 325 * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, 326 * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, DASTORE, 327 * AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, 328 * SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, 329 * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, 330 * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, 331 * D2L, D2F, I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, 332 * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or MONITOREXIT. 333 */ 334 public void visitInsn(final int opcode) { 335 if (mv != null) { 336 mv.visitInsn(opcode); 337 } 338 } 339 340 /** 341 * Visits an instruction with a single int operand. 342 * 343 * @param opcode the opcode of the instruction to be visited. This opcode is either BIPUSH, SIPUSH 344 * or NEWARRAY. 345 * @param operand the operand of the instruction to be visited.<br> 346 * When opcode is BIPUSH, operand value should be between Byte.MIN_VALUE and Byte.MAX_VALUE. 347 * <br> 348 * When opcode is SIPUSH, operand value should be between Short.MIN_VALUE and Short.MAX_VALUE. 349 * <br> 350 * When opcode is NEWARRAY, operand value should be one of {@link Opcodes#T_BOOLEAN}, {@link 351 * Opcodes#T_CHAR}, {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, {@link Opcodes#T_BYTE}, 352 * {@link Opcodes#T_SHORT}, {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. 353 */ 354 public void visitIntInsn(final int opcode, final int operand) { 355 if (mv != null) { 356 mv.visitIntInsn(opcode, operand); 357 } 358 } 359 360 /** 361 * Visits a local variable instruction. A local variable instruction is an instruction that loads 362 * or stores the value of a local variable. 363 * 364 * @param opcode the opcode of the local variable instruction to be visited. This opcode is either 365 * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. 366 * @param varIndex the operand of the instruction to be visited. This operand is the index of a 367 * local variable. 368 */ 369 public void visitVarInsn(final int opcode, final int varIndex) { 370 if (mv != null) { 371 mv.visitVarInsn(opcode, varIndex); 372 } 373 } 374 375 /** 376 * Visits a type instruction. A type instruction is an instruction that takes the internal name of 377 * a class as parameter (see {@link Type#getInternalName()}). 378 * 379 * @param opcode the opcode of the type instruction to be visited. This opcode is either NEW, 380 * ANEWARRAY, CHECKCAST or INSTANCEOF. 381 * @param type the operand of the instruction to be visited. This operand must be the internal 382 * name of an object or array class (see {@link Type#getInternalName()}). 383 */ 384 public void visitTypeInsn(final int opcode, final String type) { 385 if (mv != null) { 386 mv.visitTypeInsn(opcode, type); 387 } 388 } 389 390 /** 391 * Visits a field instruction. A field instruction is an instruction that loads or stores the 392 * value of a field of an object. 393 * 394 * @param opcode the opcode of the type instruction to be visited. This opcode is either 395 * GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. 396 * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}). 397 * @param name the field's name. 398 * @param descriptor the field's descriptor (see {@link Type}). 399 */ 400 public void visitFieldInsn( 401 final int opcode, final String owner, final String name, final String descriptor) { 402 if (mv != null) { 403 mv.visitFieldInsn(opcode, owner, name, descriptor); 404 } 405 } 406 407 /** 408 * Visits a method instruction. A method instruction is an instruction that invokes a method. 409 * 410 * @param opcode the opcode of the type instruction to be visited. This opcode is either 411 * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. 412 * @param owner the internal name of the method's owner class (see {@link 413 * Type#getInternalName()}). 414 * @param name the method's name. 415 * @param descriptor the method's descriptor (see {@link Type}). 416 * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead. 417 */ 418 @Deprecated 419 public void visitMethodInsn( 420 final int opcode, final String owner, final String name, final String descriptor) { 421 int opcodeAndSource = opcode | (api < Opcodes.ASM5 ? Opcodes.SOURCE_DEPRECATED : 0); 422 visitMethodInsn(opcodeAndSource, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE); 423 } 424 425 /** 426 * Visits a method instruction. A method instruction is an instruction that invokes a method. 427 * 428 * @param opcode the opcode of the type instruction to be visited. This opcode is either 429 * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. 430 * @param owner the internal name of the method's owner class (see {@link 431 * Type#getInternalName()}). 432 * @param name the method's name. 433 * @param descriptor the method's descriptor (see {@link Type}). 434 * @param isInterface if the method's owner class is an interface. 435 */ 436 public void visitMethodInsn( 437 final int opcode, 438 final String owner, 439 final String name, 440 final String descriptor, 441 final boolean isInterface) { 442 if (api < Opcodes.ASM5 && (opcode & Opcodes.SOURCE_DEPRECATED) == 0) { 443 if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) { 444 throw new UnsupportedOperationException("INVOKESPECIAL/STATIC on interfaces requires ASM5"); 445 } 446 visitMethodInsn(opcode, owner, name, descriptor); 447 return; 448 } 449 if (mv != null) { 450 mv.visitMethodInsn(opcode & ~Opcodes.SOURCE_MASK, owner, name, descriptor, isInterface); 451 } 452 } 453 454 /** 455 * Visits an invokedynamic instruction. 456 * 457 * @param name the method's name. 458 * @param descriptor the method's descriptor (see {@link Type}). 459 * @param bootstrapMethodHandle the bootstrap method. 460 * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be 461 * an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link 462 * Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify 463 * the content of the array so a caller should expect that this array may change. 464 */ 465 public void visitInvokeDynamicInsn( 466 final String name, 467 final String descriptor, 468 final Handle bootstrapMethodHandle, 469 final Object... bootstrapMethodArguments) { 470 if (api < Opcodes.ASM5) { 471 throw new UnsupportedOperationException(REQUIRES_ASM5); 472 } 473 if (mv != null) { 474 mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); 475 } 476 } 477 478 /** 479 * Visits a jump instruction. A jump instruction is an instruction that may jump to another 480 * instruction. 481 * 482 * @param opcode the opcode of the type instruction to be visited. This opcode is either IFEQ, 483 * IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, 484 * IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. 485 * @param label the operand of the instruction to be visited. This operand is a label that 486 * designates the instruction to which the jump instruction may jump. 487 */ 488 public void visitJumpInsn(final int opcode, final Label label) { 489 if (mv != null) { 490 mv.visitJumpInsn(opcode, label); 491 } 492 } 493 494 /** 495 * Visits a label. A label designates the instruction that will be visited just after it. 496 * 497 * @param label a {@link Label} object. 498 */ 499 public void visitLabel(final Label label) { 500 if (mv != null) { 501 mv.visitLabel(label); 502 } 503 } 504 505 // ----------------------------------------------------------------------------------------------- 506 // Special instructions 507 // ----------------------------------------------------------------------------------------------- 508 509 /** 510 * Visits a LDC instruction. Note that new constant types may be added in future versions of the 511 * Java Virtual Machine. To easily detect new constant types, implementations of this method 512 * should check for unexpected constant types, like this: 513 * 514 * <pre> 515 * if (cst instanceof Integer) { 516 * // ... 517 * } else if (cst instanceof Float) { 518 * // ... 519 * } else if (cst instanceof Long) { 520 * // ... 521 * } else if (cst instanceof Double) { 522 * // ... 523 * } else if (cst instanceof String) { 524 * // ... 525 * } else if (cst instanceof Type) { 526 * int sort = ((Type) cst).getSort(); 527 * if (sort == Type.OBJECT) { 528 * // ... 529 * } else if (sort == Type.ARRAY) { 530 * // ... 531 * } else if (sort == Type.METHOD) { 532 * // ... 533 * } else { 534 * // throw an exception 535 * } 536 * } else if (cst instanceof Handle) { 537 * // ... 538 * } else if (cst instanceof ConstantDynamic) { 539 * // ... 540 * } else { 541 * // throw an exception 542 * } 543 * </pre> 544 * 545 * @param value the constant to be loaded on the stack. This parameter must be a non null {@link 546 * Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link 547 * Type} of OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is 548 * 49, a {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle 549 * constants, for classes whose version is 51 or a {@link ConstantDynamic} for a constant 550 * dynamic for classes whose version is 55. 551 */ 552 public void visitLdcInsn(final Object value) { 553 if (api < Opcodes.ASM5 554 && (value instanceof Handle 555 || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) { 556 throw new UnsupportedOperationException(REQUIRES_ASM5); 557 } 558 if (api < Opcodes.ASM7 && value instanceof ConstantDynamic) { 559 throw new UnsupportedOperationException("This feature requires ASM7"); 560 } 561 if (mv != null) { 562 mv.visitLdcInsn(value); 563 } 564 } 565 566 /** 567 * Visits an IINC instruction. 568 * 569 * @param varIndex index of the local variable to be incremented. 570 * @param increment amount to increment the local variable by. 571 */ 572 public void visitIincInsn(final int varIndex, final int increment) { 573 if (mv != null) { 574 mv.visitIincInsn(varIndex, increment); 575 } 576 } 577 578 /** 579 * Visits a TABLESWITCH instruction. 580 * 581 * @param min the minimum key value. 582 * @param max the maximum key value. 583 * @param dflt beginning of the default handler block. 584 * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the 585 * handler block for the {@code min + i} key. 586 */ 587 public void visitTableSwitchInsn( 588 final int min, final int max, final Label dflt, final Label... labels) { 589 if (mv != null) { 590 mv.visitTableSwitchInsn(min, max, dflt, labels); 591 } 592 } 593 594 /** 595 * Visits a LOOKUPSWITCH instruction. 596 * 597 * @param dflt beginning of the default handler block. 598 * @param keys the values of the keys. 599 * @param labels beginnings of the handler blocks. {@code labels[i]} is the beginning of the 600 * handler block for the {@code keys[i]} key. 601 */ 602 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { 603 if (mv != null) { 604 mv.visitLookupSwitchInsn(dflt, keys, labels); 605 } 606 } 607 608 /** 609 * Visits a MULTIANEWARRAY instruction. 610 * 611 * @param descriptor an array type descriptor (see {@link Type}). 612 * @param numDimensions the number of dimensions of the array to allocate. 613 */ 614 public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { 615 if (mv != null) { 616 mv.visitMultiANewArrayInsn(descriptor, numDimensions); 617 } 618 } 619 620 /** 621 * Visits an annotation on an instruction. This method must be called just <i>after</i> the 622 * annotated instruction. It can be called several times for the same instruction. 623 * 624 * @param typeRef a reference to the annotated type. The sort of this type reference must be 625 * {@link TypeReference#INSTANCEOF}, {@link TypeReference#NEW}, {@link 626 * TypeReference#CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE}, {@link 627 * TypeReference#CAST}, {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link 628 * TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT}, {@link 629 * TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link 630 * TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}. 631 * @param typePath the path to the annotated type argument, wildcard bound, array element type, or 632 * static inner type within 'typeRef'. May be {@literal null} if the annotation targets 633 * 'typeRef' as a whole. 634 * @param descriptor the class descriptor of the annotation class. 635 * @param visible {@literal true} if the annotation is visible at runtime. 636 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 637 * interested in visiting this annotation. 638 */ 639 public AnnotationVisitor visitInsnAnnotation( 640 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 641 if (api < Opcodes.ASM5) { 642 throw new UnsupportedOperationException(REQUIRES_ASM5); 643 } 644 if (mv != null) { 645 return mv.visitInsnAnnotation(typeRef, typePath, descriptor, visible); 646 } 647 return null; 648 } 649 650 // ----------------------------------------------------------------------------------------------- 651 // Exceptions table entries, debug information, max stack and max locals 652 // ----------------------------------------------------------------------------------------------- 653 654 /** 655 * Visits a try catch block. 656 * 657 * @param start the beginning of the exception handler's scope (inclusive). 658 * @param end the end of the exception handler's scope (exclusive). 659 * @param handler the beginning of the exception handler's code. 660 * @param type the internal name of the type of exceptions handled by the handler (see {@link 661 * Type#getInternalName()}), or {@literal null} to catch any exceptions (for "finally" 662 * blocks). 663 * @throws IllegalArgumentException if one of the labels has already been visited by this visitor 664 * (by the {@link #visitLabel} method). 665 */ 666 public void visitTryCatchBlock( 667 final Label start, final Label end, final Label handler, final String type) { 668 if (mv != null) { 669 mv.visitTryCatchBlock(start, end, handler, type); 670 } 671 } 672 673 /** 674 * Visits an annotation on an exception handler type. This method must be called <i>after</i> the 675 * {@link #visitTryCatchBlock} for the annotated exception handler. It can be called several times 676 * for the same exception handler. 677 * 678 * @param typeRef a reference to the annotated type. The sort of this type reference must be 679 * {@link TypeReference#EXCEPTION_PARAMETER}. See {@link TypeReference}. 680 * @param typePath the path to the annotated type argument, wildcard bound, array element type, or 681 * static inner type within 'typeRef'. May be {@literal null} if the annotation targets 682 * 'typeRef' as a whole. 683 * @param descriptor the class descriptor of the annotation class. 684 * @param visible {@literal true} if the annotation is visible at runtime. 685 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 686 * interested in visiting this annotation. 687 */ 688 public AnnotationVisitor visitTryCatchAnnotation( 689 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 690 if (api < Opcodes.ASM5) { 691 throw new UnsupportedOperationException(REQUIRES_ASM5); 692 } 693 if (mv != null) { 694 return mv.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); 695 } 696 return null; 697 } 698 699 /** 700 * Visits a local variable declaration. 701 * 702 * @param name the name of a local variable. 703 * @param descriptor the type descriptor of this local variable. 704 * @param signature the type signature of this local variable. May be {@literal null} if the local 705 * variable type does not use generic types. 706 * @param start the first instruction corresponding to the scope of this local variable 707 * (inclusive). 708 * @param end the last instruction corresponding to the scope of this local variable (exclusive). 709 * @param index the local variable's index. 710 * @throws IllegalArgumentException if one of the labels has not already been visited by this 711 * visitor (by the {@link #visitLabel} method). 712 */ 713 public void visitLocalVariable( 714 final String name, 715 final String descriptor, 716 final String signature, 717 final Label start, 718 final Label end, 719 final int index) { 720 if (mv != null) { 721 mv.visitLocalVariable(name, descriptor, signature, start, end, index); 722 } 723 } 724 725 /** 726 * Visits an annotation on a local variable type. 727 * 728 * @param typeRef a reference to the annotated type. The sort of this type reference must be 729 * {@link TypeReference#LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE}. See {@link 730 * TypeReference}. 731 * @param typePath the path to the annotated type argument, wildcard bound, array element type, or 732 * static inner type within 'typeRef'. May be {@literal null} if the annotation targets 733 * 'typeRef' as a whole. 734 * @param start the fist instructions corresponding to the continuous ranges that make the scope 735 * of this local variable (inclusive). 736 * @param end the last instructions corresponding to the continuous ranges that make the scope of 737 * this local variable (exclusive). This array must have the same size as the 'start' array. 738 * @param index the local variable's index in each range. This array must have the same size as 739 * the 'start' array. 740 * @param descriptor the class descriptor of the annotation class. 741 * @param visible {@literal true} if the annotation is visible at runtime. 742 * @return a visitor to visit the annotation values, or {@literal null} if this visitor is not 743 * interested in visiting this annotation. 744 */ 745 public AnnotationVisitor visitLocalVariableAnnotation( 746 final int typeRef, 747 final TypePath typePath, 748 final Label[] start, 749 final Label[] end, 750 final int[] index, 751 final String descriptor, 752 final boolean visible) { 753 if (api < Opcodes.ASM5) { 754 throw new UnsupportedOperationException(REQUIRES_ASM5); 755 } 756 if (mv != null) { 757 return mv.visitLocalVariableAnnotation( 758 typeRef, typePath, start, end, index, descriptor, visible); 759 } 760 return null; 761 } 762 763 /** 764 * Visits a line number declaration. 765 * 766 * @param line a line number. This number refers to the source file from which the class was 767 * compiled. 768 * @param start the first instruction corresponding to this line number. 769 * @throws IllegalArgumentException if {@code start} has not already been visited by this visitor 770 * (by the {@link #visitLabel} method). 771 */ 772 public void visitLineNumber(final int line, final Label start) { 773 if (mv != null) { 774 mv.visitLineNumber(line, start); 775 } 776 } 777 778 /** 779 * Visits the maximum stack size and the maximum number of local variables of the method. 780 * 781 * @param maxStack maximum stack size of the method. 782 * @param maxLocals maximum number of local variables for the method. 783 */ 784 public void visitMaxs(final int maxStack, final int maxLocals) { 785 if (mv != null) { 786 mv.visitMaxs(maxStack, maxLocals); 787 } 788 } 789 790 /** 791 * Visits the end of the method. This method, which is the last one to be called, is used to 792 * inform the visitor that all the annotations and attributes of the method have been visited. 793 */ 794 public void visitEnd() { 795 if (mv != null) { 796 mv.visitEnd(); 797 } 798 } 799}