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