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 @SuppressWarnings("serial") 355 public AnnotationVisitor visitAnnotationDefault() { 356 return new AnnotationNode(new ArrayList<Object>(0) { 357 @Override 358 public boolean add(final Object o) { 359 annotationDefault = o; 360 return super.add(o); 361 } 362 }); 363 } 364 365 @Override 366 public AnnotationVisitor visitAnnotation(final String desc, 367 final boolean visible) { 368 AnnotationNode an = new AnnotationNode(desc); 369 if (visible) { 370 if (visibleAnnotations == null) { 371 visibleAnnotations = new ArrayList<AnnotationNode>(1); 372 } 373 visibleAnnotations.add(an); 374 } else { 375 if (invisibleAnnotations == null) { 376 invisibleAnnotations = new ArrayList<AnnotationNode>(1); 377 } 378 invisibleAnnotations.add(an); 379 } 380 return an; 381 } 382 383 @Override 384 public AnnotationVisitor visitTypeAnnotation(int typeRef, 385 TypePath typePath, String desc, boolean visible) { 386 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 387 if (visible) { 388 if (visibleTypeAnnotations == null) { 389 visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 390 } 391 visibleTypeAnnotations.add(an); 392 } else { 393 if (invisibleTypeAnnotations == null) { 394 invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1); 395 } 396 invisibleTypeAnnotations.add(an); 397 } 398 return an; 399 } 400 401 @Override 402 @SuppressWarnings("unchecked") 403 public AnnotationVisitor visitParameterAnnotation(final int parameter, 404 final String desc, final boolean visible) { 405 AnnotationNode an = new AnnotationNode(desc); 406 if (visible) { 407 if (visibleParameterAnnotations == null) { 408 int params = Type.getArgumentTypes(this.desc).length; 409 visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 410 } 411 if (visibleParameterAnnotations[parameter] == null) { 412 visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( 413 1); 414 } 415 visibleParameterAnnotations[parameter].add(an); 416 } else { 417 if (invisibleParameterAnnotations == null) { 418 int params = Type.getArgumentTypes(this.desc).length; 419 invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 420 } 421 if (invisibleParameterAnnotations[parameter] == null) { 422 invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>( 423 1); 424 } 425 invisibleParameterAnnotations[parameter].add(an); 426 } 427 return an; 428 } 429 430 @Override 431 public void visitAttribute(final Attribute attr) { 432 if (attrs == null) { 433 attrs = new ArrayList<Attribute>(1); 434 } 435 attrs.add(attr); 436 } 437 438 @Override 439 public void visitCode() { 440 } 441 442 @Override 443 public void visitFrame(final int type, final int nLocal, 444 final Object[] local, final int nStack, final Object[] stack) { 445 instructions.add(new FrameNode(type, nLocal, local == null ? null 446 : getLabelNodes(local), nStack, stack == null ? null 447 : getLabelNodes(stack))); 448 } 449 450 @Override 451 public void visitInsn(final int opcode) { 452 instructions.add(new InsnNode(opcode)); 453 } 454 455 @Override 456 public void visitIntInsn(final int opcode, final int operand) { 457 instructions.add(new IntInsnNode(opcode, operand)); 458 } 459 460 @Override 461 public void visitVarInsn(final int opcode, final int var) { 462 instructions.add(new VarInsnNode(opcode, var)); 463 } 464 465 @Override 466 public void visitTypeInsn(final int opcode, final String type) { 467 instructions.add(new TypeInsnNode(opcode, type)); 468 } 469 470 @Override 471 public void visitFieldInsn(final int opcode, final String owner, 472 final String name, final String desc) { 473 instructions.add(new FieldInsnNode(opcode, owner, name, desc)); 474 } 475 476 @Deprecated 477 @Override 478 public void visitMethodInsn(int opcode, String owner, String name, 479 String desc) { 480 if (api >= Opcodes.ASM5) { 481 super.visitMethodInsn(opcode, owner, name, desc); 482 return; 483 } 484 instructions.add(new MethodInsnNode(opcode, owner, name, desc)); 485 } 486 487 @Override 488 public void visitMethodInsn(int opcode, String owner, String name, 489 String desc, boolean itf) { 490 if (api < Opcodes.ASM5) { 491 super.visitMethodInsn(opcode, owner, name, desc, itf); 492 return; 493 } 494 instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); 495 } 496 497 @Override 498 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 499 Object... bsmArgs) { 500 instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)); 501 } 502 503 @Override 504 public void visitJumpInsn(final int opcode, final Label label) { 505 instructions.add(new JumpInsnNode(opcode, getLabelNode(label))); 506 } 507 508 @Override 509 public void visitLabel(final Label label) { 510 instructions.add(getLabelNode(label)); 511 } 512 513 @Override 514 public void visitLdcInsn(final Object cst) { 515 instructions.add(new LdcInsnNode(cst)); 516 } 517 518 @Override 519 public void visitIincInsn(final int var, final int increment) { 520 instructions.add(new IincInsnNode(var, increment)); 521 } 522 523 @Override 524 public void visitTableSwitchInsn(final int min, final int max, 525 final Label dflt, final Label... labels) { 526 instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), 527 getLabelNodes(labels))); 528 } 529 530 @Override 531 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 532 final Label[] labels) { 533 instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, 534 getLabelNodes(labels))); 535 } 536 537 @Override 538 public void visitMultiANewArrayInsn(final String desc, final int dims) { 539 instructions.add(new MultiANewArrayInsnNode(desc, dims)); 540 } 541 542 @Override 543 public AnnotationVisitor visitInsnAnnotation(int typeRef, 544 TypePath typePath, String desc, boolean visible) { 545 // Finds the last real instruction, i.e. the instruction targeted by 546 // this annotation. 547 AbstractInsnNode insn = instructions.getLast(); 548 while (insn.getOpcode() == -1) { 549 insn = insn.getPrevious(); 550 } 551 // Adds the annotation to this instruction. 552 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 553 if (visible) { 554 if (insn.visibleTypeAnnotations == null) { 555 insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 556 1); 557 } 558 insn.visibleTypeAnnotations.add(an); 559 } else { 560 if (insn.invisibleTypeAnnotations == null) { 561 insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 562 1); 563 } 564 insn.invisibleTypeAnnotations.add(an); 565 } 566 return an; 567 } 568 569 @Override 570 public void visitTryCatchBlock(final Label start, final Label end, 571 final Label handler, final String type) { 572 tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start), 573 getLabelNode(end), getLabelNode(handler), type)); 574 } 575 576 @Override 577 public AnnotationVisitor visitTryCatchAnnotation(int typeRef, 578 TypePath typePath, String desc, boolean visible) { 579 TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8); 580 TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc); 581 if (visible) { 582 if (tcb.visibleTypeAnnotations == null) { 583 tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 584 1); 585 } 586 tcb.visibleTypeAnnotations.add(an); 587 } else { 588 if (tcb.invisibleTypeAnnotations == null) { 589 tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>( 590 1); 591 } 592 tcb.invisibleTypeAnnotations.add(an); 593 } 594 return an; 595 } 596 597 @Override 598 public void visitLocalVariable(final String name, final String desc, 599 final String signature, final Label start, final Label end, 600 final int index) { 601 localVariables.add(new LocalVariableNode(name, desc, signature, 602 getLabelNode(start), getLabelNode(end), index)); 603 } 604 605 @Override 606 public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, 607 TypePath typePath, Label[] start, Label[] end, int[] index, 608 String desc, boolean visible) { 609 LocalVariableAnnotationNode an = new LocalVariableAnnotationNode( 610 typeRef, typePath, getLabelNodes(start), getLabelNodes(end), 611 index, desc); 612 if (visible) { 613 if (visibleLocalVariableAnnotations == null) { 614 visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( 615 1); 616 } 617 visibleLocalVariableAnnotations.add(an); 618 } else { 619 if (invisibleLocalVariableAnnotations == null) { 620 invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>( 621 1); 622 } 623 invisibleLocalVariableAnnotations.add(an); 624 } 625 return an; 626 } 627 628 @Override 629 public void visitLineNumber(final int line, final Label start) { 630 instructions.add(new LineNumberNode(line, getLabelNode(start))); 631 } 632 633 @Override 634 public void visitMaxs(final int maxStack, final int maxLocals) { 635 this.maxStack = maxStack; 636 this.maxLocals = maxLocals; 637 } 638 639 @Override 640 public void visitEnd() { 641 } 642 643 /** 644 * Returns the LabelNode corresponding to the given Label. Creates a new 645 * LabelNode if necessary. The default implementation of this method uses 646 * the {@link Label#info} field to store associations between labels and 647 * label nodes. 648 * 649 * @param l 650 * a Label. 651 * @return the LabelNode corresponding to l. 652 */ 653 protected LabelNode getLabelNode(final Label l) { 654 if (!(l.info instanceof LabelNode)) { 655 l.info = new LabelNode(); 656 } 657 return (LabelNode) l.info; 658 } 659 660 private LabelNode[] getLabelNodes(final Label[] l) { 661 LabelNode[] nodes = new LabelNode[l.length]; 662 for (int i = 0; i < l.length; ++i) { 663 nodes[i] = getLabelNode(l[i]); 664 } 665 return nodes; 666 } 667 668 private Object[] getLabelNodes(final Object[] objs) { 669 Object[] nodes = new Object[objs.length]; 670 for (int i = 0; i < objs.length; ++i) { 671 Object o = objs[i]; 672 if (o instanceof Label) { 673 o = getLabelNode((Label) o); 674 } 675 nodes[i] = o; 676 } 677 return nodes; 678 } 679 680 // ------------------------------------------------------------------------ 681 // Accept method 682 // ------------------------------------------------------------------------ 683 684 /** 685 * Checks that this method node is compatible with the given ASM API 686 * version. This methods checks that this node, and all its nodes 687 * recursively, do not contain elements that were introduced in more recent 688 * versions of the ASM API than the given version. 689 * 690 * @param api 691 * an ASM API version. Must be one of {@link Opcodes#ASM4} or 692 * {@link Opcodes#ASM5}. 693 */ 694 public void check(final int api) { 695 if (api == Opcodes.ASM4) { 696 if (visibleTypeAnnotations != null 697 && visibleTypeAnnotations.size() > 0) { 698 throw new RuntimeException(); 699 } 700 if (invisibleTypeAnnotations != null 701 && invisibleTypeAnnotations.size() > 0) { 702 throw new RuntimeException(); 703 } 704 int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); 705 for (int i = 0; i < n; ++i) { 706 TryCatchBlockNode tcb = tryCatchBlocks.get(i); 707 if (tcb.visibleTypeAnnotations != null 708 && tcb.visibleTypeAnnotations.size() > 0) { 709 throw new RuntimeException(); 710 } 711 if (tcb.invisibleTypeAnnotations != null 712 && tcb.invisibleTypeAnnotations.size() > 0) { 713 throw new RuntimeException(); 714 } 715 } 716 for (int i = 0; i < instructions.size(); ++i) { 717 AbstractInsnNode insn = instructions.get(i); 718 if (insn.visibleTypeAnnotations != null 719 && insn.visibleTypeAnnotations.size() > 0) { 720 throw new RuntimeException(); 721 } 722 if (insn.invisibleTypeAnnotations != null 723 && insn.invisibleTypeAnnotations.size() > 0) { 724 throw new RuntimeException(); 725 } 726 if (insn instanceof MethodInsnNode) { 727 boolean itf = ((MethodInsnNode) insn).itf; 728 if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) { 729 throw new RuntimeException(); 730 } 731 } 732 } 733 if (visibleLocalVariableAnnotations != null 734 && visibleLocalVariableAnnotations.size() > 0) { 735 throw new RuntimeException(); 736 } 737 if (invisibleLocalVariableAnnotations != null 738 && invisibleLocalVariableAnnotations.size() > 0) { 739 throw new RuntimeException(); 740 } 741 } 742 } 743 744 /** 745 * Makes the given class visitor visit this method. 746 * 747 * @param cv 748 * a class visitor. 749 */ 750 public void accept(final ClassVisitor cv) { 751 String[] exceptions = new String[this.exceptions.size()]; 752 this.exceptions.toArray(exceptions); 753 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, 754 exceptions); 755 if (mv != null) { 756 accept(mv); 757 } 758 } 759 760 /** 761 * Makes the given method visitor visit this method. 762 * 763 * @param mv 764 * a method visitor. 765 */ 766 public void accept(final MethodVisitor mv) { 767 // visits the method parameters 768 int i, j, n; 769 n = parameters == null ? 0 : parameters.size(); 770 for (i = 0; i < n; i++) { 771 ParameterNode parameter = parameters.get(i); 772 mv.visitParameter(parameter.name, parameter.access); 773 } 774 // visits the method attributes 775 if (annotationDefault != null) { 776 AnnotationVisitor av = mv.visitAnnotationDefault(); 777 AnnotationNode.accept(av, null, annotationDefault); 778 if (av != null) { 779 av.visitEnd(); 780 } 781 } 782 n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); 783 for (i = 0; i < n; ++i) { 784 AnnotationNode an = visibleAnnotations.get(i); 785 an.accept(mv.visitAnnotation(an.desc, true)); 786 } 787 n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); 788 for (i = 0; i < n; ++i) { 789 AnnotationNode an = invisibleAnnotations.get(i); 790 an.accept(mv.visitAnnotation(an.desc, false)); 791 } 792 n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); 793 for (i = 0; i < n; ++i) { 794 TypeAnnotationNode an = visibleTypeAnnotations.get(i); 795 an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 796 true)); 797 } 798 n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations 799 .size(); 800 for (i = 0; i < n; ++i) { 801 TypeAnnotationNode an = invisibleTypeAnnotations.get(i); 802 an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, 803 false)); 804 } 805 n = visibleParameterAnnotations == null ? 0 806 : visibleParameterAnnotations.length; 807 for (i = 0; i < n; ++i) { 808 List<?> l = visibleParameterAnnotations[i]; 809 if (l == null) { 810 continue; 811 } 812 for (j = 0; j < l.size(); ++j) { 813 AnnotationNode an = (AnnotationNode) l.get(j); 814 an.accept(mv.visitParameterAnnotation(i, an.desc, true)); 815 } 816 } 817 n = invisibleParameterAnnotations == null ? 0 818 : invisibleParameterAnnotations.length; 819 for (i = 0; i < n; ++i) { 820 List<?> l = invisibleParameterAnnotations[i]; 821 if (l == null) { 822 continue; 823 } 824 for (j = 0; j < l.size(); ++j) { 825 AnnotationNode an = (AnnotationNode) l.get(j); 826 an.accept(mv.visitParameterAnnotation(i, an.desc, false)); 827 } 828 } 829 if (visited) { 830 instructions.resetLabels(); 831 } 832 n = attrs == null ? 0 : attrs.size(); 833 for (i = 0; i < n; ++i) { 834 mv.visitAttribute(attrs.get(i)); 835 } 836 // visits the method's code 837 if (instructions.size() > 0) { 838 mv.visitCode(); 839 // visits try catch blocks 840 n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); 841 for (i = 0; i < n; ++i) { 842 tryCatchBlocks.get(i).updateIndex(i); 843 tryCatchBlocks.get(i).accept(mv); 844 } 845 // visits instructions 846 instructions.accept(mv); 847 // visits local variables 848 n = localVariables == null ? 0 : localVariables.size(); 849 for (i = 0; i < n; ++i) { 850 localVariables.get(i).accept(mv); 851 } 852 // visits local variable annotations 853 n = visibleLocalVariableAnnotations == null ? 0 854 : visibleLocalVariableAnnotations.size(); 855 for (i = 0; i < n; ++i) { 856 visibleLocalVariableAnnotations.get(i).accept(mv, true); 857 } 858 n = invisibleLocalVariableAnnotations == null ? 0 859 : invisibleLocalVariableAnnotations.size(); 860 for (i = 0; i < n; ++i) { 861 invisibleLocalVariableAnnotations.get(i).accept(mv, false); 862 } 863 // visits maxs 864 mv.visitMaxs(maxStack, maxLocals); 865 visited = true; 866 } 867 mv.visitEnd(); 868 } 869 }