1/***
2 * ASM: a very small and fast Java bytecode manipulation framework
3 * Copyright (c) 2000-2005 INRIA, France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.objectweb.asm.tree;
31
32import java.util.ArrayList;
33import java.util.Arrays;
34import java.util.List;
35
36import org.objectweb.asm.AnnotationVisitor;
37import org.objectweb.asm.Attribute;
38import org.objectweb.asm.ClassVisitor;
39import org.objectweb.asm.Handle;
40import org.objectweb.asm.TypeAnnotationVisitor;
41import org.objectweb.asm.Label;
42import org.objectweb.asm.MethodVisitor;
43import org.objectweb.asm.Opcodes;
44import org.objectweb.asm.Type;
45import org.objectweb.asm.TypePath;
46
47/**
48 * A node that represents a method.
49 *
50 * @author Eric Bruneton
51 */
52public class MethodNode extends MemberNode implements MethodVisitor {
53
54    // jaime
55    public TypeAnnotationVisitor visitTypeAnnotation(String desc,
56        boolean visible,
57        boolean inCode)
58    {
59        return null;
60    }
61    //end jaime
62
63    /**
64     * The method's access flags (see {@link Opcodes}). This field also
65     * indicates if the method is synthetic and/or deprecated.
66     */
67    public int access;
68
69    /**
70     * The method's name.
71     */
72    public String name;
73
74    /**
75     * The method's descriptor (see {@link Type}).
76     */
77    public String desc;
78
79    /**
80     * The method's signature. May be <tt>null</tt>.
81     */
82    public String signature;
83
84    /**
85     * The internal names of the method's exception classes (see
86     * {@link Type#getInternalName() getInternalName}). This list is a list of
87     * {@link String} objects.
88     */
89    public List exceptions;
90
91    /**
92     * The default value of this annotation interface method. This field must be
93     * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
94     * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
95     * {@link String} or {@link Type}, or an two elements String array (for
96     * enumeration values), a {@link AnnotationNode}, or a {@link List} of
97     * values of one of the preceding types. May be <tt>null</tt>.
98     */
99    public Object annotationDefault;
100
101    /**
102     * The runtime visible parameter annotations of this method. These lists are
103     * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
104     *
105     * @associates org.objectweb.asm.tree.AnnotationNode
106     * @label invisible parameters
107     */
108    public List[] visibleParameterAnnotations;
109
110    /**
111     * The runtime invisible parameter annotations of this method. These lists
112     * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
113     *
114     * @associates org.objectweb.asm.tree.AnnotationNode
115     * @label visible parameters
116     */
117    public List[] invisibleParameterAnnotations;
118
119    /**
120     * The instructions of this method. This list is a list of
121     * {@link AbstractInsnNode} objects.
122     *
123     * @associates org.objectweb.asm.tree.AbstractInsnNode
124     * @label instructions
125     */
126    public List instructions;
127
128    /**
129     * The try catch blocks of this method. This list is a list of
130     * {@link TryCatchBlockNode} objects.
131     *
132     * @associates org.objectweb.asm.tree.TryCatchBlockNode
133     */
134    public List tryCatchBlocks;
135
136    /**
137     * The maximum stack size of this method.
138     */
139    public int maxStack;
140
141    /**
142     * The maximum number of local variables of this method.
143     */
144    public int maxLocals;
145
146    /**
147     * The local variables of this method. This list is a list of
148     * {@link LocalVariableNode} objects. May be <tt>null</tt>
149     *
150     * @associates org.objectweb.asm.tree.LocalVariableNode
151     */
152    public List localVariables;
153
154    /**
155     * The line numbers of this method. This list is a list of
156     * {@link LineNumberNode} objects. May be <tt>null</tt>
157     *
158     * @associates org.objectweb.asm.tree.LineNumberNode
159     */
160    public List lineNumbers;
161
162    /**
163     * Constructs a new {@link MethodNode}.
164     *
165     * @param access the method's access flags (see {@link Opcodes}). This
166     *        parameter also indicates if the method is synthetic and/or
167     *        deprecated.
168     * @param name the method's name.
169     * @param desc the method's descriptor (see {@link Type}).
170     * @param signature the method's signature. May be <tt>null</tt>.
171     * @param exceptions the internal names of the method's exception classes
172     *        (see {@link Type#getInternalName() getInternalName}). May be
173     *        <tt>null</tt>.
174     */
175    public MethodNode(
176        final int access,
177        final String name,
178        final String desc,
179        final String signature,
180        final String[] exceptions)
181    {
182        this.access = access;
183        this.name = name;
184        this.desc = desc;
185        this.signature = signature;
186        this.exceptions = new ArrayList(exceptions == null
187                ? 0
188                : exceptions.length);
189        boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
190        this.instructions = new ArrayList(isAbstract ? 0 : 24);
191        if (!isAbstract) {
192            this.localVariables = new ArrayList(5);
193            this.lineNumbers = new ArrayList(5);
194        }
195        this.tryCatchBlocks = new ArrayList();
196        if (exceptions != null) {
197            this.exceptions.addAll(Arrays.asList(exceptions));
198        }
199    }
200
201    // ------------------------------------------------------------------------
202    // Implementation of the MethodVisitor interface
203    // ------------------------------------------------------------------------
204
205    public AnnotationVisitor visitAnnotationDefault() {
206        return new AnnotationNode(new ArrayList(0) {
207            public boolean add(Object o) {
208                annotationDefault = o;
209                return super.add(o);
210            }
211        });
212    }
213
214    public AnnotationVisitor visitParameterAnnotation(
215        final int parameter,
216        final String desc,
217        final boolean visible)
218    {
219        AnnotationNode an = new AnnotationNode(desc);
220        if (visible) {
221            if (visibleParameterAnnotations == null) {
222                int params = Type.getArgumentTypes(this.desc).length;
223                visibleParameterAnnotations = new List[params];
224            }
225            if (visibleParameterAnnotations[parameter] == null) {
226                visibleParameterAnnotations[parameter] = new ArrayList(1);
227            }
228            visibleParameterAnnotations[parameter].add(an);
229        } else {
230            if (invisibleParameterAnnotations == null) {
231                int params = Type.getArgumentTypes(this.desc).length;
232                invisibleParameterAnnotations = new List[params];
233            }
234            if (invisibleParameterAnnotations[parameter] == null) {
235                invisibleParameterAnnotations[parameter] = new ArrayList(1);
236            }
237            invisibleParameterAnnotations[parameter].add(an);
238        }
239        return an;
240    }
241
242    public void visitCode() {
243    }
244
245    public void visitInsn(final int opcode) {
246        instructions.add(new InsnNode(opcode));
247    }
248
249    public void visitIntInsn(final int opcode, final int operand) {
250        instructions.add(new IntInsnNode(opcode, operand));
251    }
252
253    public void visitVarInsn(final int opcode, final int var) {
254        instructions.add(new VarInsnNode(opcode, var));
255    }
256
257    public void visitTypeInsn(final int opcode, final String desc) {
258        instructions.add(new TypeInsnNode(opcode, desc));
259    }
260
261    public void visitFieldInsn(
262        final int opcode,
263        final String owner,
264        final String name,
265        final String desc)
266    {
267        instructions.add(new FieldInsnNode(opcode, owner, name, desc));
268    }
269
270    public void visitMethodInsn(
271        final int opcode,
272        final String owner,
273        final String name,
274        final String desc)
275    {
276        instructions.add(new MethodInsnNode(opcode, owner, name, desc));
277    }
278
279    @Override
280    public void visitInvokeDynamicInsn(
281        String name,
282        String desc,
283        Handle bsm,
284        Object... bsmArgs)
285    {
286        instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
287    }
288
289    public void visitJumpInsn(final int opcode, final Label label) {
290        instructions.add(new JumpInsnNode(opcode, label));
291    }
292
293    public void visitLabel(final Label label) {
294        instructions.add(new LabelNode(label));
295    }
296
297    public void visitLdcInsn(final Object cst) {
298        instructions.add(new LdcInsnNode(cst));
299    }
300
301    public void visitIincInsn(final int var, final int increment) {
302        instructions.add(new IincInsnNode(var, increment));
303    }
304
305    public void visitTableSwitchInsn(
306        final int min,
307        final int max,
308        final Label dflt,
309        final Label[] labels)
310    {
311        instructions.add(new TableSwitchInsnNode(min, max, dflt, labels));
312    }
313
314    public void visitLookupSwitchInsn(
315        final Label dflt,
316        final int[] keys,
317        final Label[] labels)
318    {
319        instructions.add(new LookupSwitchInsnNode(dflt, keys, labels));
320    }
321
322    public void visitMultiANewArrayInsn(final String desc, final int dims) {
323        instructions.add(new MultiANewArrayInsnNode(desc, dims));
324    }
325
326    public void visitTryCatchBlock(
327        final Label start,
328        final Label end,
329        final Label handler,
330        final String type)
331    {
332        tryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, type));
333    }
334
335    public void visitLocalVariable(
336        final String name,
337        final String desc,
338        final String signature,
339        final Label start,
340        final Label end,
341        final int index)
342    {
343        localVariables.add(new LocalVariableNode(name,
344                desc,
345                signature,
346                start,
347                end,
348                index));
349    }
350
351    public void visitLineNumber(final int line, final Label start) {
352        lineNumbers.add(new LineNumberNode(line, start));
353    }
354
355    public void visitMaxs(final int maxStack, final int maxLocals) {
356        this.maxStack = maxStack;
357        this.maxLocals = maxLocals;
358    }
359
360    // ------------------------------------------------------------------------
361    // Accept method
362    // ------------------------------------------------------------------------
363
364    /**
365     * Makes the given class visitor visit this method.
366     *
367     * @param cv a class visitor.
368     */
369    public void accept(final ClassVisitor cv) {
370        String[] exceptions = new String[this.exceptions.size()];
371        this.exceptions.toArray(exceptions);
372        MethodVisitor mv = cv.visitMethod(access,
373                name,
374                desc,
375                signature,
376                exceptions);
377        if (mv != null) {
378            accept(mv);
379        }
380    }
381
382    /**
383     * Makes the given method visitor visit this method.
384     *
385     * @param mv a method visitor.
386     */
387    public void accept(final MethodVisitor mv) {
388        // visits the method attributes
389        int i, j, n;
390        if (annotationDefault != null) {
391            AnnotationVisitor av = mv.visitAnnotationDefault();
392            AnnotationNode.accept(av, null, annotationDefault);
393            av.visitEnd();
394        }
395        n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
396        for (i = 0; i < n; ++i) {
397            AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
398            an.accept(mv.visitAnnotation(an.desc, true));
399        }
400        n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
401        for (i = 0; i < n; ++i) {
402            AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
403            an.accept(mv.visitAnnotation(an.desc, false));
404        }
405        n = visibleParameterAnnotations == null
406                ? 0
407                : visibleParameterAnnotations.length;
408        for (i = 0; i < n; ++i) {
409            List l = visibleParameterAnnotations[i];
410            if (l == null) {
411                continue;
412            }
413            for (j = 0; j < l.size(); ++j) {
414                AnnotationNode an = (AnnotationNode) l.get(j);
415                an.accept(mv.visitParameterAnnotation(i, an.desc, true));
416            }
417        }
418        n = invisibleParameterAnnotations == null
419                ? 0
420                : invisibleParameterAnnotations.length;
421        for (i = 0; i < n; ++i) {
422            List l = invisibleParameterAnnotations[i];
423            if (l == null) {
424                continue;
425            }
426            for (j = 0; j < l.size(); ++j) {
427                AnnotationNode an = (AnnotationNode) l.get(j);
428                an.accept(mv.visitParameterAnnotation(i, an.desc, false));
429            }
430        }
431        n = attrs == null ? 0 : attrs.size();
432        for (i = 0; i < n; ++i) {
433            mv.visitAttribute((Attribute) attrs.get(i));
434        }
435        // visits the method's code
436        if (instructions.size() > 0) {
437            mv.visitCode();
438            // visits try catch blocks
439            for (i = 0; i < tryCatchBlocks.size(); ++i) {
440                ((TryCatchBlockNode) tryCatchBlocks.get(i)).accept(mv);
441            }
442            // visits instructions
443            for (i = 0; i < instructions.size(); ++i) {
444                ((AbstractInsnNode) instructions.get(i)).accept(mv);
445            }
446            // visits local variables
447            n = localVariables == null ? 0 : localVariables.size();
448            for (i = 0; i < n; ++i) {
449                ((LocalVariableNode) localVariables.get(i)).accept(mv);
450            }
451            // visits line numbers
452            n = lineNumbers == null ? 0 : lineNumbers.size();
453            for (i = 0; i < n; ++i) {
454                ((LineNumberNode) lineNumbers.get(i)).accept(mv);
455            }
456            // visits maxs
457            mv.visitMaxs(maxStack, maxLocals);
458        }
459        mv.visitEnd();
460    }
461
462    @Override
463    public AnnotationVisitor visitInsnAnnotation(int typeRef,
464        TypePath typePath, String desc, boolean visible) {
465      // TODO Auto-generated method stub
466      return null;
467    }
468}
469