mirror of
https://github.com/2006-Scape/Parabot.git
synced 2026-07-03 00:37:55 +00:00
Updated ASM library (ASM 5)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 << 2) | retSize</tt> (argSize is therefore equal to
|
||||
* <tt>i >> 2</tt>, and retSize to <tt>i & 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 << 2) | retSize</tt>
|
||||
* (argSize is therefore equal to <tt>i >> 2</tt>,
|
||||
* and retSize to <tt>i & 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 < 0 || index >= 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);
|
||||
}
|
||||
|
||||
}
|
||||
+48
-8
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user