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