Updated ASM library (ASM 5)

This commit is contained in:
Clisprail
2014-01-26 00:15:10 +01:00
parent 677b0d4bd1
commit e8729cf8b0
53 changed files with 2740 additions and 413 deletions
@@ -29,6 +29,7 @@
*/
package org.objectweb.asm.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -127,6 +128,28 @@ public abstract class AbstractInsnNode {
*/
protected int opcode;
/**
* The runtime visible type annotations of this instruction. This field is
* only used for real instructions (i.e. not for labels, frames, or line
* number nodes). 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 instruction. This field is
* only used for real instructions (i.e. not for labels, frames, or line
* number nodes). 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;
/**
* Previous instruction in the list to which this instruction belongs.
*/
@@ -146,7 +169,7 @@ public abstract class AbstractInsnNode {
int index;
/**
* Constructs a new {@link org.objectweb.asm.tree.AbstractInsnNode}.
* Constructs a new {@link AbstractInsnNode}.
*
* @param opcode
* the opcode of the instruction to be constructed.
@@ -203,6 +226,29 @@ public abstract class AbstractInsnNode {
*/
public abstract void accept(final MethodVisitor cv);
/**
* Makes the given visitor visit the annotations of this instruction.
*
* @param mv
* a method visitor.
*/
protected final void acceptAnnotations(final MethodVisitor mv) {
int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
.size();
for (int i = 0; i < n; ++i) {
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
true));
}
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
.size();
for (int i = 0; i < n; ++i) {
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
false));
}
}
/**
* Returns a copy of this instruction.
*
@@ -245,4 +291,36 @@ public abstract class AbstractInsnNode {
}
return clones;
}
/**
* Clones the annotations of the given instruction into this instruction.
*
* @param insn
* the source instruction.
* @return this instruction.
*/
protected final AbstractInsnNode cloneAnnotations(
final AbstractInsnNode insn) {
if (insn.visibleTypeAnnotations != null) {
this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
src.typePath, src.desc);
src.accept(ann);
this.visibleTypeAnnotations.add(ann);
}
}
if (insn.invisibleTypeAnnotations != null) {
this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
src.typePath, src.desc);
src.accept(ann);
this.invisibleTypeAnnotations.add(ann);
}
}
return this;
}
}
@@ -54,14 +54,14 @@ public class AnnotationNode extends AnnotationVisitor {
* {@link Short}, {@link Integer}, {@link Long}, {@link Float},
* {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an
* two elements String array (for enumeration values), a
* {@link org.objectweb.asm.tree.AnnotationNode}, or a {@link java.util.List} of values of one of the
* {@link AnnotationNode}, or a {@link List} of values of one of the
* preceding types. The list may be <tt>null</tt> if there is no name value
* pair.
*/
public List<Object> values;
/**
* Constructs a new {@link org.objectweb.asm.tree.AnnotationNode}. <i>Subclasses must not use this
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #AnnotationNode(int, String)} version.
*
@@ -69,15 +69,15 @@ public class AnnotationNode extends AnnotationVisitor {
* the class descriptor of the annotation class.
*/
public AnnotationNode(final String desc) {
this(Opcodes.ASM4, desc);
this(Opcodes.ASM5, desc);
}
/**
* Constructs a new {@link org.objectweb.asm.tree.AnnotationNode}.
* Constructs a new {@link AnnotationNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link org.objectweb.asm.Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param desc
* the class descriptor of the annotation class.
*/
@@ -87,13 +87,13 @@ public class AnnotationNode extends AnnotationVisitor {
}
/**
* Constructs a new {@link org.objectweb.asm.tree.AnnotationNode} to visit an array value.
* Constructs a new {@link AnnotationNode} to visit an array value.
*
* @param values
* where the visited values must be stored.
*/
AnnotationNode(final List<Object> values) {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
this.values = values;
}
@@ -166,7 +166,8 @@ public class AnnotationNode extends AnnotationVisitor {
* versions of the ASM API than the given version.
*
* @param api
* an ASM API version. Must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
* an ASM API version. Must be one of {@link Opcodes#ASM4} or
* {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
@@ -39,6 +39,7 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
/**
* A node that represents a class.
@@ -116,7 +117,7 @@ public class ClassNode extends ClassVisitor {
/**
* The runtime visible annotations of this class. This list is a list of
* {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
@@ -125,16 +126,34 @@ public class ClassNode extends ClassVisitor {
/**
* The runtime invisible annotations of this class. This list is a list of
* {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@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 class. 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 class. 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 class. This list is a list of
* {@link org.objectweb.asm.Attribute} objects. May be <tt>null</tt>.
* {@link Attribute} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.Attribute
*/
@@ -165,20 +184,20 @@ public class ClassNode extends ClassVisitor {
public List<MethodNode> methods;
/**
* Constructs a new {@link org.objectweb.asm.tree.ClassNode}. <i>Subclasses must not use this
* Constructs a new {@link ClassNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #ClassNode(int)}
* version.
*/
public ClassNode() {
this(Opcodes.ASM4);
this(Opcodes.ASM5);
}
/**
* Constructs a new {@link org.objectweb.asm.tree.ClassNode}.
* Constructs a new {@link ClassNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link org.objectweb.asm.Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassNode(final int api) {
super(api);
@@ -238,6 +257,24 @@ public class ClassNode extends ClassVisitor {
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;
}
@Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
@@ -286,10 +323,26 @@ public class ClassNode extends ClassVisitor {
* API than the given version.
*
* @param api
* an ASM API version. Must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
* an ASM API version. Must be one of {@link Opcodes#ASM4} or
* {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
if (api == Opcodes.ASM4) {
if (visibleTypeAnnotations != null
&& visibleTypeAnnotations.size() > 0) {
throw new RuntimeException();
}
if (invisibleTypeAnnotations != null
&& invisibleTypeAnnotations.size() > 0) {
throw new RuntimeException();
}
for (FieldNode f : fields) {
f.check(api);
}
for (MethodNode m : methods) {
m.check(api);
}
}
}
/**
@@ -323,6 +376,19 @@ public class ClassNode extends ClassVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(cv.visitAnnotation(an.desc, false));
}
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
for (i = 0; i < n; ++i) {
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
an.accept(cv.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(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
false));
}
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
cv.visitAttribute(attrs.get(i));
@@ -58,7 +58,7 @@ public class FieldInsnNode extends AbstractInsnNode {
public String desc;
/**
* Constructs a new {@link org.objectweb.asm.tree.FieldInsnNode}.
* Constructs a new {@link FieldInsnNode}.
*
* @param opcode
* the opcode of the type instruction to be constructed. This
@@ -97,12 +97,14 @@ public class FieldInsnNode extends AbstractInsnNode {
}
@Override
public void accept(final MethodVisitor cv) {
cv.visitFieldInsn(opcode, owner, name, desc);
public void accept(final MethodVisitor mv) {
mv.visitFieldInsn(opcode, owner, name, desc);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new FieldInsnNode(opcode, owner, name, desc);
return new FieldInsnNode(opcode, owner, name, desc)
.cloneAnnotations(this);
}
}
@@ -37,6 +37,7 @@ import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
/**
* A node that represents a field.
@@ -75,7 +76,7 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime visible annotations of this field. This list is a list of
* {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
@@ -84,23 +85,41 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime invisible annotations of this field. This list is a list of
* {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@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 field. 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 field. 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 field. This list is a list of
* {@link org.objectweb.asm.Attribute} objects. May be <tt>null</tt>.
* {@link Attribute} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
/**
* Constructs a new {@link org.objectweb.asm.tree.FieldNode}. <i>Subclasses must not use this
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #FieldNode(int, int, String, String, String, Object)} version.
*
@@ -123,17 +142,17 @@ public class FieldNode extends FieldVisitor {
*/
public FieldNode(final int access, final String name, final String desc,
final String signature, final Object value) {
this(Opcodes.ASM4, access, name, desc, signature, value);
this(Opcodes.ASM5, access, name, desc, signature, value);
}
/**
* Constructs a new {@link org.objectweb.asm.tree.FieldNode}. <i>Subclasses must not use this
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #FieldNode(int, int, String, String, String, Object)} version.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link org.objectweb.asm.Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param access
* the field's access flags (see
* {@link org.objectweb.asm.Opcodes}). This parameter also
@@ -183,6 +202,24 @@ public class FieldNode extends FieldVisitor {
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;
}
@Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
@@ -206,10 +243,20 @@ public class FieldNode extends FieldVisitor {
* API than the given version.
*
* @param api
* an ASM API version. Must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
* an ASM API version. Must be one of {@link Opcodes#ASM4} or
* {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
if (api == Opcodes.ASM4) {
if (visibleTypeAnnotations != null
&& visibleTypeAnnotations.size() > 0) {
throw new RuntimeException();
}
if (invisibleTypeAnnotations != null
&& invisibleTypeAnnotations.size() > 0) {
throw new RuntimeException();
}
}
}
/**
@@ -234,6 +281,19 @@ public class FieldNode extends FieldVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(fv.visitAnnotation(an.desc, false));
}
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
for (i = 0; i < n; ++i) {
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
an.accept(fv.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(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
false));
}
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
fv.visitAttribute(attrs.get(i));
@@ -47,17 +47,17 @@ import org.objectweb.asm.Opcodes;
* of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
* <br>
* (*) this is mandatory only for classes whose version is greater than or equal
* to {@link org.objectweb.asm.Opcodes#V1_6 V1_6}.
* to {@link Opcodes#V1_6 V1_6}.
*
* @author Eric Bruneton
*/
public class FrameNode extends AbstractInsnNode {
/**
* The type of this frame. Must be {@link org.objectweb.asm.Opcodes#F_NEW} for expanded
* frames, or {@link org.objectweb.asm.Opcodes#F_FULL}, {@link org.objectweb.asm.Opcodes#F_APPEND},
* {@link org.objectweb.asm.Opcodes#F_CHOP}, {@link org.objectweb.asm.Opcodes#F_SAME} or
* {@link org.objectweb.asm.Opcodes#F_APPEND}, {@link org.objectweb.asm.Opcodes#F_SAME1} for compressed frames.
* The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
* frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
* {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
* {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
*/
public int type;
@@ -65,7 +65,7 @@ public class FrameNode extends AbstractInsnNode {
* The types of the local variables of this stack map frame. Elements of
* this list can be Integer, String or LabelNode objects (for primitive,
* reference and uninitialized types respectively - see
* {@link org.objectweb.asm.MethodVisitor}).
* {@link MethodVisitor}).
*/
public List<Object> local;
@@ -73,7 +73,7 @@ public class FrameNode extends AbstractInsnNode {
* The types of the operand stack elements of this stack map frame. Elements
* of this list can be Integer, String or LabelNode objects (for primitive,
* reference and uninitialized types respectively - see
* {@link org.objectweb.asm.MethodVisitor}).
* {@link MethodVisitor}).
*/
public List<Object> stack;
@@ -82,28 +82,28 @@ public class FrameNode extends AbstractInsnNode {
}
/**
* Constructs a new {@link org.objectweb.asm.tree.FrameNode}.
* Constructs a new {@link FrameNode}.
*
* @param type
* the type of this frame. Must be {@link org.objectweb.asm.Opcodes#F_NEW} for
* expanded frames, or {@link org.objectweb.asm.Opcodes#F_FULL},
* {@link org.objectweb.asm.Opcodes#F_APPEND}, {@link org.objectweb.asm.Opcodes#F_CHOP},
* {@link org.objectweb.asm.Opcodes#F_SAME} or {@link org.objectweb.asm.Opcodes#F_APPEND},
* {@link org.objectweb.asm.Opcodes#F_SAME1} for compressed frames.
* the type of this frame. Must be {@link Opcodes#F_NEW} for
* expanded frames, or {@link Opcodes#F_FULL},
* {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
* {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
* {@link Opcodes#F_SAME1} for compressed frames.
* @param nLocal
* number of local variables of this stack map frame.
* @param local
* the types of the local variables of this stack map frame.
* Elements of this list can be Integer, String or LabelNode
* objects (for primitive, reference and uninitialized types
* respectively - see {@link org.objectweb.asm.MethodVisitor}).
* respectively - see {@link MethodVisitor}).
* @param nStack
* number of operand stack elements of this stack map frame.
* @param stack
* the types of the operand stack elements of this stack map
* frame. Elements of this list can be Integer, String or
* LabelNode objects (for primitive, reference and uninitialized
* types respectively - see {@link org.objectweb.asm.MethodVisitor}).
* types respectively - see {@link MethodVisitor}).
*/
public FrameNode(final int type, final int nLocal, final Object[] local,
final int nStack, final Object[] stack) {
@@ -52,7 +52,7 @@ public class IincInsnNode extends AbstractInsnNode {
public int incr;
/**
* Constructs a new {@link org.objectweb.asm.tree.IincInsnNode}.
* Constructs a new {@link IincInsnNode}.
*
* @param var
* index of the local variable to be incremented.
@@ -73,10 +73,11 @@ public class IincInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIincInsn(var, incr);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new IincInsnNode(var, incr);
return new IincInsnNode(var, incr).cloneAnnotations(this);
}
}
@@ -64,7 +64,7 @@ public class InnerClassNode {
public int access;
/**
* Constructs a new {@link org.objectweb.asm.tree.InnerClassNode}.
* Constructs a new {@link InnerClassNode}.
*
* @param name
* the internal name of an inner class (see
@@ -35,7 +35,7 @@ import java.util.NoSuchElementException;
import org.objectweb.asm.MethodVisitor;
/**
* A doubly linked list of {@link org.objectweb.asm.tree.AbstractInsnNode} objects. <i>This
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This
* implementation is not thread safe</i>.
*/
public class InsnList {
@@ -100,7 +100,7 @@ public class InsnList {
* the index of the instruction that must be returned.
* @return the instruction whose index is given.
* @throws IndexOutOfBoundsException
* if (index < 0 || index >= size()).
* if (index &lt; 0 || index &gt;= size()).
*/
public AbstractInsnNode get(final int index) {
if (index < 0 || index >= size) {
@@ -207,7 +207,7 @@ public class InsnList {
* an instruction <i>of this list</i>.
* @param insn
* another instruction, <i>which must not belong to any
* {@link org.objectweb.asm.tree.InsnList}</i>.
* {@link InsnList}</i>.
*/
public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
AbstractInsnNode next = location.next;
@@ -241,7 +241,7 @@ public class InsnList {
*
* @param insn
* an instruction, <i>which must not belong to any
* {@link org.objectweb.asm.tree.InsnList}</i>.
* {@link InsnList}</i>.
*/
public void add(final AbstractInsnNode insn) {
++size;
@@ -287,7 +287,7 @@ public class InsnList {
*
* @param insn
* an instruction, <i>which must not belong to any
* {@link org.objectweb.asm.tree.InsnList}</i>.
* {@link InsnList}</i>.
*/
public void insert(final AbstractInsnNode insn) {
++size;
@@ -336,7 +336,7 @@ public class InsnList {
* inserted.
* @param insn
* the instruction to be inserted, <i>which must not belong to
* any {@link org.objectweb.asm.tree.InsnList}</i>.
* any {@link InsnList}</i>.
*/
public void insert(final AbstractInsnNode location,
final AbstractInsnNode insn) {
@@ -392,7 +392,7 @@ public class InsnList {
* inserted.
* @param insn
* the instruction to be inserted, <i>which must not belong to
* any {@link org.objectweb.asm.tree.InsnList}</i>.
* any {@link InsnList}</i>.
*/
public void insertBefore(final AbstractInsnNode location,
final AbstractInsnNode insn) {
@@ -479,7 +479,7 @@ public class InsnList {
*
* @param mark
* if the instructions must be marked as no longer belonging to
* any {@link org.objectweb.asm.tree.InsnList}.
* any {@link InsnList}.
*/
void removeAll(final boolean mark) {
if (mark) {
@@ -41,7 +41,7 @@ import org.objectweb.asm.MethodVisitor;
public class InsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link org.objectweb.asm.tree.InsnNode}.
* Constructs a new {@link InsnNode}.
*
* @param opcode
* the opcode of the instruction to be constructed. This opcode
@@ -78,10 +78,11 @@ public class InsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitInsn(opcode);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new InsnNode(opcode);
return new InsnNode(opcode).cloneAnnotations(this);
}
}
@@ -46,7 +46,7 @@ public class IntInsnNode extends AbstractInsnNode {
public int operand;
/**
* Constructs a new {@link org.objectweb.asm.tree.IntInsnNode}.
* Constructs a new {@link IntInsnNode}.
*
* @param opcode
* the opcode of the instruction to be constructed. This opcode
@@ -78,10 +78,11 @@ public class IntInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIntInsn(opcode, operand);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new IntInsnNode(opcode, operand);
return new IntInsnNode(opcode, operand).cloneAnnotations(this);
}
}
@@ -63,7 +63,7 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
public Object[] bsmArgs;
/**
* Constructs a new {@link org.objectweb.asm.tree.InvokeDynamicInsnNode}.
* Constructs a new {@link InvokeDynamicInsnNode}.
*
* @param name
* invokedynamic name.
@@ -91,10 +91,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
.cloneAnnotations(this);
}
}
@@ -48,7 +48,7 @@ public class JumpInsnNode extends AbstractInsnNode {
public LabelNode label;
/**
* Constructs a new {@link org.objectweb.asm.tree.JumpInsnNode}.
* Constructs a new {@link JumpInsnNode}.
*
* @param opcode
* the opcode of the type instruction to be constructed. This
@@ -86,10 +86,12 @@ public class JumpInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitJumpInsn(opcode, label.getLabel());
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new JumpInsnNode(opcode, clone(label, labels));
return new JumpInsnNode(opcode, clone(label, labels))
.cloneAnnotations(this);
}
}
@@ -35,7 +35,7 @@ import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
/**
* An {@link org.objectweb.asm.tree.AbstractInsnNode} that encapsulates a {@link org.objectweb.asm.Label}.
* An {@link AbstractInsnNode} that encapsulates a {@link Label}.
*/
public class LabelNode extends AbstractInsnNode {
@@ -49,7 +49,7 @@ public class LdcInsnNode extends AbstractInsnNode {
public Object cst;
/**
* Constructs a new {@link org.objectweb.asm.tree.LdcInsnNode}.
* Constructs a new {@link LdcInsnNode}.
*
* @param cst
* the constant to be loaded on the stack. This parameter must be
@@ -69,10 +69,11 @@ public class LdcInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitLdcInsn(cst);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new LdcInsnNode(cst);
return new LdcInsnNode(cst).cloneAnnotations(this);
}
}
@@ -53,7 +53,7 @@ public class LineNumberNode extends AbstractInsnNode {
public LabelNode start;
/**
* Constructs a new {@link org.objectweb.asm.tree.LineNumberNode}.
* Constructs a new {@link LineNumberNode}.
*
* @param line
* a line number. This number refers to the source file from
@@ -0,0 +1,157 @@
/***
* 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.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference;
/**
* A node that represents a type annotation on a local or resource variable.
*
* @author Eric Bruneton
*/
public class LocalVariableAnnotationNode extends TypeAnnotationNode {
/**
* The fist instructions corresponding to the continuous ranges that make
* the scope of this local variable (inclusive). Must not be <tt>null</tt>.
*/
public List<LabelNode> start;
/**
* The last instructions corresponding to the continuous ranges that make
* the scope of this local variable (exclusive). This list must have the
* same size as the 'start' list. Must not be <tt>null</tt>.
*/
public List<LabelNode> end;
/**
* The local variable's index in each range. This list must have the same
* size as the 'start' list. Must not be <tt>null</tt>.
*/
public List<Integer> index;
/**
* Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
* not use this constructor</i>. Instead, they must use the
* {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)}
* version.
*
* @param typeRef
* a reference to the annotated type. See {@link TypeReference}.
* @param typePath
* the path to the annotated type argument, wildcard bound, array
* element type, or static inner type within 'typeRef'. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
* @param start
* the fist instructions corresponding to the continuous ranges
* that make the scope of this local variable (inclusive).
* @param end
* the last instructions corresponding to the continuous ranges
* that make the scope of this local variable (exclusive). This
* array must have the same size as the 'start' array.
* @param index
* the local variable's index in each range. This array must have
* the same size as the 'start' array.
* @param desc
* the class descriptor of the annotation class.
*/
public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
LabelNode[] start, LabelNode[] end, int[] index, String desc) {
this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc);
}
/**
* Constructs a new {@link LocalVariableAnnotationNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param typeRef
* a reference to the annotated type. See {@link TypeReference}.
* @param start
* the fist instructions corresponding to the continuous ranges
* that make the scope of this local variable (inclusive).
* @param end
* the last instructions corresponding to the continuous ranges
* that make the scope of this local variable (exclusive). This
* array must have the same size as the 'start' array.
* @param index
* the local variable's index in each range. This array must have
* the same size as the 'start' array.
* @param typePath
* the path to the annotated type argument, wildcard bound, array
* element type, or static inner type within 'typeRef'. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
* @param desc
* the class descriptor of the annotation class.
*/
public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
LabelNode[] start, LabelNode[] end, int[] index, String desc) {
super(api, typeRef, typePath, desc);
this.start = new ArrayList<LabelNode>(start.length);
this.start.addAll(Arrays.asList(start));
this.end = new ArrayList<LabelNode>(end.length);
this.end.addAll(Arrays.asList(end));
this.index = new ArrayList<Integer>(index.length);
for (int i : index) {
this.index.add(i);
}
}
/**
* Makes the given visitor visit this type annotation.
*
* @param mv
* the visitor that must visit this annotation.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
*/
public void accept(final MethodVisitor mv, boolean visible) {
Label[] start = new Label[this.start.size()];
Label[] end = new Label[this.end.size()];
int[] index = new int[this.index.size()];
for (int i = 0; i < start.length; ++i) {
start[i] = this.start.get(i).getLabel();
end[i] = this.end.get(i).getLabel();
index[i] = this.index.get(i);
}
accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
index, desc, true));
}
}
@@ -71,7 +71,7 @@ public class LocalVariableNode {
public int index;
/**
* Constructs a new {@link org.objectweb.asm.tree.LocalVariableNode}.
* Constructs a new {@link LocalVariableNode}.
*
* @param name
* the name of a local variable.
@@ -57,12 +57,12 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
/**
* Beginnings of the handler blocks. This list is a list of
* {@link org.objectweb.asm.tree.LabelNode} objects.
* {@link LabelNode} objects.
*/
public List<LabelNode> labels;
/**
* Constructs a new {@link org.objectweb.asm.tree.LookupSwitchInsnNode}.
* Constructs a new {@link LookupSwitchInsnNode}.
*
* @param dflt
* beginning of the default handler block.
@@ -105,6 +105,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
acceptAnnotations(mv);
}
@Override
@@ -112,6 +113,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
labels), null, clone(this.labels, labels));
clone.keys.addAll(keys);
return clone;
return clone.cloneAnnotations(this);
}
}
@@ -58,7 +58,7 @@ public class MethodInsnNode extends AbstractInsnNode {
public String desc;
/**
* Constructs a new {@link org.objectweb.asm.tree.MethodInsnNode}.
* Constructs a new {@link MethodInsnNode}.
*
* @param opcode
* the opcode of the type instruction to be constructed. This
@@ -41,6 +41,7 @@ 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.
@@ -50,7 +51,7 @@ import org.objectweb.asm.Type;
public class MethodNode extends MethodVisitor {
/**
* The method's access flags (see {@link org.objectweb.asm.Opcodes}). This field also
* The method's access flags (see {@link Opcodes}). This field also
* indicates if the method is synthetic and/or deprecated.
*/
public int access;
@@ -77,9 +78,14 @@ public class MethodNode extends MethodVisitor {
*/
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 org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
@@ -88,16 +94,34 @@ public class MethodNode extends MethodVisitor {
/**
* The runtime invisible annotations of this method. This list is a list of
* {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* {@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 org.objectweb.asm.Attribute} objects. May be <tt>null</tt>.
* {@link Attribute} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.Attribute
*/
@@ -108,14 +132,14 @@ public class MethodNode extends MethodVisitor {
* 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 org.objectweb.asm.tree.AnnotationNode}, or a {@link java.util.List} of
* 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 org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible parameters
@@ -124,7 +148,7 @@ public class MethodNode extends MethodVisitor {
/**
* The runtime invisible parameter annotations of this method. These lists
* are lists of {@link org.objectweb.asm.tree.AnnotationNode} objects. May be <tt>null</tt>.
* are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label visible parameters
@@ -133,7 +157,7 @@ public class MethodNode extends MethodVisitor {
/**
* The instructions of this method. This list is a list of
* {@link org.objectweb.asm.tree.AbstractInsnNode} objects.
* {@link AbstractInsnNode} objects.
*
* @associates org.objectweb.asm.tree.AbstractInsnNode
* @label instructions
@@ -160,32 +184,48 @@ public class MethodNode extends MethodVisitor {
/**
* The local variables of this method. This list is a list of
* {@link org.objectweb.asm.tree.LocalVariableNode} objects. May be <tt>null</tt>
* {@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 org.objectweb.asm.tree.MethodNode}. <i>Subclasses must not
* 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.ASM4);
this(Opcodes.ASM5);
}
/**
* Constructs an uninitialized {@link org.objectweb.asm.tree.MethodNode}.
* Constructs an uninitialized {@link MethodNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link org.objectweb.asm.Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodNode(final int api) {
super(api);
@@ -193,12 +233,12 @@ public class MethodNode extends MethodVisitor {
}
/**
* Constructs a new {@link org.objectweb.asm.tree.MethodNode}. <i>Subclasses must not use this
* 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 org.objectweb.asm.Opcodes}). This
* the method's access flags (see {@link Opcodes}). This
* parameter also indicates if the method is synthetic and/or
* deprecated.
* @param name
@@ -214,17 +254,17 @@ public class MethodNode extends MethodVisitor {
*/
public MethodNode(final int access, final String name, final String desc,
final String signature, final String[] exceptions) {
this(Opcodes.ASM4, access, name, desc, signature, exceptions);
this(Opcodes.ASM5, access, name, desc, signature, exceptions);
}
/**
* Constructs a new {@link org.objectweb.asm.tree.MethodNode}.
* Constructs a new {@link MethodNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link org.objectweb.asm.Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param access
* the method's access flags (see {@link org.objectweb.asm.Opcodes}). This
* the method's access flags (see {@link Opcodes}). This
* parameter also indicates if the method is synthetic and/or
* deprecated.
* @param name
@@ -263,11 +303,18 @@ public class MethodNode extends MethodVisitor {
// ------------------------------------------------------------------------
@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) {
private static final long serialVersionUID = 3618671528080057645L;
@Override
@Override
public boolean add(final Object o) {
annotationDefault = o;
return super.add(o);
@@ -293,6 +340,24 @@ public class MethodNode extends MethodVisitor {
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,
@@ -419,6 +484,33 @@ public class MethodNode extends MethodVisitor {
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) {
@@ -426,6 +518,27 @@ public class MethodNode extends MethodVisitor {
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,
@@ -434,6 +547,29 @@ public class MethodNode extends MethodVisitor {
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)));
@@ -452,7 +588,7 @@ public class MethodNode extends MethodVisitor {
/**
* Returns the LabelNode corresponding to the given Label. Creates a new
* LabelNode if necessary. The default implementation of this method uses
* the {@link org.objectweb.asm.Label#info} field to store associations between labels and
* the {@link Label#info} field to store associations between labels and
* label nodes.
*
* @param l
@@ -497,10 +633,52 @@ public class MethodNode extends MethodVisitor {
* versions of the ASM API than the given version.
*
* @param api
* an ASM API version. Must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
* an ASM API version. Must be one of {@link Opcodes#ASM4} or
* {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
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();
}
}
}
/**
@@ -526,8 +704,14 @@ public class MethodNode extends MethodVisitor {
* a method visitor.
*/
public void accept(final MethodVisitor mv) {
// visits the method attributes
// 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);
@@ -545,6 +729,19 @@ public class MethodNode extends MethodVisitor {
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) {
@@ -582,6 +779,7 @@ public class MethodNode extends MethodVisitor {
// 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
@@ -591,6 +789,17 @@ public class MethodNode extends MethodVisitor {
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;
@@ -52,7 +52,7 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
public int dims;
/**
* Constructs a new {@link org.objectweb.asm.tree.MultiANewArrayInsnNode}.
* Constructs a new {@link MultiANewArrayInsnNode}.
*
* @param desc
* an array type descriptor (see {@link org.objectweb.asm.Type}).
@@ -73,11 +73,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitMultiANewArrayInsn(desc, dims);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new MultiANewArrayInsnNode(desc, dims);
return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
}
}
@@ -0,0 +1,76 @@
/***
* 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 org.objectweb.asm.MethodVisitor;
/**
* A node that represents a parameter access and name.
*
* @author Remi Forax
*/
public class ParameterNode {
/**
* The parameter's name.
*/
public String name;
/**
* The parameter's access flags (see {@link org.objectweb.asm.Opcodes}).
* Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
* <tt>ACC_MANDATED</tt>.
*/
public int access;
/**
* Constructs a new {@link ParameterNode}.
*
* @param access
* The parameter's access flags. Valid values are
* <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
* <tt>ACC_MANDATED</tt> (see {@link org.objectweb.asm.Opcodes}).
* @param name
* the parameter's name.
*/
public ParameterNode(final String name, final int access) {
this.name = name;
this.access = access;
}
/**
* Makes the given visitor visit this parameter declaration.
*
* @param mv
* a method visitor.
*/
public void accept(final MethodVisitor mv) {
mv.visitParameter(name, access);
}
}
@@ -62,12 +62,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
/**
* Beginnings of the handler blocks. This list is a list of
* {@link org.objectweb.asm.tree.LabelNode} objects.
* {@link LabelNode} objects.
*/
public List<LabelNode> labels;
/**
* Constructs a new {@link org.objectweb.asm.tree.TableSwitchInsnNode}.
* Constructs a new {@link TableSwitchInsnNode}.
*
* @param min
* the minimum key value.
@@ -103,11 +103,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
this.labels, labels));
this.labels, labels)).cloneAnnotations(this);
}
}
@@ -29,6 +29,8 @@
*/
package org.objectweb.asm.tree;
import java.util.List;
import org.objectweb.asm.MethodVisitor;
/**
@@ -60,7 +62,27 @@ public class TryCatchBlockNode {
public String type;
/**
* Constructs a new {@link org.objectweb.asm.tree.TryCatchBlockNode}.
* The runtime visible type annotations on the exception handler type. 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 on the exception handler type.
* 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;
/**
* Constructs a new {@link TryCatchBlockNode}.
*
* @param start
* beginning of the exception handler's scope (inclusive).
@@ -81,6 +103,29 @@ public class TryCatchBlockNode {
this.type = type;
}
/**
* Updates the index of this try catch block in the method's list of try
* catch block nodes. This index maybe stored in the 'target' field of the
* type annotations of this block.
*
* @param index
* the new index of this try catch block in the method's list of
* try catch block nodes.
*/
public void updateIndex(final int index) {
int newTypeRef = 0x42000000 | (index << 8);
if (visibleTypeAnnotations != null) {
for (TypeAnnotationNode tan : visibleTypeAnnotations) {
tan.typeRef = newTypeRef;
}
}
if (invisibleTypeAnnotations != null) {
for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
tan.typeRef = newTypeRef;
}
}
}
/**
* Makes the given visitor visit this try catch block.
*
@@ -90,5 +135,19 @@ public class TryCatchBlockNode {
public void accept(final MethodVisitor mv) {
mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
handler == null ? null : handler.getLabel(), type);
int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
.size();
for (int i = 0; i < n; ++i) {
TypeAnnotationNode an = visibleTypeAnnotations.get(i);
an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
an.desc, true));
}
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
.size();
for (int i = 0; i < n; ++i) {
TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
an.desc, false));
}
}
}
@@ -0,0 +1,95 @@
/***
* 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 org.objectweb.asm.Opcodes;
import org.objectweb.asm.TypePath;
import org.objectweb.asm.TypeReference;
/**
* A node that represents a type annotationn.
*
* @author Eric Bruneton
*/
public class TypeAnnotationNode extends AnnotationNode {
/**
* A reference to the annotated type. See {@link TypeReference}.
*/
public int typeRef;
/**
* The path to the annotated type argument, wildcard bound, array element
* type, or static outer type within the referenced type. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
*/
public TypePath typePath;
/**
* Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
*
* @param typeRef
* a reference to the annotated type. See {@link TypeReference}.
* @param typePath
* the path to the annotated type argument, wildcard bound, array
* element type, or static inner type within 'typeRef'. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
* @param desc
* the class descriptor of the annotation class.
*/
public TypeAnnotationNode(final int typeRef, final TypePath typePath,
final String desc) {
this(Opcodes.ASM5, typeRef, typePath, desc);
}
/**
* Constructs a new {@link AnnotationNode}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param typeRef
* a reference to the annotated type. See {@link TypeReference}.
* @param typePath
* the path to the annotated type argument, wildcard bound, array
* element type, or static inner type within 'typeRef'. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
* @param desc
* the class descriptor of the annotation class.
*/
public TypeAnnotationNode(final int api, final int typeRef,
final TypePath typePath, final String desc) {
super(api, desc);
this.typeRef = typeRef;
this.typePath = typePath;
}
}
@@ -48,7 +48,7 @@ public class TypeInsnNode extends AbstractInsnNode {
public String desc;
/**
* Constructs a new {@link org.objectweb.asm.tree.TypeInsnNode}.
* Constructs a new {@link TypeInsnNode}.
*
* @param opcode
* the opcode of the type instruction to be constructed. This
@@ -81,10 +81,11 @@ public class TypeInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitTypeInsn(opcode, desc);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new TypeInsnNode(opcode, desc);
return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
}
}
@@ -49,7 +49,7 @@ public class VarInsnNode extends AbstractInsnNode {
public int var;
/**
* Constructs a new {@link org.objectweb.asm.tree.VarInsnNode}.
* Constructs a new {@link VarInsnNode}.
*
* @param opcode
* the opcode of the local variable instruction to be
@@ -84,10 +84,11 @@ public class VarInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitVarInsn(opcode, var);
acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
return new VarInsnNode(opcode, var);
return new VarInsnNode(opcode, var).cloneAnnotations(this);
}
}