1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm.tree; 60 61 import java.util.ArrayList; 62 import java.util.Arrays; 63 import java.util.List; 64 65 import jdk.internal.org.objectweb.asm.AnnotationVisitor; 66 import jdk.internal.org.objectweb.asm.Attribute; 67 import jdk.internal.org.objectweb.asm.ClassVisitor; 68 import jdk.internal.org.objectweb.asm.Handle; 69 import jdk.internal.org.objectweb.asm.Label; 70 import jdk.internal.org.objectweb.asm.MethodVisitor; 71 import jdk.internal.org.objectweb.asm.Opcodes; 72 import jdk.internal.org.objectweb.asm.Type; 73 import jdk.internal.org.objectweb.asm.TypePath; 74 75 /** 76 * A node that represents a method. 77 * 78 * @author Eric Bruneton 79 */ 80 public class MethodNode extends MethodVisitor { 81 82 /** 83 * The method's access flags (see {@link Opcodes}). This field also 84 * indicates if the method is synthetic and/or deprecated. 85 */ 86 public int access; 87 88 /** 89 * The method's name. 90 */ 91 public String name; 92 93 /** 94 * The method's descriptor (see {@link Type}). 95 */ 96 public String desc; 97 98 /** 99 * The method's signature. May be <tt>null</tt>. 100 */ 101 public String signature; 102 103 /** 104 * The internal names of the method's exception classes (see 105 * {@link Type#getInternalName() getInternalName}). This list is a list of 106 * {@link String} objects. 107 */ 108 public List<String> exceptions; 109 110 /** 111 * The method parameter info (access flags and name) 112 */ 113 public List<ParameterNode> parameters; 114 115 /** 116 * The runtime visible annotations of this method. This list is a list of 117 * {@link AnnotationNode} objects. May be <tt>null</tt>. 118 * 119 * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode 120 * @label visible 121 */ 122 public List<AnnotationNode> visibleAnnotations; 123 124 /** 125 * The runtime invisible annotations of this method. This list is a list of 126 * {@link AnnotationNode} objects. May be <tt>null</tt>. 127 * 128 * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode 129 * @label invisible 130 */ 131 public List<AnnotationNode> invisibleAnnotations; 132 133 /** 134 * The runtime visible type annotations of this method. This list is a list 135 * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. 136 * 137 * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode 138 * @label visible 139 */ 140 public List<TypeAnnotationNode> visibleTypeAnnotations; 141 142 /** 143 * The runtime invisible type annotations of this method. This list is a 144 * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>. 145 * 146 * @associates jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode 147 * @label invisible 148 */ 149 public List<TypeAnnotationNode> invisibleTypeAnnotations; 150 151 /** 152 * The non standard attributes of this method. This list is a list of 153 * {@link Attribute} objects. May be <tt>null</tt>. 154 * 155 * @associates jdk.internal.org.objectweb.asm.Attribute 156 */ 157 public List<Attribute> attrs; 158 159 /** 160 * The default value of this annotation interface method. This field must be 161 * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short}, 162 * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, 163 * {@link String} or {@link Type}, or an two elements String array (for 164 * enumeration values), a {@link AnnotationNode}, or a {@link List} of 165 * values of one of the preceding types. May be <tt>null</tt>. 166 */ 167 public Object annotationDefault; 168 169 /** 170 * The runtime visible parameter annotations of this method. These lists are 171 * lists of {@link AnnotationNode} objects. May be <tt>null</tt>. 172 * 173 * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode 174 * @label invisible parameters 175 */ 176 public List<AnnotationNode>[] visibleParameterAnnotations; 177 178 /** 179 * The runtime invisible parameter annotations of this method. These lists 180 * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>. 181 * 182 * @associates jdk.internal.org.objectweb.asm.tree.AnnotationNode 183 * @label visible parameters 184 */ 185 public List<AnnotationNode>[] invisibleParameterAnnotations; 186 187 /** 188 * The instructions of this method. This list is a list of 189 * {@link AbstractInsnNode} objects. 190 * 191 * @associates jdk.internal.org.objectweb.asm.tree.AbstractInsnNode 192 * @label instructions 193 */ 194 public InsnList instructions; 195 196 /** 197 * The try catch blocks of this method. This list is a list of 198 * {@link TryCatchBlockNode} objects. 199 * 200 * @associates jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode 201 */ 202 public List<TryCatchBlockNode> tryCatchBlocks; 203 204 /** 205 * The maximum stack size of this method. 206 */ 207 public int maxStack; 208 209 /** 210 * The maximum number of local variables of this method. 211 */ 212 public int maxLocals; 213 214 /** 215 * The local variables of this method. This list is a list of 216 * {@link LocalVariableNode} objects. May be <tt>null</tt> 217 * 218 * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableNode 219 */ 220 public List<LocalVariableNode> localVariables; 221 222 /** 223 * The visible local variable annotations of this method. This list is a 224 * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt> 225 * 226 * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode 227 */ 228 public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations; 229 230 /** 231 * The invisible local variable annotations of this method. This list is a 232 * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt> 233 * 234 * @associates jdk.internal.org.objectweb.asm.tree.LocalVariableAnnotationNode 235 */ 236 public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations; 237 238 /** 239 * If the accept method has been called on this object. 240 */ 241 private boolean visited; 242 243 /** 244 * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not 245 * use this constructor</i>. Instead, they must use the 246 * {@link #MethodNode(int)} version. 247 * 248 * @throws IllegalStateException 249 * If a subclass calls this constructor. 250 */ 251 public MethodNode() { 252 this(Opcodes.ASM5); 253 if (getClass() != MethodNode.class) { 254 throw new IllegalStateException(); 255 } 256 } 257 258 /** 259 * Constructs an uninitialized {@link MethodNode}. 260 * 261 * @param api 262 * the ASM API version implemented by this visitor. Must be one 263 * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 264 */ 265 public MethodNode(final int api) { 266 super(api); 267 this.instructions = new InsnList(); 268 } 269 270 /** 271 * Constructs a new {@link MethodNode}. <i>Subclasses must not use this 272 * constructor</i>. Instead, they must use the 273 * {@link #MethodNode(int, int, String, String, String, String[])} version. 274 * 275 * @param access 276 * the method's access flags (see {@link Opcodes}). This 277 * parameter also indicates if the method is synthetic and/or 278 * deprecated. 279 * @param name 280 * the method's name. 281 * @param desc 282 * the method's descriptor (see {@link Type}). 283 * @param signature 284 * the method's signature. May be <tt>null</tt>. 285 * @param exceptions 286 * the internal names of the method's exception classes (see 287 * {@link Type#getInternalName() getInternalName}). May be 288 * <tt>null</tt>. 289 * @throws IllegalStateException 290 * If a subclass calls this constructor. 291 */ 292 public MethodNode(final int access, final String name, final String desc, 293 final String signature, final String[] exceptions) { 294 this(Opcodes.ASM5, access, name, desc, signature, exceptions); 295 if (getClass() != MethodNode.class) { 296 throw new IllegalStateException(); 297 } 298 } 299 300 /** 301 * Constructs a new {@link MethodNode}. 302 * 303 * @param api 304 * the ASM API version implemented by this visitor. Must be one 305 * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 306 * @param access 307 * the method's access flags (see {@link Opcodes}). This 308 * parameter also indicates if the method is synthetic and/or 309 * deprecated. 310 * @param name 311 * the method's name. 312 * @param desc 313 * the method's descriptor (see {@link Type}). 314 * @param signature 315 * the method's signature. May be <tt>null</tt>. 316 * @param exceptions 317 * the internal names of the method's exception classes (see 318 * {@link Type#getInternalName() getInternalName}). May be 319 * <tt>null</tt>. 320 */ 321 public MethodNode(final int api, final int access, final String name, 322 final String desc, final String signature, final String[] exceptions) { 323 super(api); 324 this.access = access; 325 this.name = name; 326 this.desc = desc; 327 this.signature = signature; 328 this.exceptions = new ArrayList<String>(exceptions == null ? 0 329 : exceptions.length); 330 boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0; 331 if (!isAbstract) { 332 this.localVariables = new ArrayList<LocalVariableNode>(5); 333 } 334 this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(); 335 if (exceptions != null) { 336 this.exceptions.addAll(Arrays.asList(exceptions)); 337 } 338 this.instructions = new InsnList(); 339 } 340 341 // ------------------------------------------------------------------------ 342 // Implementation of the MethodVisitor abstract class 343 // ------------------------------------------------------------------------ 344 345 @Override 346 public void visitParameter(String name, int access) { 347 if (parameters == null) { 348 parameters = new ArrayList<ParameterNode>(5); 349 } 350 parameters.add(new ParameterNode(name, access)); 351 } 352 353 @Override 354 public AnnotationVisitor visitAnnotationDefault() { 355 return new AnnotationNode(new ArrayList<Object>(0) { 356 @Override 357 public boolean add(final Object o) { 358 annotationDefault = o; 359 return super.add(o); 360 } 361 }); 362 } 363 364 @Override 365 public AnnotationVisitor visitAnnotation(final String desc, 366 final boolean visible) { 367 AnnotationNode an = new AnnotationNode(desc); 368 if (visible) { 369 if (visibleAnnotations == null) { 370 visibleAnnotations = new ArrayList<AnnotationNode>(1); 371 } 372 visibleAnnotations.add(an); 373 } else { 374 if (invisibleAnnotations == null) { 375 invisibleAnnotations = new ArrayList<AnnotationNode>(1); 376 } 377 invisibleAnnotations.add(an); 378 } 379 return an; 380 } 381 382 @Override 383 public AnnotationVisitor visitTypeAnnotation(int typeRef, 384 TypePath typePath, String desc, boolean visible) { 385 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 386 if (visible) { 387 if (visibleTypeAnnotations == null) { 388 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 389 } 390 visibleTypeAnnotations.add(an); 391 } else { 392 if (invisibleTypeAnnotations == null) { 393 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 394 } 395 invisibleTypeAnnotations.add(an); 396 } 397 return an; 398 } 399 400 @Override 401 public AnnotationVisitor visitParameterAnnotation(final int parameter, 402 final String desc, final boolean visible) { 403 AnnotationNode an = new AnnotationNode(desc); 404 if (visible) { 405 if (visibleParameterAnnotations == null) { 406 int params = Type.getArgumentTypes(this.desc).length; 407 visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 408 } 409 if (visibleParameterAnnotations[parameter] == null) { 410 visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( 411 1); 412 } 413 visibleParameterAnnotations[parameter].add(an); 414 } else { 415 if (invisibleParameterAnnotations == null) { 416 int params = Type.getArgumentTypes(this.desc).length; 417 invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 418 } 419 if (invisibleParameterAnnotations[parameter] == null) { 420 invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( 421 1); 422 } 423 invisibleParameterAnnotations[parameter].add(an); 424 } 425 return an; 426 } 427 428 @Override 429 public void visitAttribute(final Attribute attr) { 430 if (attrs == null) { 431 attrs = new ArrayList<Attribute>(1); 432 } 433 attrs.add(attr); 434 } 435 436 @Override 437 public void visitCode() { 438 } 439 440 @Override 441 public void visitFrame(final int type, final int nLocal, 442 final Object[] local, final int nStack, final Object[] stack) { 443 instructions.add(new FrameNode(type, nLocal, local == null ? null 444 : getLabelNodes(local), nStack, stack == null ? null 445 : getLabelNodes(stack))); 446 } 447 448 @Override 449 public void visitInsn(final int opcode) { 450 instructions.add(new InsnNode(opcode)); 451 } 452 453 @Override 454 public void visitIntInsn(final int opcode, final int operand) { 455 instructions.add(new IntInsnNode(opcode, operand)); 456 } 457 458 @Override 459 public void visitVarInsn(final int opcode, final int var) { 460 instructions.add(new VarInsnNode(opcode, var)); 461 } 462 463 @Override 464 public void visitTypeInsn(final int opcode, final String type) { 465 instructions.add(new TypeInsnNode(opcode, type)); 466 } 467 468 @Override 469 public void visitFieldInsn(final int opcode, final String owner, 470 final String name, final String desc) { 471 instructions.add(new FieldInsnNode(opcode, owner, name, desc)); 472 } 473 474 @Deprecated 475 @Override 476 public void visitMethodInsn(int opcode, String owner, String name, 477 String desc) { 478 if (api >= Opcodes.ASM5) { 479 super.visitMethodInsn(opcode, owner, name, desc); 480 return; 481 } 482 instructions.add(new MethodInsnNode(opcode, owner, name, desc)); 483 } 484 485 @Override 486 public void visitMethodInsn(int opcode, String owner, String name, 487 String desc, boolean itf) { 488 if (api < Opcodes.ASM5) { 489 super.visitMethodInsn(opcode, owner, name, desc, itf); 490 return; 491 } 492 instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); 493 } 494 495 @Override 496 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 497 Object... bsmArgs) { 498 instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)); 499 } 500 501 @Override 502 public void visitJumpInsn(final int opcode, final Label label) { 503 instructions.add(new JumpInsnNode(opcode, getLabelNode(label))); 504 } 505 506 @Override 507 public void visitLabel(final Label label) { 508 instructions.add(getLabelNode(label)); 509 } 510 511 @Override 512 public void visitLdcInsn(final Object cst) { 513 instructions.add(new LdcInsnNode(cst)); 514 } 515 516 @Override 517 public void visitIincInsn(final int var, final int increment) { 518 instructions.add(new IincInsnNode(var, increment)); 519 } 520 521 @Override 522 public void visitTableSwitchInsn(final int min, final int max, 523 final Label dflt, final Label... labels) { 524 instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), 525 getLabelNodes(labels))); 526 } 527 528 @Override 529 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 530 final Label[] labels) { 531 instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, 532 getLabelNodes(labels))); 533 } 534 535 @Override 536 public void visitMultiANewArrayInsn(final String desc, final int dims) { 537 instructions.add(new MultiANewArrayInsnNode(desc, dims)); 538 } 539 540 @Override 541 public AnnotationVisitor visitInsnAnnotation(int typeRef, 542 TypePath typePath, String desc, boolean visible) { 543 // Finds the last real instruction, i.e. the instruction targeted by 544 // this annotation. 545 AbstractInsnNode insn = instructions.getLast(); 546 while (insn.getOpcode() == -1) { 547 insn = insn.getPrevious(); 548 } 549 // Adds the annotation to this instruction. 550 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 551 if (visible) { 552 if (insn.visibleTypeAnnotations == null) { 553 insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 554 1); 555 } 556 insn.visibleTypeAnnotations.add(an); 557 } else { 558 if (insn.invisibleTypeAnnotations == null) { 559 insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 560 1); 561 } 562 insn.invisibleTypeAnnotations.add(an); 563 } 564 return an; 565 } 566 567 @Override 568 public void visitTryCatchBlock(final Label start, final Label end, 569 final Label handler, final String type) { 570 tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start), 571 getLabelNode(end), getLabelNode(handler), type)); 572 } 573 574 @Override 575 public AnnotationVisitor visitTryCatchAnnotation(int typeRef, 576 TypePath typePath, String desc, boolean visible) { 577 TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8); 578 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 579 if (visible) { 580 if (tcb.visibleTypeAnnotations == null) { 581 tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 582 1); 583 } 584 tcb.visibleTypeAnnotations.add(an); 585 } else { 586 if (tcb.invisibleTypeAnnotations == null) { 587 tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 588 1); 589 } 590 tcb.invisibleTypeAnnotations.add(an); 591 } 592 return an; 593 } 594 595 @Override 596 public void visitLocalVariable(final String name, final String desc, 597 final String signature, final Label start, final Label end, 598 final int index) { 599 localVariables.add(new LocalVariableNode(name, desc, signature, 600 getLabelNode(start), getLabelNode(end), index)); 601 } 602 603 @Override 604 public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, 605 TypePath typePath, Label[] start, Label[] end, int[] index, 606 String desc, boolean visible) { 607 LocalVariableAnnotationNode an = new LocalVariableAnnotationNode( 608 typeRef, typePath, getLabelNodes(start), getLabelNodes(end), 609 index, desc); 610 if (visible) { 611 if (visibleLocalVariableAnnotations == null) { 612 visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( 613 1); 614 } 615 visibleLocalVariableAnnotations.add(an); 616 } else { 617 if (invisibleLocalVariableAnnotations == null) { 618 invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( 619 1); 620 } 621 invisibleLocalVariableAnnotations.add(an); 622 } 623 return an; 624 } 625 626 @Override 627 public void visitLineNumber(final int line, final Label start) { 628 instructions.add(new LineNumberNode(line, getLabelNode(start))); 629 } 630 631 @Override 632 public void visitMaxs(final int maxStack, final int maxLocals) { 633 this.maxStack = maxStack; 634 this.maxLocals = maxLocals; 635 } 636 637 @Override 638 public void visitEnd() { 639 } 640 641 /** 642 * Returns the LabelNode corresponding to the given Label. Creates a new 643 * LabelNode if necessary. The default implementation of this method uses 644 * the {@link Label#info} field to store associations between labels and 645 * label nodes. 646 * 647 * @param l 648 * a Label. 649 * @return the LabelNode corresponding to l. 650 */ 651 protected LabelNode getLabelNode(final Label l) { 652 if (!(l.info instanceof LabelNode)) { 653 l.info = new LabelNode(); 654 } 655 return (LabelNode) l.info; 656 } 657 658 private LabelNode[] getLabelNodes(final Label[] l) { 659 LabelNode[] nodes = new LabelNode[l.length]; 660 for (int i = 0; i < l.length; ++i) { 661 nodes[i] = getLabelNode(l[i]); 662 } 663 return nodes; 664 } 665 666 private Object[] getLabelNodes(final Object[] objs) { 667 Object[] nodes = new Object[objs.length]; 668 for (int i = 0; i < objs.length; ++i) { 669 Object o = objs[i]; 670 if (o instanceof Label) { 671 o = getLabelNode((Label) o); 672 } 673 nodes[i] = o; 674 } 675 return nodes; 676 } 677 678 // ------------------------------------------------------------------------ 679 // Accept method 680 // ------------------------------------------------------------------------ 681 682 /** 683 * Checks that this method node is compatible with the given ASM API 684 * version. This methods checks that this node, and all its nodes 685 * recursively, do not contain elements that were introduced in more recent 686 * versions of the ASM API than the given version. 687 * 688 * @param api 689 * an ASM API version. Must be one of {@link Opcodes#ASM4} or 690 * {@link Opcodes#ASM5}. 691 */ 692 public void check(final int api) { 693 if (api == Opcodes.ASM4) { 694 if (visibleTypeAnnotations != null 695 && visibleTypeAnnotations.size() > 0) { 696 throw new RuntimeException(); 697 } 698 if (invisibleTypeAnnotations != null 699 && invisibleTypeAnnotations.size() > 0) { 700 throw new RuntimeException(); 701 } 702 int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); 703 for (int i = 0; i < n; ++i) { 704 TryCatchBlockNode tcb = tryCatchBlocks.get(i); 705 if (tcb.visibleTypeAnnotations != null 706 && tcb.visibleTypeAnnotations.size() > 0) { 707 throw new RuntimeException(); 708 } 709 if (tcb.invisibleTypeAnnotations != null 710 && tcb.invisibleTypeAnnotations.size() > 0) { 711 throw new RuntimeException(); 712 } 713 } 714 for (int i = 0; i < instructions.size(); ++i) { 715 AbstractInsnNode insn = instructions.get(i); 716 if (insn.visibleTypeAnnotations != null 717 && insn.visibleTypeAnnotations.size() > 0) { 718 throw new RuntimeException(); 719 } 720 if (insn.invisibleTypeAnnotations != null 721 && insn.invisibleTypeAnnotations.size() > 0) { 722 throw new RuntimeException(); 723 } 724 if (insn instanceof MethodInsnNode) { 725 boolean itf = ((MethodInsnNode) insn).itf; 726 if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) { 727 throw new RuntimeException(); 728 } 729 } 730 } 731 if (visibleLocalVariableAnnotations != null 732 && visibleLocalVariableAnnotations.size() > 0) { 733 throw new RuntimeException(); 734 } 735 if (invisibleLocalVariableAnnotations != null 736 && invisibleLocalVariableAnnotations.size() > 0) { 737 throw new RuntimeException(); 738 } 739 } 740 } 741 742 /** 743 * Makes the given class visitor visit this method. 744 * 745 * @param cv 746 * a class visitor. 747 */ 748 public void accept(final ClassVisitor cv) { 749 String[] exceptions = new String[this.exceptions.size()]; 750 this.exceptions.toArray(exceptions); 751 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, 752 exceptions); 753 if (mv != null) { 754 accept(mv); 755 } 756 } 757 758 /** 759 * Makes the given method visitor visit this method. 760 * 761 * @param mv 762 * a method visitor. 763 */ 764 public void accept(final MethodVisitor mv) { 765 // visits the method parameters 766 int i, j, n; 767 n = parameters == null ? 0 : parameters.size(); 768 for (i = 0; i < n; i++) { 769 ParameterNode parameter = parameters.get(i); 770 mv.visitParameter(parameter.name, parameter.access); 771 } 772 // visits the method attributes 773 if (annotationDefault != null) { 774 AnnotationVisitor av = mv.visitAnnotationDefault(); 775 AnnotationNode.accept(av, null, annotationDefault); 776 if (av != null) { 777 av.visitEnd(); 778 } 779 } 780 n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); 781 for (i = 0; i < n; ++i) { 782 AnnotationNode an = visibleAnnotations.get(i); 783 an.accept(mv.visitAnnotation(an.desc, true)); 784 } 785 n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); 786 for (i = 0; i < n; ++i) { 787 AnnotationNode an = invisibleAnnotations.get(i); 788 an.accept(mv.visitAnnotation(an.desc, false)); 789 } 790 n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); 791 for (i = 0; i < n; ++i) { 792 TypeAnnotationNode an = visibleTypeAnnotations.get(i); 793 an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 794 true)); 795 } 796 n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations 797 .size(); 798 for (i = 0; i < n; ++i) { 799 TypeAnnotationNode an = invisibleTypeAnnotations.get(i); 800 an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 801 false)); 802 } 803 n = visibleParameterAnnotations == null ? 0 804 : visibleParameterAnnotations.length; 805 for (i = 0; i < n; ++i) { 806 List<?> l = visibleParameterAnnotations[i]; 807 if (l == null) { 808 continue; 809 } 810 for (j = 0; j < l.size(); ++j) { 811 AnnotationNode an = (AnnotationNode) l.get(j); 812 an.accept(mv.visitParameterAnnotation(i, an.desc, true)); 813 } 814 } 815 n = invisibleParameterAnnotations == null ? 0 816 : invisibleParameterAnnotations.length; 817 for (i = 0; i < n; ++i) { 818 List<?> l = invisibleParameterAnnotations[i]; 819 if (l == null) { 820 continue; 821 } 822 for (j = 0; j < l.size(); ++j) { 823 AnnotationNode an = (AnnotationNode) l.get(j); 824 an.accept(mv.visitParameterAnnotation(i, an.desc, false)); 825 } 826 } 827 if (visited) { 828 instructions.resetLabels(); 829 } 830 n = attrs == null ? 0 : attrs.size(); 831 for (i = 0; i < n; ++i) { 832 mv.visitAttribute(attrs.get(i)); 833 } 834 // visits the method's code 835 if (instructions.size() > 0) { 836 mv.visitCode(); 837 // visits try catch blocks 838 n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); 839 for (i = 0; i < n; ++i) { 840 tryCatchBlocks.get(i).updateIndex(i); 841 tryCatchBlocks.get(i).accept(mv); 842 } 843 // visits instructions 844 instructions.accept(mv); 845 // visits local variables 846 n = localVariables == null ? 0 : localVariables.size(); 847 for (i = 0; i < n; ++i) { 848 localVariables.get(i).accept(mv); 849 } 850 // visits local variable annotations 851 n = visibleLocalVariableAnnotations == null ? 0 852 : visibleLocalVariableAnnotations.size(); 853 for (i = 0; i < n; ++i) { 854 visibleLocalVariableAnnotations.get(i).accept(mv, true); 855 } 856 n = invisibleLocalVariableAnnotations == null ? 0 857 : invisibleLocalVariableAnnotations.size(); 858 for (i = 0; i < n; ++i) { 859 invisibleLocalVariableAnnotations.get(i).accept(mv, false); 860 } 861 // visits maxs 862 mv.visitMaxs(maxStack, maxLocals); 863 visited = true; 864 } 865 mv.visitEnd(); 866 } 867 }