mirror of
https://github.com/2006-Scape/Parabot.git
synced 2026-07-03 00:37:55 +00:00
Moved to Maven
This commit is contained in:
@@ -0,0 +1,809 @@
|
||||
/***
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.objectweb.asm.tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.Attribute;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.TypePath;
|
||||
|
||||
/**
|
||||
* A node that represents a method.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class MethodNode extends MethodVisitor {
|
||||
|
||||
/**
|
||||
* The method's access flags (see {@link Opcodes}). This field also
|
||||
* indicates if the method is synthetic and/or deprecated.
|
||||
*/
|
||||
public int access;
|
||||
|
||||
/**
|
||||
* The method's name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* The method's descriptor (see {@link Type}).
|
||||
*/
|
||||
public String desc;
|
||||
|
||||
/**
|
||||
* The method's signature. May be <tt>null</tt>.
|
||||
*/
|
||||
public String signature;
|
||||
|
||||
/**
|
||||
* The internal names of the method's exception classes (see
|
||||
* {@link Type#getInternalName() getInternalName}). This list is a list of
|
||||
* {@link String} objects.
|
||||
*/
|
||||
public List<String> exceptions;
|
||||
|
||||
/**
|
||||
* The method parameter info (access flags and name)
|
||||
*/
|
||||
public List<ParameterNode> parameters;
|
||||
|
||||
/**
|
||||
* The runtime visible annotations of this method. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.AnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
public List<AnnotationNode> visibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible annotations of this method. This list is a list of
|
||||
* {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.AnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
public List<AnnotationNode> invisibleAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this method. This list is a list
|
||||
* of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label visible
|
||||
*/
|
||||
public List<TypeAnnotationNode> visibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this method. This list is a
|
||||
* list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.TypeAnnotationNode
|
||||
* @label invisible
|
||||
*/
|
||||
public List<TypeAnnotationNode> invisibleTypeAnnotations;
|
||||
|
||||
/**
|
||||
* The non standard attributes of this method. This list is a list of
|
||||
* {@link Attribute} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.Attribute
|
||||
*/
|
||||
public List<Attribute> attrs;
|
||||
|
||||
/**
|
||||
* The default value of this annotation interface method. This field must be
|
||||
* a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
|
||||
* {@link Integer}, {@link Long}, {@link Float}, {@link Double},
|
||||
* {@link String} or {@link Type}, or an two elements String array (for
|
||||
* enumeration values), a {@link AnnotationNode}, or a {@link List} of
|
||||
* values of one of the preceding types. May be <tt>null</tt>.
|
||||
*/
|
||||
public Object annotationDefault;
|
||||
|
||||
/**
|
||||
* The runtime visible parameter annotations of this method. These lists are
|
||||
* lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.AnnotationNode
|
||||
* @label invisible parameters
|
||||
*/
|
||||
public List<AnnotationNode>[] visibleParameterAnnotations;
|
||||
|
||||
/**
|
||||
* The runtime invisible parameter annotations of this method. These lists
|
||||
* are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.AnnotationNode
|
||||
* @label visible parameters
|
||||
*/
|
||||
public List<AnnotationNode>[] invisibleParameterAnnotations;
|
||||
|
||||
/**
|
||||
* The instructions of this method. This list is a list of
|
||||
* {@link AbstractInsnNode} objects.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.AbstractInsnNode
|
||||
* @label instructions
|
||||
*/
|
||||
public InsnList instructions;
|
||||
|
||||
/**
|
||||
* The try catch blocks of this method. This list is a list of
|
||||
* {@link TryCatchBlockNode} objects.
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.TryCatchBlockNode
|
||||
*/
|
||||
public List<TryCatchBlockNode> tryCatchBlocks;
|
||||
|
||||
/**
|
||||
* The maximum stack size of this method.
|
||||
*/
|
||||
public int maxStack;
|
||||
|
||||
/**
|
||||
* The maximum number of local variables of this method.
|
||||
*/
|
||||
public int maxLocals;
|
||||
|
||||
/**
|
||||
* The local variables of this method. This list is a list of
|
||||
* {@link LocalVariableNode} objects. May be <tt>null</tt>
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.LocalVariableNode
|
||||
*/
|
||||
public List<LocalVariableNode> localVariables;
|
||||
|
||||
/**
|
||||
* The visible local variable annotations of this method. This list is a
|
||||
* list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
|
||||
*/
|
||||
public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
|
||||
|
||||
/**
|
||||
* The invisible local variable annotations of this method. This list is a
|
||||
* list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
|
||||
*
|
||||
* @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
|
||||
*/
|
||||
public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
|
||||
|
||||
/**
|
||||
* If the accept method has been called on this object.
|
||||
*/
|
||||
private boolean visited;
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
|
||||
* use this constructor</i>. Instead, they must use the
|
||||
* {@link #MethodNode(int)} version.
|
||||
*/
|
||||
public MethodNode() {
|
||||
this(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized {@link MethodNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
||||
*/
|
||||
public MethodNode(final int api) {
|
||||
super(api);
|
||||
this.instructions = new InsnList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodNode}. <i>Subclasses must not use this
|
||||
* constructor</i>. Instead, they must use the
|
||||
* {@link #MethodNode(int, int, String, String, String, String[])} version.
|
||||
*
|
||||
* @param access
|
||||
* the method's access flags (see {@link Opcodes}). This
|
||||
* parameter also indicates if the method is synthetic and/or
|
||||
* deprecated.
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type}).
|
||||
* @param signature
|
||||
* the method's signature. May be <tt>null</tt>.
|
||||
* @param exceptions
|
||||
* the internal names of the method's exception classes (see
|
||||
* {@link Type#getInternalName() getInternalName}). May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public MethodNode(final int access, final String name, final String desc,
|
||||
final String signature, final String[] exceptions) {
|
||||
this(Opcodes.ASM5, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodNode}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
||||
* @param access
|
||||
* the method's access flags (see {@link Opcodes}). This
|
||||
* parameter also indicates if the method is synthetic and/or
|
||||
* deprecated.
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type}).
|
||||
* @param signature
|
||||
* the method's signature. May be <tt>null</tt>.
|
||||
* @param exceptions
|
||||
* the internal names of the method's exception classes (see
|
||||
* {@link Type#getInternalName() getInternalName}). May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public MethodNode(final int api, final int access, final String name,
|
||||
final String desc, final String signature, final String[] exceptions) {
|
||||
super(api);
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.signature = signature;
|
||||
this.exceptions = new ArrayList<String>(exceptions == null ? 0
|
||||
: exceptions.length);
|
||||
boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
|
||||
if (!isAbstract) {
|
||||
this.localVariables = new ArrayList<LocalVariableNode>(5);
|
||||
}
|
||||
this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
|
||||
if (exceptions != null) {
|
||||
this.exceptions.addAll(Arrays.asList(exceptions));
|
||||
}
|
||||
this.instructions = new InsnList();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Implementation of the MethodVisitor abstract class
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visitParameter(String name, int access) {
|
||||
if (parameters == null) {
|
||||
parameters = new ArrayList<ParameterNode>(5);
|
||||
}
|
||||
parameters.add(new ParameterNode(name, access));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotationDefault() {
|
||||
return new AnnotationNode(new ArrayList<Object>(0) {
|
||||
@Override
|
||||
public boolean add(final Object o) {
|
||||
annotationDefault = o;
|
||||
return super.add(o);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc,
|
||||
final boolean visible) {
|
||||
AnnotationNode an = new AnnotationNode(desc);
|
||||
if (visible) {
|
||||
if (visibleAnnotations == null) {
|
||||
visibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
visibleAnnotations.add(an);
|
||||
} else {
|
||||
if (invisibleAnnotations == null) {
|
||||
invisibleAnnotations = new ArrayList<AnnotationNode>(1);
|
||||
}
|
||||
invisibleAnnotations.add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
|
||||
if (visible) {
|
||||
if (visibleTypeAnnotations == null) {
|
||||
visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
visibleTypeAnnotations.add(an);
|
||||
} else {
|
||||
if (invisibleTypeAnnotations == null) {
|
||||
invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
|
||||
}
|
||||
invisibleTypeAnnotations.add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public AnnotationVisitor visitParameterAnnotation(final int parameter,
|
||||
final String desc, final boolean visible) {
|
||||
AnnotationNode an = new AnnotationNode(desc);
|
||||
if (visible) {
|
||||
if (visibleParameterAnnotations == null) {
|
||||
int params = Type.getArgumentTypes(this.desc).length;
|
||||
visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
|
||||
}
|
||||
if (visibleParameterAnnotations[parameter] == null) {
|
||||
visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
|
||||
1);
|
||||
}
|
||||
visibleParameterAnnotations[parameter].add(an);
|
||||
} else {
|
||||
if (invisibleParameterAnnotations == null) {
|
||||
int params = Type.getArgumentTypes(this.desc).length;
|
||||
invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
|
||||
}
|
||||
if (invisibleParameterAnnotations[parameter] == null) {
|
||||
invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
|
||||
1);
|
||||
}
|
||||
invisibleParameterAnnotations[parameter].add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(final Attribute attr) {
|
||||
if (attrs == null) {
|
||||
attrs = new ArrayList<Attribute>(1);
|
||||
}
|
||||
attrs.add(attr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFrame(final int type, final int nLocal,
|
||||
final Object[] local, final int nStack, final Object[] stack) {
|
||||
instructions.add(new FrameNode(type, nLocal, local == null ? null
|
||||
: getLabelNodes(local), nStack, stack == null ? null
|
||||
: getLabelNodes(stack)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInsn(final int opcode) {
|
||||
instructions.add(new InsnNode(opcode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIntInsn(final int opcode, final int operand) {
|
||||
instructions.add(new IntInsnNode(opcode, operand));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVarInsn(final int opcode, final int var) {
|
||||
instructions.add(new VarInsnNode(opcode, var));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(final int opcode, final String type) {
|
||||
instructions.add(new TypeInsnNode(opcode, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
instructions.add(new FieldInsnNode(opcode, owner, name, desc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner,
|
||||
final String name, final String desc) {
|
||||
instructions.add(new MethodInsnNode(opcode, owner, name, desc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
|
||||
Object... bsmArgs) {
|
||||
instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(final int opcode, final Label label) {
|
||||
instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLabel(final Label label) {
|
||||
instructions.add(getLabelNode(label));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(final Object cst) {
|
||||
instructions.add(new LdcInsnNode(cst));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIincInsn(final int var, final int increment) {
|
||||
instructions.add(new IincInsnNode(var, increment));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTableSwitchInsn(final int min, final int max,
|
||||
final Label dflt, final Label... labels) {
|
||||
instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
|
||||
getLabelNodes(labels)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
|
||||
final Label[] labels) {
|
||||
instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
|
||||
getLabelNodes(labels)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiANewArrayInsn(final String desc, final int dims) {
|
||||
instructions.add(new MultiANewArrayInsnNode(desc, dims));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
// Finds the last real instruction, i.e. the instruction targeted by
|
||||
// this annotation.
|
||||
AbstractInsnNode insn = instructions.getLast();
|
||||
while (insn.getOpcode() == -1) {
|
||||
insn = insn.getPrevious();
|
||||
}
|
||||
// Adds the annotation to this instruction.
|
||||
TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
|
||||
if (visible) {
|
||||
if (insn.visibleTypeAnnotations == null) {
|
||||
insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
insn.visibleTypeAnnotations.add(an);
|
||||
} else {
|
||||
if (insn.invisibleTypeAnnotations == null) {
|
||||
insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
insn.invisibleTypeAnnotations.add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryCatchBlock(final Label start, final Label end,
|
||||
final Label handler, final String type) {
|
||||
tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
|
||||
getLabelNode(end), getLabelNode(handler), type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
||||
TypePath typePath, String desc, boolean visible) {
|
||||
TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
|
||||
TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
|
||||
if (visible) {
|
||||
if (tcb.visibleTypeAnnotations == null) {
|
||||
tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
tcb.visibleTypeAnnotations.add(an);
|
||||
} else {
|
||||
if (tcb.invisibleTypeAnnotations == null) {
|
||||
tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
tcb.invisibleTypeAnnotations.add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(final String name, final String desc,
|
||||
final String signature, final Label start, final Label end,
|
||||
final int index) {
|
||||
localVariables.add(new LocalVariableNode(name, desc, signature,
|
||||
getLabelNode(start), getLabelNode(end), index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||
String desc, boolean visible) {
|
||||
LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
|
||||
typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
|
||||
index, desc);
|
||||
if (visible) {
|
||||
if (visibleLocalVariableAnnotations == null) {
|
||||
visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
visibleLocalVariableAnnotations.add(an);
|
||||
} else {
|
||||
if (invisibleLocalVariableAnnotations == null) {
|
||||
invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
|
||||
1);
|
||||
}
|
||||
invisibleLocalVariableAnnotations.add(an);
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLineNumber(final int line, final Label start) {
|
||||
instructions.add(new LineNumberNode(line, getLabelNode(start)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMaxs(final int maxStack, final int maxLocals) {
|
||||
this.maxStack = maxStack;
|
||||
this.maxLocals = maxLocals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LabelNode corresponding to the given Label. Creates a new
|
||||
* LabelNode if necessary. The default implementation of this method uses
|
||||
* the {@link Label#info} field to store associations between labels and
|
||||
* label nodes.
|
||||
*
|
||||
* @param l
|
||||
* a Label.
|
||||
* @return the LabelNode corresponding to l.
|
||||
*/
|
||||
protected LabelNode getLabelNode(final Label l) {
|
||||
if (!(l.info instanceof LabelNode)) {
|
||||
l.info = new LabelNode();
|
||||
}
|
||||
return (LabelNode) l.info;
|
||||
}
|
||||
|
||||
private LabelNode[] getLabelNodes(final Label[] l) {
|
||||
LabelNode[] nodes = new LabelNode[l.length];
|
||||
for (int i = 0; i < l.length; ++i) {
|
||||
nodes[i] = getLabelNode(l[i]);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private Object[] getLabelNodes(final Object[] objs) {
|
||||
Object[] nodes = new Object[objs.length];
|
||||
for (int i = 0; i < objs.length; ++i) {
|
||||
Object o = objs[i];
|
||||
if (o instanceof Label) {
|
||||
o = getLabelNode((Label) o);
|
||||
}
|
||||
nodes[i] = o;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Accept method
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks that this method node is compatible with the given ASM API
|
||||
* version. This methods checks that this node, and all its nodes
|
||||
* recursively, do not contain elements that were introduced in more recent
|
||||
* versions of the ASM API than the given version.
|
||||
*
|
||||
* @param api
|
||||
* an ASM API version. Must be one of {@link Opcodes#ASM4} or
|
||||
* {@link Opcodes#ASM5}.
|
||||
*/
|
||||
public void check(final int api) {
|
||||
if (api == Opcodes.ASM4) {
|
||||
if (visibleTypeAnnotations != null
|
||||
&& visibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (invisibleTypeAnnotations != null
|
||||
&& invisibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
TryCatchBlockNode tcb = tryCatchBlocks.get(i);
|
||||
if (tcb.visibleTypeAnnotations != null
|
||||
&& tcb.visibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (tcb.invisibleTypeAnnotations != null
|
||||
&& tcb.invisibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < instructions.size(); ++i) {
|
||||
AbstractInsnNode insn = instructions.get(i);
|
||||
if (insn.visibleTypeAnnotations != null
|
||||
&& insn.visibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (insn.invisibleTypeAnnotations != null
|
||||
&& insn.invisibleTypeAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
if (visibleLocalVariableAnnotations != null
|
||||
&& visibleLocalVariableAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (invisibleLocalVariableAnnotations != null
|
||||
&& invisibleLocalVariableAnnotations.size() > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given class visitor visit this method.
|
||||
*
|
||||
* @param cv
|
||||
* a class visitor.
|
||||
*/
|
||||
public void accept(final ClassVisitor cv) {
|
||||
String[] exceptions = new String[this.exceptions.size()];
|
||||
this.exceptions.toArray(exceptions);
|
||||
MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
|
||||
exceptions);
|
||||
if (mv != null) {
|
||||
accept(mv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given method visitor visit this method.
|
||||
*
|
||||
* @param mv
|
||||
* a method visitor.
|
||||
*/
|
||||
public void accept(final MethodVisitor mv) {
|
||||
// visits the method parameters
|
||||
int i, j, n;
|
||||
n = parameters == null ? 0 : parameters.size();
|
||||
for (i = 0; i < n; i++) {
|
||||
ParameterNode parameter = parameters.get(i);
|
||||
mv.visitParameter(parameter.name, parameter.access);
|
||||
}
|
||||
// visits the method attributes
|
||||
if (annotationDefault != null) {
|
||||
AnnotationVisitor av = mv.visitAnnotationDefault();
|
||||
AnnotationNode.accept(av, null, annotationDefault);
|
||||
if (av != null) {
|
||||
av.visitEnd();
|
||||
}
|
||||
}
|
||||
n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = visibleAnnotations.get(i);
|
||||
an.accept(mv.visitAnnotation(an.desc, true));
|
||||
}
|
||||
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
AnnotationNode an = invisibleAnnotations.get(i);
|
||||
an.accept(mv.visitAnnotation(an.desc, false));
|
||||
}
|
||||
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
true));
|
||||
}
|
||||
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
|
||||
.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
|
||||
an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
|
||||
false));
|
||||
}
|
||||
n = visibleParameterAnnotations == null ? 0
|
||||
: visibleParameterAnnotations.length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
List<?> l = visibleParameterAnnotations[i];
|
||||
if (l == null) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < l.size(); ++j) {
|
||||
AnnotationNode an = (AnnotationNode) l.get(j);
|
||||
an.accept(mv.visitParameterAnnotation(i, an.desc, true));
|
||||
}
|
||||
}
|
||||
n = invisibleParameterAnnotations == null ? 0
|
||||
: invisibleParameterAnnotations.length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
List<?> l = invisibleParameterAnnotations[i];
|
||||
if (l == null) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < l.size(); ++j) {
|
||||
AnnotationNode an = (AnnotationNode) l.get(j);
|
||||
an.accept(mv.visitParameterAnnotation(i, an.desc, false));
|
||||
}
|
||||
}
|
||||
if (visited) {
|
||||
instructions.resetLabels();
|
||||
}
|
||||
n = attrs == null ? 0 : attrs.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
mv.visitAttribute(attrs.get(i));
|
||||
}
|
||||
// visits the method's code
|
||||
if (instructions.size() > 0) {
|
||||
mv.visitCode();
|
||||
// visits try catch blocks
|
||||
n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
tryCatchBlocks.get(i).updateIndex(i);
|
||||
tryCatchBlocks.get(i).accept(mv);
|
||||
}
|
||||
// visits instructions
|
||||
instructions.accept(mv);
|
||||
// visits local variables
|
||||
n = localVariables == null ? 0 : localVariables.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
localVariables.get(i).accept(mv);
|
||||
}
|
||||
// visits local variable annotations
|
||||
n = visibleLocalVariableAnnotations == null ? 0
|
||||
: visibleLocalVariableAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
visibleLocalVariableAnnotations.get(i).accept(mv, true);
|
||||
}
|
||||
n = invisibleLocalVariableAnnotations == null ? 0
|
||||
: invisibleLocalVariableAnnotations.size();
|
||||
for (i = 0; i < n; ++i) {
|
||||
invisibleLocalVariableAnnotations.get(i).accept(mv, false);
|
||||
}
|
||||
// visits maxs
|
||||
mv.visitMaxs(maxStack, maxLocals);
|
||||
visited = true;
|
||||
}
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user