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
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4}.
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -52,28 +52,28 @@ public abstract class AnnotationVisitor {
protected AnnotationVisitor av;
/**
* Constructs a new {@link org.objectweb.asm.AnnotationVisitor}.
* Constructs a new {@link AnnotationVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link org.objectweb.asm.AnnotationVisitor}.
* Constructs a new {@link AnnotationVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param av
* the annotation visitor to which this visitor must delegate
* method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
if (api != Opcodes.ASM4) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -30,7 +30,7 @@
package org.objectweb.asm;
/**
* An {@link org.objectweb.asm.AnnotationVisitor} that generates annotations in bytecode form.
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
*
* @author Eric Bruneton
* @author Eugene Kuleshov
@@ -88,7 +88,7 @@ final class AnnotationWriter extends AnnotationVisitor {
// ------------------------------------------------------------------------
/**
* Constructs a new {@link org.objectweb.asm.AnnotationWriter}.
* Constructs a new {@link AnnotationWriter}.
*
* @param cw
* the class writer to which this annotation must be added.
@@ -104,7 +104,7 @@ final class AnnotationWriter extends AnnotationVisitor {
*/
AnnotationWriter(final ClassWriter cw, final boolean named,
final ByteVector bv, final ByteVector parent, final int offset) {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
this.cw = cw;
this.named = named;
this.bv = bv;
@@ -315,4 +315,57 @@ final class AnnotationWriter extends AnnotationVisitor {
}
}
}
/**
* Puts the given type reference and type path into the given bytevector.
* LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
*
* @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 out
* where the type reference and type path must be put.
*/
static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
switch (typeRef >>> 24) {
case 0x00: // CLASS_TYPE_PARAMETER
case 0x01: // METHOD_TYPE_PARAMETER
case 0x16: // METHOD_FORMAL_PARAMETER
out.putShort(typeRef >>> 16);
break;
case 0x13: // FIELD
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
out.putByte(typeRef >>> 24);
break;
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
out.putInt(typeRef);
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
break;
}
if (typePath == null) {
out.putByte(0);
} else {
int length = typePath.b[typePath.offset] * 2 + 1;
out.putByteArray(typePath.b, typePath.offset, length);
}
}
}
@@ -93,7 +93,7 @@ public class Attribute {
/**
* Reads a {@link #type type} attribute. This method must return a
* <i>new</i> {@link org.objectweb.asm.Attribute} object, of type {@link #type type},
* <i>new</i> {@link Attribute} object, of type {@link #type type},
* corresponding to the <tt>len</tt> bytes starting at the given offset, in
* the given class reader.
*
@@ -119,7 +119,7 @@ public class Attribute {
* @param labels
* the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return a <i>new</i> {@link org.objectweb.asm.Attribute} object corresponding to the given
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
protected Attribute read(final ClassReader cr, final int off,
@@ -48,7 +48,7 @@ public class ByteVector {
int length;
/**
* Constructs a new {@link org.objectweb.asm.ByteVector ByteVector} with a default initial
* Constructs a new {@link ByteVector ByteVector} with a default initial
* size.
*/
public ByteVector() {
@@ -56,7 +56,7 @@ public class ByteVector {
}
/**
* Constructs a new {@link org.objectweb.asm.ByteVector ByteVector} with the given initial
* Constructs a new {@link ByteVector ByteVector} with the given initial
* size.
*
* @param initialSize
@@ -204,11 +204,14 @@ public class ByteVector {
* automatically enlarged if necessary.
*
* @param s
* a String.
* a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
if (charLength > 65535) {
throw new IllegalArgumentException();
}
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
@@ -238,6 +241,9 @@ public class ByteVector {
byteLength += 2;
}
}
if (byteLength > 65535) {
throw new IllegalArgumentException();
}
data[length] = (byte) (byteLength >>> 8);
data[length + 1] = (byte) byteLength;
if (length + 2 + byteLength > data.length) {
+348 -55
View File
@@ -106,7 +106,7 @@ public class ClassReader {
/**
* The class to be parsed. <i>The content of this array must not be
* modified. This field is intended for {@link org.objectweb.asm.Attribute} sub classes, and
* modified. This field is intended for {@link Attribute} sub classes, and
* is normally not needed by class generators or adapters.</i>
*/
public final byte[] b;
@@ -144,7 +144,7 @@ public class ClassReader {
// ------------------------------------------------------------------------
/**
* Constructs a new {@link org.objectweb.asm.ClassReader} object.
* Constructs a new {@link ClassReader} object.
*
* @param b
* the bytecode of the class to be read.
@@ -154,7 +154,7 @@ public class ClassReader {
}
/**
* Constructs a new {@link org.objectweb.asm.ClassReader} object.
* Constructs a new {@link ClassReader} object.
*
* @param b
* the bytecode of the class to be read.
@@ -166,7 +166,7 @@ public class ClassReader {
public ClassReader(final byte[] b, final int off, final int len) {
this.b = b;
// checks the class version
if (readShort(off + 6) > Opcodes.V1_7) {
if (readShort(off + 6) > Opcodes.V1_8) {
throw new IllegalArgumentException();
}
// parses the constant pool
@@ -413,11 +413,11 @@ public class ClassReader {
}
/**
* Constructs a new {@link org.objectweb.asm.ClassReader} object.
* Constructs a new {@link ClassReader} object.
*
* @param is
* an input stream from which to read the class.
* @throws java.io.IOException
* @throws IOException
* if a problem occurs during reading.
*/
public ClassReader(final InputStream is) throws IOException {
@@ -425,11 +425,11 @@ public class ClassReader {
}
/**
* Constructs a new {@link org.objectweb.asm.ClassReader} object.
* Constructs a new {@link ClassReader} object.
*
* @param name
* the binary qualified name of the class to be read.
* @throws java.io.IOException
* @throws IOException
* if an exception occurs during reading.
*/
public ClassReader(final String name) throws IOException {
@@ -446,7 +446,7 @@ public class ClassReader {
* @param close
* true to close the input stream after reading.
* @return the bytecode read from the given input stream.
* @throws java.io.IOException
* @throws IOException
* if a problem occurs during reading.
*/
private static byte[] readClass(final InputStream is, boolean close)
@@ -491,7 +491,7 @@ public class ClassReader {
// ------------------------------------------------------------------------
/**
* Makes the given visitor visit the Java class of this {@link org.objectweb.asm.ClassReader}
* Makes the given visitor visit the Java class of this {@link ClassReader}
* . This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
*
@@ -507,7 +507,7 @@ public class ClassReader {
}
/**
* Makes the given visitor visit the Java class of this {@link org.objectweb.asm.ClassReader}.
* Makes the given visitor visit the Java class of this {@link ClassReader}.
* This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
*
@@ -557,6 +557,8 @@ public class ClassReader {
String enclosingDesc = null;
int anns = 0;
int ianns = 0;
int tanns = 0;
int itanns = 0;
int innerClasses = 0;
Attribute attributes = null;
@@ -581,6 +583,9 @@ public class ClassReader {
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) {
@@ -592,6 +597,9 @@ public class ClassReader {
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else if ("BootstrapMethods".equals(attrName)) {
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
@@ -626,7 +634,7 @@ public class ClassReader {
enclosingDesc);
}
// visits the class annotations
// visits the class annotations and type annotations
if (ANNOTATIONS && anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
@@ -639,6 +647,22 @@ public class ClassReader {
classVisitor.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
classVisitor.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
}
// visits the attributes
while (attributes != null) {
@@ -697,6 +721,8 @@ public class ClassReader {
String signature = null;
int anns = 0;
int ianns = 0;
int tanns = 0;
int itanns = 0;
Object value = null;
Attribute attributes = null;
@@ -717,9 +743,15 @@ public class ClassReader {
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else {
Attribute attr = readAttribute(context.attrs, attrName, u + 8,
readInt(u + 4), c, -1, null);
@@ -739,7 +771,7 @@ public class ClassReader {
return u;
}
// visits the field annotations
// visits the field annotations and type annotations
if (ANNOTATIONS && anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
@@ -752,6 +784,22 @@ public class ClassReader {
fv.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
fv.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
fv.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
}
// visits the field attributes
while (attributes != null) {
@@ -782,9 +830,9 @@ public class ClassReader {
final Context context, int u) {
// reads the method declaration
char[] c = context.buffer;
int access = readUnsignedShort(u);
String name = readUTF8(u + 2, c);
String desc = readUTF8(u + 4, c);
context.access = readUnsignedShort(u);
context.name = readUTF8(u + 2, c);
context.desc = readUTF8(u + 4, c);
u += 6;
// reads the method attributes
@@ -792,8 +840,11 @@ public class ClassReader {
int exception = 0;
String[] exceptions = null;
String signature = null;
int methodParameters = 0;
int anns = 0;
int ianns = 0;
int tanns = 0;
int itanns = 0;
int dann = 0;
int mpanns = 0;
int impanns = 0;
@@ -818,24 +869,32 @@ public class ClassReader {
} else if (SIGNATURES && "Signature".equals(attrName)) {
signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
context.access |= Opcodes.ACC_DEPRECATED;
} else if (ANNOTATIONS
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8;
} else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
dann = u + 8;
} else if ("Synthetic".equals(attrName)) {
access |= Opcodes.ACC_SYNTHETIC
context.access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeVisibleParameterAnnotations".equals(attrName)) {
mpanns = u + 8;
} else if (ANNOTATIONS
&& "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
impanns = u + 8;
} else if ("MethodParameters".equals(attrName)) {
methodParameters = u + 8;
} else {
Attribute attr = readAttribute(context.attrs, attrName, u + 8,
readInt(u + 4), c, -1, null);
@@ -849,8 +908,8 @@ public class ClassReader {
u += 2;
// visits the method declaration
MethodVisitor mv = classVisitor.visitMethod(access, name, desc,
signature, exceptions);
MethodVisitor mv = classVisitor.visitMethod(context.access,
context.name, context.desc, signature, exceptions);
if (mv == null) {
return u;
}
@@ -894,6 +953,13 @@ public class ClassReader {
}
}
// visit the method parameters
if (methodParameters != 0) {
for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
}
}
// visits the method annotations
if (ANNOTATIONS && dann != 0) {
AnnotationVisitor dv = mv.visitAnnotationDefault();
@@ -914,11 +980,27 @@ public class ClassReader {
mv.visitAnnotation(readUTF8(v, c), false));
}
}
if (ANNOTATIONS && tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
mv.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
}
if (ANNOTATIONS && itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true,
mv.visitTypeAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
}
if (ANNOTATIONS && mpanns != 0) {
readParameterAnnotations(mpanns, desc, c, true, mv);
readParameterAnnotations(mv, context, mpanns, true);
}
if (ANNOTATIONS && impanns != 0) {
readParameterAnnotations(impanns, desc, c, false, mv);
readParameterAnnotations(mv, context, impanns, false);
}
// visits the method attributes
@@ -931,9 +1013,6 @@ public class ClassReader {
// visits the method code
if (code != 0) {
context.access = access;
context.name = name;
context.desc = desc;
mv.visitCode();
readCode(mv, context, code);
}
@@ -966,7 +1045,7 @@ public class ClassReader {
// reads the bytecode to find the labels
int codeStart = u;
int codeEnd = u + codeLength;
Label[] labels = new Label[codeLength + 2];
Label[] labels = context.labels = new Label[codeLength + 2];
readLabel(codeLength + 1, labels);
while (u < codeEnd) {
int offset = u - codeStart;
@@ -1049,6 +1128,12 @@ public class ClassReader {
u += 2;
// reads the code attributes
int[] tanns = null; // start index of each visible type annotation
int[] itanns = null; // start index of each invisible type annotation
int tann = 0; // current index in tanns array
int itann = 0; // current index in itanns array
int ntoff = -1; // next visible type annotation code offset
int nitoff = -1; // next invisible type annotation code offset
int varTable = 0;
int varTypeTable = 0;
boolean zip = true;
@@ -1089,6 +1174,16 @@ public class ClassReader {
v += 4;
}
}
} else if (ANNOTATIONS
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = readTypeAnnotations(mv, context, u + 8, true);
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
: readUnsignedShort(tanns[0] + 1);
} else if (ANNOTATIONS
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = readTypeAnnotations(mv, context, u + 8, false);
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
: readUnsignedShort(itanns[0] + 1);
} else if (FRAMES && "StackMapTable".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) {
stackMap = u + 10;
@@ -1211,7 +1306,7 @@ public class ClassReader {
}
}
if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, labels, frame);
stackMap = readFrame(stackMap, zip, unzip, frame);
--frameCount;
} else {
frame = null;
@@ -1358,6 +1453,29 @@ public class ClassReader {
u += 4;
break;
}
// visit the instruction annotations, if any
while (tanns != null && tann < tanns.length && ntoff <= offset) {
if (ntoff == offset) {
int v = readAnnotationTarget(context, tanns[tann]);
readAnnotationValues(v + 2, c, true,
mv.visitInsnAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), true));
}
ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1
: readUnsignedShort(tanns[tann] + 1);
}
while (itanns != null && itann < itanns.length && nitoff <= offset) {
if (nitoff == offset) {
int v = readAnnotationTarget(context, itanns[itann]);
readAnnotationValues(v + 2, c, true,
mv.visitInsnAnnotation(context.typeRef,
context.typePath, readUTF8(v, c), false));
}
nitoff = ++itann >= itanns.length
|| readByte(itanns[itann]) < 0x43 ? -1
: readUnsignedShort(itanns[itann] + 1);
}
}
if (labels[codeLength] != null) {
mv.visitLabel(labels[codeLength]);
@@ -1397,6 +1515,32 @@ public class ClassReader {
}
}
// visits the local variables type annotations
if (tanns != null) {
for (int i = 0; i < tanns.length; ++i) {
if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) {
int v = readAnnotationTarget(context, tanns[i]);
v = readAnnotationValues(v + 2, c, true,
mv.visitLocalVariableAnnotation(context.typeRef,
context.typePath, context.start,
context.end, context.index, readUTF8(v, c),
true));
}
}
}
if (itanns != null) {
for (int i = 0; i < itanns.length; ++i) {
if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) {
int v = readAnnotationTarget(context, itanns[i]);
v = readAnnotationValues(v + 2, c, true,
mv.visitLocalVariableAnnotation(context.typeRef,
context.typePath, context.start,
context.end, context.index, readUTF8(v, c),
false));
}
}
}
// visits the code attributes
while (attributes != null) {
Attribute attr = attributes.next;
@@ -1409,25 +1553,176 @@ public class ClassReader {
mv.visitMaxs(maxStack, maxLocals);
}
/**
* Parses a type annotation table to find the labels, and to visit the try
* catch block annotations.
*
* @param u
* the start offset of a type annotation table.
* @param mv
* the method visitor to be used to visit the try catch block
* annotations.
* @param context
* information about the class being parsed.
* @param visible
* if the type annotation table to parse contains runtime visible
* annotations.
* @return the start offset of each type annotation in the parsed table.
*/
private int[] readTypeAnnotations(final MethodVisitor mv,
final Context context, int u, boolean visible) {
char[] c = context.buffer;
int[] offsets = new int[readUnsignedShort(u)];
u += 2;
for (int i = 0; i < offsets.length; ++i) {
offsets[i] = u;
int target = readInt(u);
switch (target >>> 24) {
case 0x00: // CLASS_TYPE_PARAMETER
case 0x01: // METHOD_TYPE_PARAMETER
case 0x16: // METHOD_FORMAL_PARAMETER
u += 2;
break;
case 0x13: // FIELD
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
u += 1;
break;
case 0x40: // LOCAL_VARIABLE
case 0x41: // RESOURCE_VARIABLE
for (int j = readUnsignedShort(u + 1); j > 0; --j) {
int start = readUnsignedShort(u + 3);
int length = readUnsignedShort(u + 5);
readLabel(start, context.labels);
readLabel(start + length, context.labels);
u += 6;
}
u += 3;
break;
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
u += 4;
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
u += 3;
break;
}
int pathLength = readByte(u);
if ((target >>> 24) == 0x42) {
TypePath path = pathLength == 0 ? null : new TypePath(b, u);
u += 1 + 2 * pathLength;
u = readAnnotationValues(u + 2, c, true,
mv.visitTryCatchAnnotation(target, path,
readUTF8(u, c), visible));
} else {
u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null);
}
}
return offsets;
}
/**
* Parses the header of a type annotation to extract its target_type and
* target_path (the result is stored in the given context), and returns the
* start offset of the rest of the type_annotation structure (i.e. the
* offset to the type_index field, which is followed by
* num_element_value_pairs and then the name,value pairs).
*
* @param context
* information about the class being parsed. This is where the
* extracted target_type and target_path must be stored.
* @param u
* the start offset of a type_annotation structure.
* @return the start offset of the rest of the type_annotation structure.
*/
private int readAnnotationTarget(final Context context, int u) {
int target = readInt(u);
switch (target >>> 24) {
case 0x00: // CLASS_TYPE_PARAMETER
case 0x01: // METHOD_TYPE_PARAMETER
case 0x16: // METHOD_FORMAL_PARAMETER
target &= 0xFFFF0000;
u += 2;
break;
case 0x13: // FIELD
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
target &= 0xFF000000;
u += 1;
break;
case 0x40: // LOCAL_VARIABLE
case 0x41: { // RESOURCE_VARIABLE
target &= 0xFF000000;
int n = readUnsignedShort(u + 1);
context.start = new Label[n];
context.end = new Label[n];
context.index = new int[n];
u += 3;
for (int i = 0; i < n; ++i) {
int start = readUnsignedShort(u);
int length = readUnsignedShort(u + 2);
context.start[i] = readLabel(start, context.labels);
context.end[i] = readLabel(start + length, context.labels);
context.index[i] = readUnsignedShort(u + 4);
u += 6;
}
break;
}
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
target &= 0xFF0000FF;
u += 4;
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000;
u += 3;
break;
}
int pathLength = readByte(u);
context.typeRef = target;
context.typePath = pathLength == 0 ? null : new TypePath(b, u);
return u + 1 + 2 * pathLength;
}
/**
* Reads parameter annotations and makes the given visitor visit them.
*
* @param mv
* the visitor that must visit the annotations.
* @param context
* information about the class being parsed.
* @param v
* start offset in {@link #b b} of the annotations to be read.
* @param desc
* the method descriptor.
* @param buf
* buffer to be used to call {@link #readUTF8 readUTF8},
* {@link #readClass(int,char[]) readClass} or {@link #readConst
* readConst}.
* @param visible
* <tt>true</tt> if the annotations to be read are visible at
* runtime.
* @param mv
* the visitor that must visit the annotations.
*/
private void readParameterAnnotations(int v, final String desc,
final char[] buf, final boolean visible, final MethodVisitor mv) {
private void readParameterAnnotations(final MethodVisitor mv,
final Context context, int v, final boolean visible) {
int i;
int n = b[v++] & 0xFF;
// workaround for a bug in javac (javac compiler generates a parameter
@@ -1436,7 +1731,7 @@ public class ClassReader {
// equal to the number of parameters in the method descriptor - which
// includes the synthetic parameters added by the compiler). This work-
// around supposes that the synthetic parameters are the first ones.
int synthetics = Type.getArgumentTypes(desc).length - n;
int synthetics = Type.getArgumentTypes(context.desc).length - n;
AnnotationVisitor av;
for (i = 0; i < synthetics; ++i) {
// virtual annotation to detect synthetic parameters in MethodWriter
@@ -1445,12 +1740,13 @@ public class ClassReader {
av.visitEnd();
}
}
char[] c = context.buffer;
for (; i < n + synthetics; ++i) {
int j = readUnsignedShort(v);
v += 2;
for (; j > 0; --j) {
av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
v = readAnnotationValues(v + 2, buf, true, av);
av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible);
v = readAnnotationValues(v + 2, c, true, av);
}
}
}
@@ -1729,17 +2025,14 @@ public class ClassReader {
* if the stack map frame at stackMap is compressed or not.
* @param unzip
* if the stack map frame must be uncompressed.
* @param labels
* the labels of the method currently being parsed, indexed by
* their offset. A new label for the parsed stack map frame is
* stored in this array if it does not already exist.
* @param frame
* where the parsed stack map frame must be stored.
* @return the offset of the first byte following the parsed frame.
*/
private int readFrame(int stackMap, boolean zip, boolean unzip,
Label[] labels, Context frame) {
Context frame) {
char[] c = frame.buffer;
Label[] labels = frame.labels;
int tag;
int delta;
if (zip) {
@@ -1916,7 +2209,7 @@ public class ClassReader {
* prototypes of the attributes that must be parsed during the
* visit of the class. Any attribute whose type is not equal to
* the type of one the prototypes is ignored (i.e. an empty
* {@link org.objectweb.asm.Attribute} instance is returned).
* {@link Attribute} instance is returned).
* @param type
* the type of the attribute.
* @param off
@@ -1968,7 +2261,7 @@ public class ClassReader {
/**
* Returns the start index of the constant pool item in {@link #b b}, plus
* one. <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* one. <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param item
@@ -1993,7 +2286,7 @@ public class ClassReader {
/**
* Reads a byte value in {@link #b b}. <i>This method is intended for
* {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index
@@ -2006,7 +2299,7 @@ public class ClassReader {
/**
* Reads an unsigned short value in {@link #b b}. <i>This method is intended
* for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index
@@ -2020,7 +2313,7 @@ public class ClassReader {
/**
* Reads a signed short value in {@link #b b}. <i>This method is intended
* for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index
@@ -2034,7 +2327,7 @@ public class ClassReader {
/**
* Reads a signed int value in {@link #b b}. <i>This method is intended for
* {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index
@@ -2049,7 +2342,7 @@ public class ClassReader {
/**
* Reads a signed long value in {@link #b b}. <i>This method is intended for
* {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index
@@ -2064,7 +2357,7 @@ public class ClassReader {
/**
* Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
* is intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed
* is intended for {@link Attribute} sub classes, and is normally not needed
* by class generators or adapters.</i>
*
* @param index
@@ -2139,7 +2432,7 @@ public class ClassReader {
/**
* Reads a class constant pool item in {@link #b b}. <i>This method is
* intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index
@@ -2159,7 +2452,7 @@ public class ClassReader {
/**
* Reads a numeric or string constant pool item in {@link #b b}. <i>This
* method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param item
@@ -33,8 +33,9 @@ package org.objectweb.asm;
* A visitor to visit a Java class. The methods of this class must be called in
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> | <tt>visitField</tt> |
* <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
* <tt>visitEnd</tt>.
*
* @author Eric Bruneton
*/
@@ -42,7 +43,7 @@ public abstract class ClassVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4}.
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -53,28 +54,28 @@ public abstract class ClassVisitor {
protected ClassVisitor cv;
/**
* Constructs a new {@link org.objectweb.asm.ClassVisitor}.
* Constructs a new {@link ClassVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link org.objectweb.asm.ClassVisitor}.
* Constructs a new {@link ClassVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param cv
* the class visitor to which this visitor must delegate method
* calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
if (api != Opcodes.ASM4) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -168,6 +169,39 @@ public abstract class ClassVisitor {
return null;
}
/**
* Visits an annotation on a type in the class signature.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
* CLASS_TYPE_PARAMETER},
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
* CLASS_TYPE_PARAMETER_BOUND} or
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits a non standard attribute of the class.
*
@@ -30,10 +30,10 @@
package org.objectweb.asm;
/**
* A {@link org.objectweb.asm.ClassVisitor} that generates classes in bytecode form. More
* A {@link ClassVisitor} that generates classes in bytecode form. More
* precisely this visitor generates a byte array conforming to the Java class
* file format. It can be used alone, to generate a Java class "from scratch",
* or with one or more {@link org.objectweb.asm.ClassReader ClassReader} and adapter class visitor
* or with one or more {@link ClassReader ClassReader} and adapter class visitor
* to generate a modified class from one or more existing Java classes.
*
* @author Eric Bruneton
@@ -250,7 +250,7 @@ public class ClassWriter extends ClassVisitor {
static final int HANDLE_BASE = 20;
/**
* Normal type Item stored in the ClassWriter {@link org.objectweb.asm.ClassWriter#typeTable},
* Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
* instead of the constant pool, in order to avoid clashes with normal
* constant pool items in the ClassWriter constant pool's hash table.
*/
@@ -258,14 +258,14 @@ public class ClassWriter extends ClassVisitor {
/**
* Uninitialized type Item stored in the ClassWriter
* {@link org.objectweb.asm.ClassWriter#typeTable}, instead of the constant pool, in order to
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
* avoid clashes with normal constant pool items in the ClassWriter constant
* pool's hash table.
*/
static final int TYPE_UNINIT = 31;
/**
* Merged type Item stored in the ClassWriter {@link org.objectweb.asm.ClassWriter#typeTable},
* Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
* instead of the constant pool, in order to avoid clashes with normal
* constant pool items in the ClassWriter constant pool's hash table.
*/
@@ -416,6 +416,16 @@ public class ClassWriter extends ClassVisitor {
*/
private AnnotationWriter ianns;
/**
* The runtime visible type annotations of this class.
*/
private AnnotationWriter tanns;
/**
* The runtime invisible type annotations of this class.
*/
private AnnotationWriter itanns;
/**
* The non standard attributes of this class.
*/
@@ -477,12 +487,12 @@ public class ClassWriter extends ClassVisitor {
* <tt>true</tt> if the maximum stack size and number of local variables
* must be automatically computed.
*/
private final boolean computeMaxs;
private boolean computeMaxs;
/**
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
*/
private final boolean computeFrames;
private boolean computeFrames;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
@@ -587,7 +597,7 @@ public class ClassWriter extends ClassVisitor {
// ------------------------------------------------------------------------
/**
* Constructs a new {@link org.objectweb.asm.ClassWriter} object.
* Constructs a new {@link ClassWriter} object.
*
* @param flags
* option flags that can be used to modify the default behavior
@@ -595,7 +605,7 @@ public class ClassWriter extends ClassVisitor {
* {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
index = 1;
pool = new ByteVector();
items = new Item[256];
@@ -609,7 +619,7 @@ public class ClassWriter extends ClassVisitor {
}
/**
* Constructs a new {@link org.objectweb.asm.ClassWriter} object and enables optimizations for
* Constructs a new {@link ClassWriter} object and enables optimizations for
* "mostly add" bytecode transformations. These optimizations are the
* following:
*
@@ -622,13 +632,13 @@ public class ClassWriter extends ClassVisitor {
* directly from the original class bytecode (i.e. without emitting visit
* events for all the method instructions), which saves a <i>lot</i> of
* time. Untransformed methods are detected by the fact that the
* {@link org.objectweb.asm.ClassReader} receives {@link MethodVisitor} objects that come from
* a {@link org.objectweb.asm.ClassWriter} (and not from any other {@link org.objectweb.asm.ClassVisitor}
* {@link ClassReader} receives {@link MethodVisitor} objects that come from
* a {@link ClassWriter} (and not from any other {@link ClassVisitor}
* instance).</li>
* </ul>
*
* @param classReader
* the {@link org.objectweb.asm.ClassReader} used to read the original class. It
* the {@link ClassReader} used to read the original class. It
* will be used to copy the entire constant pool from the
* original class and also to copy other fragments of original
* bytecode where applicable.
@@ -710,6 +720,29 @@ public class ClassWriter extends ClassVisitor {
return aw;
}
@Override
public final AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = tanns;
tanns = aw;
} else {
aw.next = itanns;
itanns = aw;
}
return aw;
}
@Override
public final void visitAttribute(final Attribute attr) {
attr.next = attrs;
@@ -831,6 +864,16 @@ public class ClassWriter extends ClassVisitor {
size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations");
}
if (ClassReader.ANNOTATIONS && tanns != null) {
++attributeCount;
size += 8 + tanns.getSize();
newUTF8("RuntimeVisibleTypeAnnotations");
}
if (ClassReader.ANNOTATIONS && itanns != null) {
++attributeCount;
size += 8 + itanns.getSize();
newUTF8("RuntimeInvisibleTypeAnnotations");
}
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
@@ -904,13 +947,34 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (ClassReader.ANNOTATIONS && tanns != null) {
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (ClassReader.ANNOTATIONS && itanns != null) {
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
anns = null;
ianns = null;
attrs = null;
innerClassesCount = 0;
innerClasses = null;
bootstrapMethodsCount = 0;
bootstrapMethods = null;
firstField = null;
lastField = null;
firstMethod = null;
lastMethod = null;
computeMaxs = false;
computeFrames = true;
invalidFrames = false;
new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
return toByteArray();
}
return out.data;
}
@@ -978,7 +1042,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param cst
@@ -995,7 +1059,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds an UTF8 string to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param value
@@ -1016,7 +1080,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a class reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
@@ -1037,7 +1101,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a class reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
@@ -1051,7 +1115,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a method type reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param methodDesc
@@ -1072,7 +1136,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a method type reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param methodDesc
@@ -1087,7 +1151,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a handle to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item. <i>This method is
* intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param tag
@@ -1128,7 +1192,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a handle to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item. <i>This method is
* intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param tag
@@ -1156,7 +1220,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds an invokedynamic reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param name
@@ -1240,7 +1304,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds an invokedynamic reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param name
@@ -1286,7 +1350,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a field reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param owner
@@ -1331,7 +1395,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a method reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param owner
@@ -1449,7 +1513,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is normally not
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param name
@@ -1577,7 +1641,7 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the common super type of the two given types. The default
* implementation of this method <i>loads<i> the two given classes and uses
* implementation of this method <i>loads</i> the two given classes and uses
* the java.lang.Class methods to find the common super class. It can be
* overridden to compute this common super type in other ways, in particular
* without actually loading any class, or to take into account the class
+37 -2
View File
@@ -31,7 +31,7 @@
package org.objectweb.asm;
/**
* Information about a class being parsed in a {@link org.objectweb.asm.ClassReader}.
* Information about a class being parsed in a {@link ClassReader}.
*
* @author Eric Bruneton
*/
@@ -43,7 +43,7 @@ class Context {
Attribute[] attrs;
/**
* The {@link org.objectweb.asm.ClassReader} option flags for the parsing of this class.
* The {@link ClassReader} option flags for the parsing of this class.
*/
int flags;
@@ -72,11 +72,46 @@ class Context {
*/
String desc;
/**
* The label objects, indexed by bytecode offset, of the method currently
* being parsed (only bytecode offsets for which a label is needed have a
* non null associated Label object).
*/
Label[] labels;
/**
* The target of the type annotation currently being parsed.
*/
int typeRef;
/**
* The path of the type annotation currently being parsed.
*/
TypePath typePath;
/**
* The offset of the latest stack map frame that has been parsed.
*/
int offset;
/**
* The labels corresponding to the start of the local variable ranges in the
* local variable type annotation currently being parsed.
*/
Label[] start;
/**
* The labels corresponding to the end of the local variable ranges in the
* local variable type annotation currently being parsed.
*/
Label[] end;
/**
* The local variable indices for each local variable range in the local
* variable type annotation currently being parsed.
*/
int[] index;
/**
* The encoding of the latest stack map frame that has been parsed.
*/
+4 -4
View File
@@ -43,20 +43,20 @@ class Edge {
/**
* Denotes a control flow graph edge corresponding to an exception handler.
* More precisely any {@link org.objectweb.asm.Edge} whose {@link #info} is strictly positive
* More precisely any {@link Edge} whose {@link #info} is strictly positive
* corresponds to an exception handler. The actual value of {@link #info} is
* the index, in the {@link org.objectweb.asm.ClassWriter} type table, of the exception that
* the index, in the {@link ClassWriter} type table, of the exception that
* is catched.
*/
static final int EXCEPTION = 0x7FFFFFFF;
/**
* Information about this control flow graph edge. If
* {@link org.objectweb.asm.ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
* {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
* stack size in the basic block from which this edge originates. This size
* is equal to the stack size at the "jump" instruction to which this edge
* corresponds, relatively to the stack size at the beginning of the
* originating basic block. If {@link org.objectweb.asm.ClassWriter#COMPUTE_FRAMES} is used,
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
* this field is the kind of this control flow graph edge (i.e. NORMAL or
* EXCEPTION).
*/
@@ -31,8 +31,8 @@ package org.objectweb.asm;
/**
* A visitor to visit a Java field. The methods of this class must be called in
* the following order: ( <tt>visitAnnotation</tt> | <tt>visitAttribute</tt> )*
* <tt>visitEnd</tt>.
* the following order: ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
*
* @author Eric Bruneton
*/
@@ -40,7 +40,7 @@ public abstract class FieldVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4}.
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -51,28 +51,28 @@ public abstract class FieldVisitor {
protected FieldVisitor fv;
/**
* Constructs a new {@link org.objectweb.asm.FieldVisitor}.
* Constructs a new {@link FieldVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public FieldVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link org.objectweb.asm.FieldVisitor}.
* Constructs a new {@link FieldVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param fv
* the field visitor to which this visitor must delegate method
* calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
if (api != Opcodes.ASM4) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -96,6 +96,35 @@ public abstract class FieldVisitor {
return null;
}
/**
* Visits an annotation on the type of the field.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#FIELD FIELD}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits a non standard attribute of the field.
*
@@ -30,7 +30,7 @@
package org.objectweb.asm;
/**
* An {@link org.objectweb.asm.FieldVisitor} that generates Java fields in bytecode form.
* An {@link FieldVisitor} that generates Java fields in bytecode form.
*
* @author Eric Bruneton
*/
@@ -80,6 +80,17 @@ final class FieldWriter extends FieldVisitor {
*/
private AnnotationWriter ianns;
/**
* The runtime visible type annotations of this field. May be <tt>null</tt>.
*/
private AnnotationWriter tanns;
/**
* The runtime invisible type annotations of this field. May be
* <tt>null</tt>.
*/
private AnnotationWriter itanns;
/**
* The non standard attributes of this field. May be <tt>null</tt>.
*/
@@ -90,7 +101,7 @@ final class FieldWriter extends FieldVisitor {
// ------------------------------------------------------------------------
/**
* Constructs a new {@link org.objectweb.asm.FieldWriter}.
* Constructs a new {@link FieldWriter}.
*
* @param cw
* the class writer to which this field must be added.
@@ -107,7 +118,7 @@ final class FieldWriter extends FieldVisitor {
*/
FieldWriter(final ClassWriter cw, final int access, final String name,
final String desc, final String signature, final Object value) {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
if (cw.firstField == null) {
cw.firstField = this;
} else {
@@ -150,6 +161,29 @@ final class FieldWriter extends FieldVisitor {
return aw;
}
@Override
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = tanns;
tanns = aw;
} else {
aw.next = itanns;
itanns = aw;
}
return aw;
}
@Override
public void visitAttribute(final Attribute attr) {
attr.next = attrs;
@@ -198,6 +232,14 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
if (ClassReader.ANNOTATIONS && tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize();
}
if (ClassReader.ANNOTATIONS && itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize();
}
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
@@ -237,6 +279,12 @@ final class FieldWriter extends FieldVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && tanns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && itanns != null) {
++attributeCount;
}
if (attrs != null) {
attributeCount += attrs.getCount();
}
@@ -266,6 +314,14 @@ final class FieldWriter extends FieldVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (ClassReader.ANNOTATIONS && tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (ClassReader.ANNOTATIONS && itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
+2 -2
View File
@@ -1278,8 +1278,8 @@ final class Frame {
* @param frame
* the basic block whose input frame must be updated.
* @param edge
* the kind of the {@link org.objectweb.asm.Edge} between this label and 'label'.
* See {@link org.objectweb.asm.Edge#info}.
* the kind of the {@link Edge} between this label and 'label'.
* See {@link Edge#info}.
* @return <tt>true</tt> if the input frame of the given label has been
* changed by this operation.
*/
+8 -5
View File
@@ -49,7 +49,8 @@ public final class Handle {
final int tag;
/**
* The internal name of the field or method designed by this handle.
* The internal name of the class that owns the field or method designated
* by this handle.
*/
final String owner;
@@ -76,8 +77,8 @@ public final class Handle {
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner
* the internal name of the field or method designed by this
* handle.
* the internal name of the class that owns the field or method
* designated by this handle.
* @param name
* the name of the field or method designated by this handle.
* @param desc
@@ -106,9 +107,11 @@ public final class Handle {
}
/**
* Returns the internal name of the field or method designed by this handle.
* Returns the internal name of the class that owns the field or method
* designated by this handle.
*
* @return the internal name of the field or method designed by this handle.
* @return the internal name of the class that owns the field or method
* designated by this handle.
*/
public String getOwner() {
return owner;
+15 -15
View File
@@ -31,7 +31,7 @@ package org.objectweb.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link org.objectweb.asm.ClassWriter} class.
* methods in the {@link ClassWriter} class.
*
* @author Eric Bruneton
*/
@@ -45,24 +45,24 @@ final class Item {
/**
* Type of this constant pool item. A single class is used to represent all
* constant pool item types, in order to minimize the bytecode size of this
* package. The value of this field is one of {@link org.objectweb.asm.ClassWriter#INT},
* {@link org.objectweb.asm.ClassWriter#LONG}, {@link org.objectweb.asm.ClassWriter#FLOAT},
* {@link org.objectweb.asm.ClassWriter#DOUBLE}, {@link org.objectweb.asm.ClassWriter#UTF8},
* {@link org.objectweb.asm.ClassWriter#STR}, {@link org.objectweb.asm.ClassWriter#CLASS},
* {@link org.objectweb.asm.ClassWriter#NAME_TYPE}, {@link org.objectweb.asm.ClassWriter#FIELD},
* {@link org.objectweb.asm.ClassWriter#METH}, {@link org.objectweb.asm.ClassWriter#IMETH},
* {@link org.objectweb.asm.ClassWriter#MTYPE}, {@link org.objectweb.asm.ClassWriter#INDY}.
* package. The value of this field is one of {@link ClassWriter#INT},
* {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
* {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
*
* MethodHandle constant 9 variations are stored using a range of 9 values
* from {@link org.objectweb.asm.ClassWriter#HANDLE_BASE} + 1 to
* {@link org.objectweb.asm.ClassWriter#HANDLE_BASE} + 9.
* from {@link ClassWriter#HANDLE_BASE} + 1 to
* {@link ClassWriter#HANDLE_BASE} + 9.
*
* Special Item types are used for Items that are stored in the ClassWriter
* {@link org.objectweb.asm.ClassWriter#typeTable}, instead of the constant pool, in order to
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
* avoid clashes with normal constant pool items in the ClassWriter constant
* pool's hash table. These special item types are
* {@link org.objectweb.asm.ClassWriter#TYPE_NORMAL}, {@link org.objectweb.asm.ClassWriter#TYPE_UNINIT} and
* {@link org.objectweb.asm.ClassWriter#TYPE_MERGED}.
* {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
* {@link ClassWriter#TYPE_MERGED}.
*/
int type;
@@ -106,13 +106,13 @@ final class Item {
Item next;
/**
* Constructs an uninitialized {@link org.objectweb.asm.Item}.
* Constructs an uninitialized {@link Item}.
*/
Item() {
}
/**
* Constructs an uninitialized {@link org.objectweb.asm.Item} for constant pool element at
* Constructs an uninitialized {@link Item} for constant pool element at
* given position.
*
* @param index
+5 -5
View File
@@ -214,7 +214,7 @@ public class Label {
/**
* Information about the input and output stack map frames of this basic
* block. This field is only used when {@link org.objectweb.asm.ClassWriter#COMPUTE_FRAMES}
* block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
* option is used.
*/
Frame frame;
@@ -222,7 +222,7 @@ public class Label {
/**
* The successor of this label, in the order they are visited. This linked
* list does not include labels used for debug info only. If
* {@link org.objectweb.asm.ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
* {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
* does not contain successive labels that denote the same bytecode position
* (in this case only the first label appears in this list).
*/
@@ -230,8 +230,8 @@ public class Label {
/**
* The successors of this node in the control flow graph. These successors
* are stored in a linked list of {@link org.objectweb.asm.Edge Edge} objects, linked to each
* other by their {@link org.objectweb.asm.Edge#next} field.
* are stored in a linked list of {@link Edge Edge} objects, linked to each
* other by their {@link Edge#next} field.
*/
Edge successors;
@@ -262,7 +262,7 @@ public class Label {
/**
* Returns the offset corresponding to this label. This offset is computed
* from the start of the method's bytecode. <i>This method is intended for
* {@link org.objectweb.asm.Attribute} sub classes, and is normally not needed by class
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @return the offset corresponding to this label.
@@ -31,18 +31,24 @@ package org.objectweb.asm;
/**
* A visitor to visit a Java method. The methods of this class must be called in
* the following order: [ <tt>visitAnnotationDefault</tt> ] (
* <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
* <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
* <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> |
* <tt>visitTryCatchBlock</tt> | <tt>visitLocalVariable</tt> |
* the following order: ( <tt>visitParameter</tt> )* [
* <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [
* <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> |
* <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> |
* <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
* <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
* <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
* addition, the <tt>visit</tt><i>X</i>Insn</tt> and <tt>visitLabel</tt> methods
* must be called in the sequential order of the bytecode instructions of the
* visited code, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
* labels passed as arguments have been visited, and the
* <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> methods must be
* called <i>after</i> the labels passed as arguments have been visited.
* addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must
* be called in the sequential order of the bytecode instructions of the visited
* code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
* instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
* labels passed as arguments have been visited,
* <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
* corresponding try catch block has been visited, and the
* <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
* <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
* passed as arguments have been visited.
*
* @author Eric Bruneton
*/
@@ -50,7 +56,7 @@ public abstract class MethodVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4}.
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -61,28 +67,28 @@ public abstract class MethodVisitor {
protected MethodVisitor mv;
/**
* Constructs a new {@link org.objectweb.asm.MethodVisitor}.
* Constructs a new {@link MethodVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link org.objectweb.asm.MethodVisitor}.
* Constructs a new {@link MethodVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4}.
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
* @param mv
* the method visitor to which this visitor must delegate method
* calls. May be null.
*/
public MethodVisitor(final int api, final MethodVisitor mv) {
if (api != Opcodes.ASM4) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
}
this.api = api;
@@ -90,9 +96,28 @@ public abstract class MethodVisitor {
}
// -------------------------------------------------------------------------
// Annotations and non standard attributes
// Parameters, annotations and non standard attributes
// -------------------------------------------------------------------------
/**
* Visits a parameter of this method.
*
* @param name
* parameter name or null if none is provided.
* @param access
* the parameter's access flags, only <tt>ACC_FINAL</tt>,
* <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
* allowed (see {@link Opcodes}).
*/
public void visitParameter(String name, int access) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (mv != null) {
mv.visitParameter(name, access);
}
}
/**
* Visits the default value of this annotation interface method.
*
@@ -127,6 +152,42 @@ public abstract class MethodVisitor {
return null;
}
/**
* Visits an annotation on a type in the method signature.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
* METHOD_TYPE_PARAMETER},
* {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
* METHOD_TYPE_PARAMETER_BOUND},
* {@link TypeReference#METHOD_RETURN METHOD_RETURN},
* {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
* {@link TypeReference#METHOD_FORMAL_PARAMETER
* METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
* THROWS}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (mv != null) {
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits an annotation of a parameter this method.
*
@@ -201,9 +262,11 @@ public abstract class MethodVisitor {
* <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
* same as the locals in the previous frame, except that the last 1-3 locals
* are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
* <li>{@link Opcodes#F_FULL} representing complete frame data.</li></li>
* <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
* </ul>
* </ul> <br>
* </li>
* </ul>
* <br>
* In both cases the first frame, corresponding to the method's parameters
* and access flags, is implicit and must not be visited. Also, it is
* illegal to visit two or more frames for the same code location (i.e., at
@@ -395,7 +458,7 @@ public abstract class MethodVisitor {
* @param bsmArgs
* the bootstrap method constant arguments. Each argument must be
* an {@link Integer}, {@link Float}, {@link Long},
* {@link Double}, {@link String}, {@link Type} or {@link org.objectweb.asm.Handle}
* {@link Double}, {@link String}, {@link Type} or {@link Handle}
* value. This method is allowed to modify the content of the
* array so a caller should expect that this array may change.
*/
@@ -431,7 +494,7 @@ public abstract class MethodVisitor {
* just after it.
*
* @param label
* a {@link org.objectweb.asm.Label Label} object.
* a {@link Label Label} object.
*/
public void visitLabel(Label label) {
if (mv != null) {
@@ -484,7 +547,7 @@ public abstract class MethodVisitor {
* {@link Double}, a {@link String}, a {@link Type} of OBJECT or
* ARRAY sort for <tt>.class</tt> constants, for classes whose
* version is 49.0, a {@link Type} of METHOD sort or a
* {@link org.objectweb.asm.Handle} for MethodType and MethodHandle constants, for
* {@link Handle} for MethodType and MethodHandle constants, for
* classes whose version is 51.0.
*/
public void visitLdcInsn(Object cst) {
@@ -558,6 +621,48 @@ public abstract class MethodVisitor {
}
}
/**
* Visits an annotation on an instruction. This method must be called just
* <i>after</i> the annotated instruction. It can be called several times
* for the same instruction.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
* {@link TypeReference#NEW NEW},
* {@link TypeReference#CONSTRUCTOR_REFERENCE
* CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
* METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
* {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitInsnAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (mv != null) {
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
// -------------------------------------------------------------------------
// Exceptions table entries, debug information, max stack and max locals
// -------------------------------------------------------------------------
@@ -586,6 +691,38 @@ public abstract class MethodVisitor {
}
}
/**
* Visits an annotation on an exception handler type. This method must be
* called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
* exception handler. It can be called several times for the same exception
* handler.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#EXCEPTION_PARAMETER
* EXCEPTION_PARAMETER}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (mv != null) {
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
}
return null;
}
/**
* Visits a local variable declaration.
*
@@ -616,6 +753,48 @@ public abstract class MethodVisitor {
}
}
/**
* Visits an annotation on a local variable type.
*
* @param typeRef
* a reference to the annotated type. The sort of this type
* reference must be {@link TypeReference#LOCAL_VARIABLE
* LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
* RESOURCE_VARIABLE}. 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.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
TypePath typePath, Label[] start, Label[] end, int[] index,
String desc, boolean visible) {
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
if (mv != null) {
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
end, index, desc, visible);
}
return null;
}
/**
* Visits a line number declaration.
*
+239 -11
View File
@@ -30,7 +30,7 @@
package org.objectweb.asm;
/**
* A {@link org.objectweb.asm.MethodVisitor} that generates methods in bytecode form. Each visit
* A {@link MethodVisitor} that generates methods in bytecode form. Each visit
* method of this class appends the bytecode corresponding to the visited
* instruction to a byte vector, in the order these methods are called.
*
@@ -191,6 +191,18 @@ class MethodWriter extends MethodVisitor {
*/
private AnnotationWriter ianns;
/**
* The runtime visible type annotations of this method. May be <tt>null</tt>
* .
*/
private AnnotationWriter tanns;
/**
* The runtime invisible type annotations of this method. May be
* <tt>null</tt>.
*/
private AnnotationWriter itanns;
/**
* The runtime visible parameter annotations of this method. May be
* <tt>null</tt>.
@@ -263,7 +275,7 @@ class MethodWriter extends MethodVisitor {
* local variables start at index 3 and are followed by the operand stack
* values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
* nStack, frame[3] = nLocal. All types are encoded as integers, with the
* same format as the one used in {@link org.objectweb.asm.Label}, but limited to BASE types.
* same format as the one used in {@link Label}, but limited to BASE types.
*/
private int[] frame;
@@ -282,6 +294,16 @@ class MethodWriter extends MethodVisitor {
*/
private Handler lastHandler;
/**
* Number of entries in the MethodParameters attribute.
*/
private int methodParametersCount;
/**
* The MethodParameters attribute.
*/
private ByteVector methodParameters;
/**
* Number of entries in the LocalVariableTable attribute.
*/
@@ -312,6 +334,21 @@ class MethodWriter extends MethodVisitor {
*/
private ByteVector lineNumber;
/**
* The start offset of the last visited instruction.
*/
private int lastCodeOffset;
/**
* The runtime visible type annotations of the code. May be <tt>null</tt>.
*/
private AnnotationWriter ctanns;
/**
* The runtime invisible type annotations of the code. May be <tt>null</tt>.
*/
private AnnotationWriter ictanns;
/**
* The non standard attributes of the method's code.
*/
@@ -351,8 +388,8 @@ class MethodWriter extends MethodVisitor {
/**
* A list of labels. This list is the list of basic blocks in the method,
* i.e. a list of Label objects linked to each other by their
* {@link org.objectweb.asm.Label#successor} field, in the order they are visited by
* {@link org.objectweb.asm.MethodVisitor#visitLabel}, and starting with the first basic
* {@link Label#successor} field, in the order they are visited by
* {@link MethodVisitor#visitLabel}, and starting with the first basic
* block.
*/
private Label labels;
@@ -371,7 +408,7 @@ class MethodWriter extends MethodVisitor {
* The (relative) stack size after the last visited instruction. This size
* is relative to the beginning of the current basic block, i.e., the true
* stack size after the last visited instruction is equal to the
* {@link org.objectweb.asm.Label#inputStackTop beginStackSize} of the current basic block
* {@link Label#inputStackTop beginStackSize} of the current basic block
* plus <tt>stackSize</tt>.
*/
private int stackSize;
@@ -380,7 +417,7 @@ class MethodWriter extends MethodVisitor {
* The (relative) maximum stack size after the last visited instruction.
* This size is relative to the beginning of the current basic block, i.e.,
* the true maximum stack size after the last visited instruction is equal
* to the {@link org.objectweb.asm.Label#inputStackTop beginStackSize} of the current basic
* to the {@link Label#inputStackTop beginStackSize} of the current basic
* block plus <tt>stackSize</tt>.
*/
private int maxStackSize;
@@ -390,7 +427,7 @@ class MethodWriter extends MethodVisitor {
// ------------------------------------------------------------------------
/**
* Constructs a new {@link org.objectweb.asm.MethodWriter}.
* Constructs a new {@link MethodWriter}.
*
* @param cw
* the class writer in which the method must be added.
@@ -416,7 +453,7 @@ class MethodWriter extends MethodVisitor {
final String desc, final String signature,
final String[] exceptions, final boolean computeMaxs,
final boolean computeFrames) {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
if (cw.firstMethod == null) {
cw.firstMethod = this;
} else {
@@ -461,6 +498,16 @@ class MethodWriter extends MethodVisitor {
// Implementation of the MethodVisitor abstract class
// ------------------------------------------------------------------------
@Override
public void visitParameter(String name, int access) {
if (methodParameters == null) {
methodParameters = new ByteVector();
}
++methodParametersCount;
methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
.putShort(access);
}
@Override
public AnnotationVisitor visitAnnotationDefault() {
if (!ClassReader.ANNOTATIONS) {
@@ -490,6 +537,29 @@ class MethodWriter extends MethodVisitor {
return aw;
}
@Override
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = tanns;
tanns = aw;
} else {
aw.next = itanns;
itanns = aw;
}
return aw;
}
@Override
public AnnotationVisitor visitParameterAnnotation(final int parameter,
final String desc, final boolean visible) {
@@ -642,6 +712,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitInsn(final int opcode) {
lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
code.putByte(opcode);
// update currentBlock
@@ -667,6 +738,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIntInsn(final int opcode, final int operand) {
lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -691,6 +763,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitVarInsn(final int opcode, final int var) {
lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -749,6 +822,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitTypeInsn(final int opcode, final String type) {
lastCodeOffset = code.length;
Item i = cw.newClassItem(type);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -771,6 +845,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitFieldInsn(final int opcode, final String owner,
final String name, final String desc) {
lastCodeOffset = code.length;
Item i = cw.newFieldItem(owner, name, desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -809,6 +884,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMethodInsn(final int opcode, final String owner,
final String name, final String desc) {
lastCodeOffset = code.length;
boolean itf = opcode == Opcodes.INVOKEINTERFACE;
Item i = cw.newMethodItem(owner, name, desc, itf);
int argSize = i.intVal;
@@ -861,6 +937,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitInvokeDynamicInsn(final String name, final String desc,
final Handle bsm, final Object... bsmArgs) {
lastCodeOffset = code.length;
Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
@@ -900,6 +977,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitJumpInsn(final int opcode, final Label label) {
lastCodeOffset = code.length;
Label nextInsn = null;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1045,6 +1123,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitLdcInsn(final Object cst) {
lastCodeOffset = code.length;
Item i = cw.newConstItem(cst);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1078,6 +1157,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIincInsn(final int var, final int increment) {
lastCodeOffset = code.length;
if (currentBlock != null) {
if (compute == FRAMES) {
currentBlock.frame.execute(Opcodes.IINC, var, null, null);
@@ -1102,6 +1182,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitTableSwitchInsn(final int min, final int max,
final Label dflt, final Label... labels) {
lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.TABLESWITCH);
@@ -1118,6 +1199,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
final Label[] labels) {
lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.LOOKUPSWITCH);
@@ -1160,6 +1242,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMultiANewArrayInsn(final String desc, final int dims) {
lastCodeOffset = code.length;
Item i = cw.newClassItem(desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1175,6 +1258,30 @@ class MethodWriter extends MethodVisitor {
code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
}
@Override
public AnnotationVisitor visitInsnAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = ctanns;
ctanns = aw;
} else {
aw.next = ictanns;
ictanns = aw;
}
return aw;
}
@Override
public void visitTryCatchBlock(final Label start, final Label end,
final Label handler, final String type) {
@@ -1193,6 +1300,29 @@ class MethodWriter extends MethodVisitor {
lastHandler = h;
}
@Override
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv);
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = ctanns;
ctanns = aw;
} else {
aw.next = ictanns;
ictanns = aw;
}
return aw;
}
@Override
public void visitLocalVariable(final String name, final String desc,
final String signature, final Label start, final Label end,
@@ -1225,6 +1355,41 @@ class MethodWriter extends MethodVisitor {
}
}
@Override
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
TypePath typePath, Label[] start, Label[] end, int[] index,
String desc, boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write target_type and target_info
bv.putByte(typeRef >>> 24).putShort(start.length);
for (int i = 0; i < start.length; ++i) {
bv.putShort(start[i].position)
.putShort(end[i].position - start[i].position)
.putShort(index[i]);
}
if (typePath == null) {
bv.putByte(0);
} else {
int length = typePath.b[typePath.offset] * 2 + 1;
bv.putByteArray(typePath.b, typePath.offset, length);
}
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
bv.length - 2);
if (visible) {
aw.next = ctanns;
ctanns = aw;
} else {
aw.next = ictanns;
ictanns = aw;
}
return aw;
}
@Override
public void visitLineNumber(final int line, final Label start) {
if (lineNumber == null) {
@@ -1768,7 +1933,7 @@ class MethodWriter extends MethodVisitor {
/**
* Writes some types of the current frame {@link #frame} into the
* StackMapTableAttribute. This method converts types from the format used
* in {@link org.objectweb.asm.Label} to the format used in StackMapTable attributes. In
* in {@link Label} to the format used in StackMapTable attributes. In
* particular, it converts type table indexes to constant pool indexes.
*
* @param start
@@ -1890,6 +2055,14 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(zip ? "StackMapTable" : "StackMap");
size += 8 + stackMap.length;
}
if (ClassReader.ANNOTATIONS && ctanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + ctanns.getSize();
}
if (ClassReader.ANNOTATIONS && ictanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + ictanns.getSize();
}
if (cattrs != null) {
size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
@@ -1915,6 +2088,10 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(signature);
size += 8;
}
if (methodParameters != null) {
cw.newUTF8("MethodParameters");
size += 7 + methodParameters.length;
}
if (ClassReader.ANNOTATIONS && annd != null) {
cw.newUTF8("AnnotationDefault");
size += 6 + annd.length;
@@ -1927,6 +2104,14 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
if (ClassReader.ANNOTATIONS && tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize();
}
if (ClassReader.ANNOTATIONS && itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize();
}
if (ClassReader.ANNOTATIONS && panns != null) {
cw.newUTF8("RuntimeVisibleParameterAnnotations");
size += 7 + 2 * (panns.length - synthetics);
@@ -1983,6 +2168,9 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.SIGNATURES && signature != null) {
++attributeCount;
}
if (methodParameters != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && annd != null) {
++attributeCount;
}
@@ -1992,6 +2180,12 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && tanns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && itanns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && panns != null) {
++attributeCount;
}
@@ -2016,6 +2210,12 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
size += 8 + stackMap.length;
}
if (ClassReader.ANNOTATIONS && ctanns != null) {
size += 8 + ctanns.getSize();
}
if (ClassReader.ANNOTATIONS && ictanns != null) {
size += 8 + ictanns.getSize();
}
if (cattrs != null) {
size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
@@ -2045,6 +2245,12 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && ctanns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && ictanns != null) {
++attributeCount;
}
if (cattrs != null) {
attributeCount += cattrs.getCount();
}
@@ -2070,6 +2276,14 @@ class MethodWriter extends MethodVisitor {
out.putInt(stackMap.length + 2).putShort(frameCount);
out.putByteArray(stackMap.data, 0, stackMap.length);
}
if (ClassReader.ANNOTATIONS && ctanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
ctanns.put(out);
}
if (ClassReader.ANNOTATIONS && ictanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
ictanns.put(out);
}
if (cattrs != null) {
cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
}
@@ -2095,6 +2309,12 @@ class MethodWriter extends MethodVisitor {
out.putShort(cw.newUTF8("Signature")).putInt(2)
.putShort(cw.newUTF8(signature));
}
if (methodParameters != null) {
out.putShort(cw.newUTF8("MethodParameters"));
out.putInt(methodParameters.length + 1).putByte(
methodParametersCount);
out.putByteArray(methodParameters.data, 0, methodParameters.length);
}
if (ClassReader.ANNOTATIONS && annd != null) {
out.putShort(cw.newUTF8("AnnotationDefault"));
out.putInt(annd.length);
@@ -2108,6 +2328,14 @@ class MethodWriter extends MethodVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (ClassReader.ANNOTATIONS && tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (ClassReader.ANNOTATIONS && itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (ClassReader.ANNOTATIONS && panns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
AnnotationWriter.put(panns, synthetics, out);
@@ -2127,7 +2355,7 @@ class MethodWriter extends MethodVisitor {
/**
* Resizes and replaces the temporary instructions inserted by
* {@link org.objectweb.asm.Label#resolve} for wide forward jumps, while keeping jump offsets
* {@link Label#resolve} for wide forward jumps, while keeping jump offsets
* and instruction addresses consistent. This may require to resize other
* existing instructions, or even to introduce new instructions: for
* example, increasing the size of an instruction by 2 at the middle of a
@@ -2138,7 +2366,7 @@ class MethodWriter extends MethodVisitor {
* by this method.
* <p>
* <i>This method must be called after all the method that is being built
* has been visited</i>. In particular, the {@link org.objectweb.asm.Label Label} objects used
* has been visited</i>. In particular, the {@link Label Label} objects used
* to construct the method are no longer valid after this method has been
* called.
*/
+6 -3
View File
@@ -46,6 +46,7 @@ public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0;
int ASM5 = 5 << 16 | 0 << 8 | 0;
// versions
@@ -56,6 +57,7 @@ public interface Opcodes {
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
// access flags
@@ -63,7 +65,7 @@ public interface Opcodes {
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_VOLATILE = 0x0040; // field
@@ -74,9 +76,10 @@ public interface Opcodes {
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter
// ASM specific pseudo access flags
@@ -108,7 +111,7 @@ public interface Opcodes {
// stack map frame types
/**
* Represents an expanded frame. See {@link org.objectweb.asm.ClassReader#EXPAND_FRAMES}.
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
*/
int F_NEW = -1;
+10 -9
View File
@@ -294,7 +294,7 @@ public class Type {
* Returns the Java method type corresponding to the given constructor.
*
* @param c
* a {@link java.lang.reflect.Constructor Constructor} object.
* a {@link Constructor Constructor} object.
* @return the Java method type corresponding to the given constructor.
*/
public static Type getType(final Constructor<?> c) {
@@ -305,7 +305,7 @@ public class Type {
* Returns the Java method type corresponding to the given method.
*
* @param m
* a {@link java.lang.reflect.Method Method} object.
* a {@link Method Method} object.
* @return the Java method type corresponding to the given method.
*/
public static Type getType(final Method m) {
@@ -401,8 +401,8 @@ public class Type {
* @return the size of the arguments of the method (plus one for the
* implicit this argument), argSize, and the size of its return
* value, retSize, packed into a single int i =
* <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
* <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
* <tt>(argSize &lt;&lt; 2) | retSize</tt> (argSize is therefore equal to
* <tt>i &gt;&gt; 2</tt>, and retSize to <tt>i &amp; 0x03</tt>).
*/
public static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
@@ -606,9 +606,10 @@ public class Type {
*
* @return the size of the arguments (plus one for the implicit this
* argument), argSize, and the size of the return value, retSize,
* packed into a single int i = <tt>(argSize << 2) | retSize</tt>
* (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
* <tt>i & 0x03</tt>).
* packed into a single
* int i = <tt>(argSize &lt;&lt; 2) | retSize</tt>
* (argSize is therefore equal to <tt>i &gt;&gt; 2</tt>,
* and retSize to <tt>i &amp; 0x03</tt>).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@@ -708,7 +709,7 @@ public class Type {
* Returns the descriptor corresponding to the given constructor.
*
* @param c
* a {@link java.lang.reflect.Constructor Constructor} object.
* a {@link Constructor Constructor} object.
* @return the descriptor of the given constructor.
*/
public static String getConstructorDescriptor(final Constructor<?> c) {
@@ -725,7 +726,7 @@ public class Type {
* Returns the descriptor corresponding to the given method.
*
* @param m
* a {@link java.lang.reflect.Method Method} object.
* a {@link Method Method} object.
* @return the descriptor of the given method.
*/
public static String getMethodDescriptor(final Method m) {
@@ -0,0 +1,193 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2013 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;
/**
* The path to a type argument, wildcard bound, array element type, or static
* inner type within an enclosing type.
*
* @author Eric Bruneton
*/
public class TypePath {
/**
* A type path step that steps into the element type of an array type. See
* {@link #getStep getStep}.
*/
public final static int ARRAY_ELEMENT = 0;
/**
* A type path step that steps into the nested type of a class type. See
* {@link #getStep getStep}.
*/
public final static int INNER_TYPE = 1;
/**
* A type path step that steps into the bound of a wildcard type. See
* {@link #getStep getStep}.
*/
public final static int WILDCARD_BOUND = 2;
/**
* A type path step that steps into a type argument of a generic type. See
* {@link #getStep getStep}.
*/
public final static int TYPE_ARGUMENT = 3;
/**
* The byte array where the path is stored, in Java class file format.
*/
byte[] b;
/**
* The offset of the first byte of the type path in 'b'.
*/
int offset;
/**
* Creates a new type path.
*
* @param b
* the byte array containing the type path in Java class file
* format.
* @param offset
* the offset of the first byte of the type path in 'b'.
*/
TypePath(byte[] b, int offset) {
this.b = b;
this.offset = offset;
}
/**
* Returns the length of this path.
*
* @return the length of this path.
*/
public int getLength() {
return b[offset];
}
/**
* Returns the value of the given step of this path.
*
* @param index
* an index between 0 and {@link #getLength()}, exclusive.
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
* INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*/
public int getStep(int index) {
return b[offset + 2 * index + 1];
}
/**
* Returns the index of the type argument that the given step is stepping
* into. This method should only be used for steps whose value is
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*
* @param index
* an index between 0 and {@link #getLength()}, exclusive.
* @return the index of the type argument that the given step is stepping
* into.
*/
public int getStepArgument(int index) {
return b[offset + 2 * index + 2];
}
/**
* Converts a type path in string form, in the format used by
* {@link #toString()}, into a TypePath object.
*
* @param typePath
* a type path in string form, in the format used by
* {@link #toString()}. May be null or empty.
* @return the corresponding TypePath object, or null if the path is empty.
*/
public static TypePath fromString(final String typePath) {
if (typePath == null || typePath.length() == 0) {
return null;
}
int n = typePath.length();
ByteVector out = new ByteVector(n);
out.putByte(0);
for (int i = 0; i < n;) {
char c = typePath.charAt(i++);
if (c == '[') {
out.put11(ARRAY_ELEMENT, 0);
} else if (c == '.') {
out.put11(INNER_TYPE, 0);
} else if (c == '*') {
out.put11(WILDCARD_BOUND, 0);
} else if (c >= '0' && c <= '9') {
int typeArg = c - '0';
while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
typeArg = typeArg * 10 + c - '0';
i += 1;
}
out.put11(TYPE_ARGUMENT, typeArg);
}
}
out.data[0] = (byte) (out.length / 2);
return new TypePath(out.data, 0);
}
/**
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT
* ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
* INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
* with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
* argument index in decimal form.
*/
@Override
public String toString() {
int length = getLength();
StringBuilder result = new StringBuilder(length * 2);
for (int i = 0; i < length; ++i) {
switch (getStep(i)) {
case ARRAY_ELEMENT:
result.append('[');
break;
case INNER_TYPE:
result.append('.');
break;
case WILDCARD_BOUND:
result.append('*');
break;
case TYPE_ARGUMENT:
result.append(getStepArgument(i));
break;
default:
result.append('_');
}
}
return result.toString();
}
}
@@ -0,0 +1,452 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2013 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;
/**
* A reference to a type appearing in a class, field or method declaration, or
* on an instruction. Such a reference designates the part of the class where
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
* declaration, etc).
*
* @author Eric Bruneton
*/
public class TypeReference {
/**
* The sort of type references that target a type parameter of a generic
* class. See {@link #getSort getSort}.
*/
public final static int CLASS_TYPE_PARAMETER = 0x00;
/**
* The sort of type references that target a type parameter of a generic
* method. See {@link #getSort getSort}.
*/
public final static int METHOD_TYPE_PARAMETER = 0x01;
/**
* The sort of type references that target the super class of a class or one
* of the interfaces it implements. See {@link #getSort getSort}.
*/
public final static int CLASS_EXTENDS = 0x10;
/**
* The sort of type references that target a bound of a type parameter of a
* generic class. See {@link #getSort getSort}.
*/
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
/**
* The sort of type references that target a bound of a type parameter of a
* generic method. See {@link #getSort getSort}.
*/
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
/**
* The sort of type references that target the type of a field. See
* {@link #getSort getSort}.
*/
public final static int FIELD = 0x13;
/**
* The sort of type references that target the return type of a method. See
* {@link #getSort getSort}.
*/
public final static int METHOD_RETURN = 0x14;
/**
* The sort of type references that target the receiver type of a method.
* See {@link #getSort getSort}.
*/
public final static int METHOD_RECEIVER = 0x15;
/**
* The sort of type references that target the type of a formal parameter of
* a method. See {@link #getSort getSort}.
*/
public final static int METHOD_FORMAL_PARAMETER = 0x16;
/**
* The sort of type references that target the type of an exception declared
* in the throws clause of a method. See {@link #getSort getSort}.
*/
public final static int THROWS = 0x17;
/**
* The sort of type references that target the type of a local variable in a
* method. See {@link #getSort getSort}.
*/
public final static int LOCAL_VARIABLE = 0x40;
/**
* The sort of type references that target the type of a resource variable
* in a method. See {@link #getSort getSort}.
*/
public final static int RESOURCE_VARIABLE = 0x41;
/**
* The sort of type references that target the type of the exception of a
* 'catch' clause in a method. See {@link #getSort getSort}.
*/
public final static int EXCEPTION_PARAMETER = 0x42;
/**
* The sort of type references that target the type declared in an
* 'instanceof' instruction. See {@link #getSort getSort}.
*/
public final static int INSTANCEOF = 0x43;
/**
* The sort of type references that target the type of the object created by
* a 'new' instruction. See {@link #getSort getSort}.
*/
public final static int NEW = 0x44;
/**
* The sort of type references that target the receiver type of a
* constructor reference. See {@link #getSort getSort}.
*/
public final static int CONSTRUCTOR_REFERENCE = 0x45;
/**
* The sort of type references that target the receiver type of a method
* reference. See {@link #getSort getSort}.
*/
public final static int METHOD_REFERENCE = 0x46;
/**
* The sort of type references that target the type declared in an explicit
* or implicit cast instruction. See {@link #getSort getSort}.
*/
public final static int CAST = 0x47;
/**
* The sort of type references that target a type parameter of a generic
* constructor in a constructor call. See {@link #getSort getSort}.
*/
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
/**
* The sort of type references that target a type parameter of a generic
* method in a method call. See {@link #getSort getSort}.
*/
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
/**
* The sort of type references that target a type parameter of a generic
* constructor in a constructor reference. See {@link #getSort getSort}.
*/
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
/**
* The sort of type references that target a type parameter of a generic
* method in a method reference. See {@link #getSort getSort}.
*/
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
/**
* The type reference value in Java class file format.
*/
private int value;
/**
* Creates a new TypeReference.
*
* @param typeRef
* the int encoded value of the type reference, as received in a
* visit method related to type annotations, like
* visitTypeAnnotation.
*/
public TypeReference(int typeRef) {
this.value = typeRef;
}
/**
* Returns a type reference of the given sort.
*
* @param sort
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
* @return a type reference of the given sort.
*/
public static TypeReference newTypeReference(int sort) {
return new TypeReference(sort << 24);
}
/**
* Returns a reference to a type parameter of a generic class or method.
*
* @param sort
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
* @param paramIndex
* the type parameter index.
* @return a reference to the given generic class or method type parameter.
*/
public static TypeReference newTypeParameterReference(int sort,
int paramIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16));
}
/**
* Returns a reference to a type parameter bound of a generic class or
* method.
*
* @param sort
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
* @param paramIndex
* the type parameter index.
* @param boundIndex
* the type bound index within the above type parameters.
* @return a reference to the given generic class or method type parameter
* bound.
*/
public static TypeReference newTypeParameterBoundReference(int sort,
int paramIndex, int boundIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16)
| (boundIndex << 8));
}
/**
* Returns a reference to the super class or to an interface of the
* 'implements' clause of a class.
*
* @param itfIndex
* the index of an interface in the 'implements' clause of a
* class, or -1 to reference the super class of the class.
* @return a reference to the given super type of a class.
*/
public static TypeReference newSuperTypeReference(int itfIndex) {
itfIndex &= 0xFFFF;
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
}
/**
* Returns a reference to the type of a formal parameter of a method.
*
* @param paramIndex
* the formal parameter index.
*
* @return a reference to the type of the given method formal parameter.
*/
public static TypeReference newFormalParameterReference(int paramIndex) {
return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
| (paramIndex << 16));
}
/**
* Returns a reference to the type of an exception, in a 'throws' clause of
* a method.
*
* @param exceptionIndex
* the index of an exception in a 'throws' clause of a method.
*
* @return a reference to the type of the given exception.
*/
public static TypeReference newExceptionReference(int exceptionIndex) {
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
}
/**
* Returns a reference to the type of the exception declared in a 'catch'
* clause of a method.
*
* @param tryCatchBlockIndex
* the index of a try catch block (using the order in which they
* are visited with visitTryCatchBlock).
*
* @return a reference to the type of the given exception.
*/
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
return new TypeReference((EXCEPTION_PARAMETER << 24)
| (tryCatchBlockIndex << 8));
}
/**
* Returns a reference to the type of a type argument in a constructor or
* method call or reference.
*
* @param sort
* {@link #CAST CAST},
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
* @param argIndex
* the type argument index.
*
* @return a reference to the type of the given type argument.
*/
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
return new TypeReference((sort << 24) | argIndex);
}
/**
* Returns the sort of this type reference.
*
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
* {@link #CLASS_EXTENDS CLASS_EXTENDS},
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
* {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
* {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
* {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
* METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
* METHOD_REFERENCE_TYPE_ARGUMENT}.
*/
public int getSort() {
return value >>> 24;
}
/**
* Returns the index of the type parameter referenced by this type
* reference. This method must only be used for type references whose sort
* is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter index.
*/
public int getTypeParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the type parameter bound, within the type parameter
* {@link #getTypeParameterIndex}, referenced by this type reference. This
* method must only be used for type references whose sort is
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
*
* @return a type parameter bound index.
*/
public int getTypeParameterBoundIndex() {
return (value & 0x0000FF00) >> 8;
}
/**
* Returns the index of the "super type" of a class that is referenced by
* this type reference. This method must only be used for type references
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
*
* @return the index of an interface in the 'implements' clause of a class,
* or -1 if this type reference references the type of the super
* class.
*/
public int getSuperTypeIndex() {
return (short) ((value & 0x00FFFF00) >> 8);
}
/**
* Returns the index of the formal parameter whose type is referenced by
* this type reference. This method must only be used for type references
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
*
* @return a formal parameter index.
*/
public int getFormalParameterIndex() {
return (value & 0x00FF0000) >> 16;
}
/**
* Returns the index of the exception, in a 'throws' clause of a method,
* whose type is referenced by this type reference. This method must only be
* used for type references whose sort is {@link #THROWS THROWS}.
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getExceptionIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the try catch block (using the order in which they
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by
* this type reference. This method must only be used for type references
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
*
* @return the index of an exception in the 'throws' clause of a method.
*/
public int getTryCatchBlockIndex() {
return (value & 0x00FFFF00) >> 8;
}
/**
* Returns the index of the type argument referenced by this type reference.
* This method must only be used for type references whose sort is
* {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
*
* @return a type parameter index.
*/
public int getTypeArgumentIndex() {
return value & 0xFF;
}
/**
* Returns the int encoded value of this type reference, suitable for use in
* visit methods related to type annotations, like visitTypeAnnotation.
*
* @return the int encoded value of this type reference.
*/
public int getValue() {
return value;
}
}
@@ -1,87 +0,0 @@
<html>
<!--
* 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.
-->
<body>
Provides a small and fast bytecode manipulation framework.
<p>
The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized
around the {@link org.objectweb.asm.ClassVisitor ClassVisitor},
{@link org.objectweb.asm.FieldVisitor FieldVisitor},
{@link org.objectweb.asm.MethodVisitor MethodVisitor} and
{@link org.objectweb.asm.AnnotationVisitor AnnotationVisitor} abstract classes,
which allow one to visit the fields, methods and annotations of a class,
including the bytecode instructions of each method.
<p>
In addition to these main abstract classes, ASM provides a {@link
org.objectweb.asm.ClassReader ClassReader} class, that can parse an
existing class and make a given visitor visit it. ASM also provides
a {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is
a visitor that generates Java class files.
<p>
In order to generate a class from scratch, only the {@link
org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,
in order to generate a class, one must just call its visit<i>Xxx</i>
methods with the appropriate arguments to generate the desired fields
and methods. See the "helloworld" example in the ASM distribution for
more details about class generation.
<p>
In order to modify existing classes, one must use a {@link
org.objectweb.asm.ClassReader ClassReader} class to analyze
the original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter
ClassWriter} to construct the modified class. The class modifier
is just a {@link org.objectweb.asm.ClassVisitor ClassVisitor}
that delegates most of the work to another {@link org.objectweb.asm.ClassVisitor
ClassVisitor}, but that sometimes changes some parameter values,
or call additional methods, in order to implement the desired
modification process. In order to make it easier to implement such
class modifiers, the {@link org.objectweb.asm.ClassVisitor
ClassVisitor} and {@link org.objectweb.asm.MethodVisitor MethodVisitor}
classes delegate by default all the method calls they receive to an
optional visitor. See the "adapt" example in the ASM
distribution for more details about class modification.
<p>
The size of the core ASM library, <tt>asm.jar</tt>, is only 45KB, which is much
smaller than the size of the
<a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the
size of the
<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also
much faster than these tools. Indeed the overhead of a load time class
transformation process is of the order of 60% with ASM, 700% or more with BCEL,
and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM
distribution)!
@since ASM 1.3
</body>
</html>
@@ -44,7 +44,7 @@ public class SignatureReader {
private final String signature;
/**
* Constructs a {@link org.objectweb.asm.signature.SignatureReader} for the given signature.
* Constructs a {@link SignatureReader} for the given signature.
*
* @param signature
* A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
@@ -56,9 +56,9 @@ public class SignatureReader {
/**
* Makes the given visitor visit the signature of this
* {@link org.objectweb.asm.signature.SignatureReader}. This signature is the one specified in the
* {@link SignatureReader}. This signature is the one specified in the
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
* method is intended to be called on a {@link org.objectweb.asm.signature.SignatureReader} that was
* method is intended to be called on a {@link SignatureReader} that was
* created using a <i>ClassSignature</i> (such as the <code>signature</code>
* parameter of the {@link org.objectweb.asm.ClassVisitor#visit
* ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
@@ -114,9 +114,9 @@ public class SignatureReader {
/**
* Makes the given visitor visit the signature of this
* {@link org.objectweb.asm.signature.SignatureReader}. This signature is the one specified in the
* {@link SignatureReader}. This signature is the one specified in the
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
* method is intended to be called on a {@link org.objectweb.asm.signature.SignatureReader} that was
* method is intended to be called on a {@link SignatureReader} that was
* created using a <i>FieldTypeSignature</i>, such as the
* <code>signature</code> parameter of the
* {@link org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField}
@@ -29,10 +29,12 @@
*/
package org.objectweb.asm.signature;
import org.objectweb.asm.Opcodes;
/**
* A visitor to visit a generic signature. The methods of this interface must be
* called in one of the three following orders (the last one is the only valid
* order for a {@link org.objectweb.asm.signature.SignatureVisitor} that is returned by a method of this
* order for a {@link SignatureVisitor} that is returned by a method of this
* interface):
* <ul>
* <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
@@ -71,18 +73,21 @@ public abstract class SignatureVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
/**
* Constructs a new {@link org.objectweb.asm.signature.SignatureVisitor}.
* Constructs a new {@link SignatureVisitor}.
*
* @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 SignatureVisitor(final int api) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
}
this.api = api;
}
@@ -63,10 +63,10 @@ public class SignatureWriter extends SignatureVisitor {
private int argumentStack;
/**
* Constructs a new {@link org.objectweb.asm.signature.SignatureWriter} object.
* Constructs a new {@link SignatureWriter} object.
*/
public SignatureWriter() {
super(Opcodes.ASM4);
super(Opcodes.ASM5);
}
// ------------------------------------------------------------------------
@@ -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);
}
}
@@ -1,5 +1,4 @@
<html>
<!--
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
@@ -27,10 +26,51 @@
* 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.
-->
<body>
Provides support for type signatures.
*/
package org.objectweb.asm.tree;
@since ASM 2.0
</body>
</html>
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);
}
}