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 }