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