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