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