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