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