From e8729cf8b01268a7a968eaeace15f4aeda07f47d Mon Sep 17 00:00:00 2001 From: Clisprail Date: Sun, 26 Jan 2014 00:15:10 +0100 Subject: [PATCH] Updated ASM library (ASM 5) --- .../org/objectweb/asm/AnnotationVisitor.java | 12 +- .../org/objectweb/asm/AnnotationWriter.java | 59 ++- .../src/org/objectweb/asm/Attribute.java | 4 +- .../src/org/objectweb/asm/ByteVector.java | 12 +- .../src/org/objectweb/asm/ClassReader.java | 403 +++++++++++++--- .../src/org/objectweb/asm/ClassVisitor.java | 50 +- .../src/org/objectweb/asm/ClassWriter.java | 124 +++-- parabotv2/src/org/objectweb/asm/Context.java | 39 +- parabotv2/src/org/objectweb/asm/Edge.java | 8 +- .../src/org/objectweb/asm/FieldVisitor.java | 45 +- .../src/org/objectweb/asm/FieldWriter.java | 62 ++- parabotv2/src/org/objectweb/asm/Frame.java | 4 +- parabotv2/src/org/objectweb/asm/Handle.java | 13 +- parabotv2/src/org/objectweb/asm/Item.java | 30 +- parabotv2/src/org/objectweb/asm/Label.java | 10 +- .../src/org/objectweb/asm/MethodVisitor.java | 225 ++++++++- .../src/org/objectweb/asm/MethodWriter.java | 250 +++++++++- parabotv2/src/org/objectweb/asm/Opcodes.java | 9 +- parabotv2/src/org/objectweb/asm/Type.java | 19 +- parabotv2/src/org/objectweb/asm/TypePath.java | 193 ++++++++ .../src/org/objectweb/asm/TypeReference.java | 452 ++++++++++++++++++ parabotv2/src/org/objectweb/asm/package.html | 87 ---- .../asm/signature/SignatureReader.java | 10 +- .../asm/signature/SignatureVisitor.java | 13 +- .../asm/signature/SignatureWriter.java | 4 +- .../objectweb/asm/tree/AbstractInsnNode.java | 80 +++- .../objectweb/asm/tree/AnnotationNode.java | 17 +- .../src/org/objectweb/asm/tree/ClassNode.java | 84 +++- .../org/objectweb/asm/tree/FieldInsnNode.java | 10 +- .../src/org/objectweb/asm/tree/FieldNode.java | 78 ++- .../src/org/objectweb/asm/tree/FrameNode.java | 30 +- .../org/objectweb/asm/tree/IincInsnNode.java | 5 +- .../objectweb/asm/tree/InnerClassNode.java | 2 +- .../src/org/objectweb/asm/tree/InsnList.java | 16 +- .../src/org/objectweb/asm/tree/InsnNode.java | 5 +- .../org/objectweb/asm/tree/IntInsnNode.java | 5 +- .../asm/tree/InvokeDynamicInsnNode.java | 6 +- .../org/objectweb/asm/tree/JumpInsnNode.java | 6 +- .../src/org/objectweb/asm/tree/LabelNode.java | 2 +- .../org/objectweb/asm/tree/LdcInsnNode.java | 5 +- .../objectweb/asm/tree/LineNumberNode.java | 2 +- .../asm/tree/LocalVariableAnnotationNode.java | 157 ++++++ .../objectweb/asm/tree/LocalVariableNode.java | 2 +- .../asm/tree/LookupSwitchInsnNode.java | 7 +- .../objectweb/asm/tree/MethodInsnNode.java | 2 +- .../org/objectweb/asm/tree/MethodNode.java | 261 +++++++++- .../asm/tree/MultiANewArrayInsnNode.java | 5 +- .../package.html => tree/ParameterNode.java} | 56 ++- .../asm/tree/TableSwitchInsnNode.java | 7 +- .../objectweb/asm/tree/TryCatchBlockNode.java | 61 ++- .../asm/tree/TypeAnnotationNode.java | 95 ++++ .../org/objectweb/asm/tree/TypeInsnNode.java | 5 +- .../org/objectweb/asm/tree/VarInsnNode.java | 5 +- 53 files changed, 2740 insertions(+), 413 deletions(-) create mode 100644 parabotv2/src/org/objectweb/asm/TypePath.java create mode 100644 parabotv2/src/org/objectweb/asm/TypeReference.java delete mode 100644 parabotv2/src/org/objectweb/asm/package.html create mode 100644 parabotv2/src/org/objectweb/asm/tree/LocalVariableAnnotationNode.java rename parabotv2/src/org/objectweb/asm/{signature/package.html => tree/ParameterNode.java} (57%) create mode 100644 parabotv2/src/org/objectweb/asm/tree/TypeAnnotationNode.java diff --git a/parabotv2/src/org/objectweb/asm/AnnotationVisitor.java b/parabotv2/src/org/objectweb/asm/AnnotationVisitor.java index 30d62c3..b644083 100644 --- a/parabotv2/src/org/objectweb/asm/AnnotationVisitor.java +++ b/parabotv2/src/org/objectweb/asm/AnnotationVisitor.java @@ -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; diff --git a/parabotv2/src/org/objectweb/asm/AnnotationWriter.java b/parabotv2/src/org/objectweb/asm/AnnotationWriter.java index 3c7ef47..6b95608 100644 --- a/parabotv2/src/org/objectweb/asm/AnnotationWriter.java +++ b/parabotv2/src/org/objectweb/asm/AnnotationWriter.java @@ -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 + * null 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); + } + } } diff --git a/parabotv2/src/org/objectweb/asm/Attribute.java b/parabotv2/src/org/objectweb/asm/Attribute.java index 868e1ff..8a2a882 100644 --- a/parabotv2/src/org/objectweb/asm/Attribute.java +++ b/parabotv2/src/org/objectweb/asm/Attribute.java @@ -93,7 +93,7 @@ public class Attribute { /** * Reads a {@link #type type} attribute. This method must return a - * new {@link org.objectweb.asm.Attribute} object, of type {@link #type type}, + * new {@link Attribute} object, of type {@link #type type}, * corresponding to the len 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 null if the * attribute to be read is not a code attribute. - * @return a new {@link org.objectweb.asm.Attribute} object corresponding to the given + * @return a new {@link Attribute} object corresponding to the given * bytes. */ protected Attribute read(final ClassReader cr, final int off, diff --git a/parabotv2/src/org/objectweb/asm/ByteVector.java b/parabotv2/src/org/objectweb/asm/ByteVector.java index 579d7d4..f1e2da1 100644 --- a/parabotv2/src/org/objectweb/asm/ByteVector.java +++ b/parabotv2/src/org/objectweb/asm/ByteVector.java @@ -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) { diff --git a/parabotv2/src/org/objectweb/asm/ClassReader.java b/parabotv2/src/org/objectweb/asm/ClassReader.java index 35a6893..9816c60 100644 --- a/parabotv2/src/org/objectweb/asm/ClassReader.java +++ b/parabotv2/src/org/objectweb/asm/ClassReader.java @@ -106,7 +106,7 @@ public class ClassReader { /** * The class to be parsed. 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. */ 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 * true 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. This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * one. This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param item @@ -1993,7 +2286,7 @@ public class ClassReader { /** * Reads a byte value in {@link #b b}. 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. * * @param index @@ -2006,7 +2299,7 @@ public class ClassReader { /** * Reads an unsigned short value in {@link #b b}. 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. * * @param index @@ -2020,7 +2313,7 @@ public class ClassReader { /** * Reads a signed short value in {@link #b b}. 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. * * @param index @@ -2034,7 +2327,7 @@ public class ClassReader { /** * Reads a signed int value in {@link #b b}. 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. * * @param index @@ -2049,7 +2342,7 @@ public class ClassReader { /** * Reads a signed long value in {@link #b b}. 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. * * @param index @@ -2064,7 +2357,7 @@ public class ClassReader { /** * Reads an UTF8 string constant pool item in {@link #b b}. 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. * * @param index @@ -2139,7 +2432,7 @@ public class ClassReader { /** * Reads a class constant pool item in {@link #b b}. 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. * * @param index @@ -2159,7 +2452,7 @@ public class ClassReader { /** * Reads a numeric or string constant pool item in {@link #b b}. 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. * * @param item diff --git a/parabotv2/src/org/objectweb/asm/ClassVisitor.java b/parabotv2/src/org/objectweb/asm/ClassVisitor.java index 57b0514..107ada0 100644 --- a/parabotv2/src/org/objectweb/asm/ClassVisitor.java +++ b/parabotv2/src/org/objectweb/asm/ClassVisitor.java @@ -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: visit [ visitSource ] [ * visitOuterClass ] ( visitAnnotation | - * visitAttribute )* ( visitInnerClass | visitField | - * visitMethod )* visitEnd. + * visitTypeAnnotation | visitAttribute )* ( + * visitInnerClass | visitField | visitMethod )* + * visitEnd. * * @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 + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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. * diff --git a/parabotv2/src/org/objectweb/asm/ClassWriter.java b/parabotv2/src/org/objectweb/asm/ClassWriter.java index 9a7819c..7a77614 100644 --- a/parabotv2/src/org/objectweb/asm/ClassWriter.java +++ b/parabotv2/src/org/objectweb/asm/ClassWriter.java @@ -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 { * true if the maximum stack size and number of local variables * must be automatically computed. */ - private final boolean computeMaxs; + private boolean computeMaxs; /** * true if the stack map frames must be recomputed from scratch. */ - private final boolean computeFrames; + private boolean computeFrames; /** * true 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 lot 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). * * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. 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. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. 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. * * @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. 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. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. - * This method is intended for {@link org.objectweb.asm.Attribute} sub classes, and is + * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @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. 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. * * @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 loads the two given classes and uses + * implementation of this method loads 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 diff --git a/parabotv2/src/org/objectweb/asm/Context.java b/parabotv2/src/org/objectweb/asm/Context.java index 280e1eb..363b34c 100644 --- a/parabotv2/src/org/objectweb/asm/Context.java +++ b/parabotv2/src/org/objectweb/asm/Context.java @@ -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. */ diff --git a/parabotv2/src/org/objectweb/asm/Edge.java b/parabotv2/src/org/objectweb/asm/Edge.java index 74b35a7..4e87cba 100644 --- a/parabotv2/src/org/objectweb/asm/Edge.java +++ b/parabotv2/src/org/objectweb/asm/Edge.java @@ -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). */ diff --git a/parabotv2/src/org/objectweb/asm/FieldVisitor.java b/parabotv2/src/org/objectweb/asm/FieldVisitor.java index bfb26b5..2372e4c 100644 --- a/parabotv2/src/org/objectweb/asm/FieldVisitor.java +++ b/parabotv2/src/org/objectweb/asm/FieldVisitor.java @@ -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: ( visitAnnotation | visitAttribute )* - * visitEnd. + * the following order: ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* visitEnd. * * @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 + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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. * diff --git a/parabotv2/src/org/objectweb/asm/FieldWriter.java b/parabotv2/src/org/objectweb/asm/FieldWriter.java index 86a58e6..84d92aa 100644 --- a/parabotv2/src/org/objectweb/asm/FieldWriter.java +++ b/parabotv2/src/org/objectweb/asm/FieldWriter.java @@ -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 null. + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this field. May be + * null. + */ + private AnnotationWriter itanns; + /** * The non standard attributes of this field. May be null. */ @@ -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); } diff --git a/parabotv2/src/org/objectweb/asm/Frame.java b/parabotv2/src/org/objectweb/asm/Frame.java index 507705b..10e15bc 100644 --- a/parabotv2/src/org/objectweb/asm/Frame.java +++ b/parabotv2/src/org/objectweb/asm/Frame.java @@ -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 true if the input frame of the given label has been * changed by this operation. */ diff --git a/parabotv2/src/org/objectweb/asm/Handle.java b/parabotv2/src/org/objectweb/asm/Handle.java index 533471e..a627911 100644 --- a/parabotv2/src/org/objectweb/asm/Handle.java +++ b/parabotv2/src/org/objectweb/asm/Handle.java @@ -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; diff --git a/parabotv2/src/org/objectweb/asm/Item.java b/parabotv2/src/org/objectweb/asm/Item.java index 742173c..c25b7b7 100644 --- a/parabotv2/src/org/objectweb/asm/Item.java +++ b/parabotv2/src/org/objectweb/asm/Item.java @@ -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 diff --git a/parabotv2/src/org/objectweb/asm/Label.java b/parabotv2/src/org/objectweb/asm/Label.java index 3e7f894..1c4de30 100644 --- a/parabotv2/src/org/objectweb/asm/Label.java +++ b/parabotv2/src/org/objectweb/asm/Label.java @@ -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. 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. * * @return the offset corresponding to this label. diff --git a/parabotv2/src/org/objectweb/asm/MethodVisitor.java b/parabotv2/src/org/objectweb/asm/MethodVisitor.java index 1448177..832c124 100644 --- a/parabotv2/src/org/objectweb/asm/MethodVisitor.java +++ b/parabotv2/src/org/objectweb/asm/MethodVisitor.java @@ -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: [ visitAnnotationDefault ] ( - * visitAnnotation | visitParameterAnnotation | - * visitAttribute )* [ visitCode ( visitFrame | - * visitXInsn | visitLabel | - * visitTryCatchBlock | visitLocalVariable | + * the following order: ( visitParameter )* [ + * visitAnnotationDefault ] ( visitAnnotation | + * visitTypeAnnotation | visitAttribute )* [ + * visitCode ( visitFrame | visitXInsn | + * visitLabel | visitInsnAnnotation | + * visitTryCatchBlock | visitTryCatchBlockAnnotation | + * visitLocalVariable | visitLocalVariableAnnotation | * visitLineNumber )* visitMaxs ] visitEnd. In - * addition, the visitXInsn and visitLabel methods - * must be called in the sequential order of the bytecode instructions of the - * visited code, visitTryCatchBlock must be called before the - * labels passed as arguments have been visited, and the - * visitLocalVariable and visitLineNumber methods must be - * called after the labels passed as arguments have been visited. + * addition, the visitXInsn and visitLabel methods must + * be called in the sequential order of the bytecode instructions of the visited + * code, visitInsnAnnotation must be called after the annotated + * instruction, visitTryCatchBlock must be called before the + * labels passed as arguments have been visited, + * visitTryCatchBlockAnnotation must be called after the + * corresponding try catch block has been visited, and the + * visitLocalVariable, visitLocalVariableAnnotation and + * visitLineNumber methods must be called after 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 ACC_FINAL, + * ACC_SYNTHETIC or/and ACC_MANDATED 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 + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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 { *
  • {@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 (nLocals is 1, 2 or 3).
  • - *
  • {@link Opcodes#F_FULL} representing complete frame data.
  • + *
  • {@link Opcodes#F_FULL} representing complete frame data.
  • * - *
    + * + * + *
    * 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 .class 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 + * after 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 + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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 after 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 + * null if the annotation targets 'typeRef' as a whole. + * @param desc + * the class descriptor of the annotation class. + * @param visible + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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 + * null 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 + * true if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or null 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. * diff --git a/parabotv2/src/org/objectweb/asm/MethodWriter.java b/parabotv2/src/org/objectweb/asm/MethodWriter.java index cdc9a76..fd3c953 100644 --- a/parabotv2/src/org/objectweb/asm/MethodWriter.java +++ b/parabotv2/src/org/objectweb/asm/MethodWriter.java @@ -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 null + * . + */ + private AnnotationWriter tanns; + + /** + * The runtime invisible type annotations of this method. May be + * null. + */ + private AnnotationWriter itanns; + /** * The runtime visible parameter annotations of this method. May be * null. @@ -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 null. + */ + private AnnotationWriter ctanns; + + /** + * The runtime invisible type annotations of the code. May be null. + */ + 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 stackSize. */ 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 stackSize. */ 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. *

    * This method must be called after all the method that is being built - * has been visited. In particular, the {@link org.objectweb.asm.Label Label} objects used + * has been visited. In particular, the {@link Label Label} objects used * to construct the method are no longer valid after this method has been * called. */ diff --git a/parabotv2/src/org/objectweb/asm/Opcodes.java b/parabotv2/src/org/objectweb/asm/Opcodes.java index 0796eb8..e5c2b33 100644 --- a/parabotv2/src/org/objectweb/asm/Opcodes.java +++ b/parabotv2/src/org/objectweb/asm/Opcodes.java @@ -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; diff --git a/parabotv2/src/org/objectweb/asm/Type.java b/parabotv2/src/org/objectweb/asm/Type.java index b44d0c7..2ce4cb3 100644 --- a/parabotv2/src/org/objectweb/asm/Type.java +++ b/parabotv2/src/org/objectweb/asm/Type.java @@ -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 = - * (argSize << 2) | retSize (argSize is therefore equal to - * i >> 2, and retSize to i & 0x03). + * (argSize << 2) | retSize (argSize is therefore equal to + * i >> 2, and retSize to i & 0x03). */ 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 = (argSize << 2) | retSize - * (argSize is therefore equal to i >> 2, and retSize to - * i & 0x03). + * packed into a single + * int i = (argSize << 2) | retSize + * (argSize is therefore equal to i >> 2, + * and retSize to i & 0x03). */ 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) { diff --git a/parabotv2/src/org/objectweb/asm/TypePath.java b/parabotv2/src/org/objectweb/asm/TypePath.java new file mode 100644 index 0000000..3c5f984 --- /dev/null +++ b/parabotv2/src/org/objectweb/asm/TypePath.java @@ -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(); + } +} diff --git a/parabotv2/src/org/objectweb/asm/TypeReference.java b/parabotv2/src/org/objectweb/asm/TypeReference.java new file mode 100644 index 0000000..dff76c0 --- /dev/null +++ b/parabotv2/src/org/objectweb/asm/TypeReference.java @@ -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; + } +} diff --git a/parabotv2/src/org/objectweb/asm/package.html b/parabotv2/src/org/objectweb/asm/package.html deleted file mode 100644 index 2d4a765..0000000 --- a/parabotv2/src/org/objectweb/asm/package.html +++ /dev/null @@ -1,87 +0,0 @@ - - - -Provides a small and fast bytecode manipulation framework. - -

    -The ASM 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. - -

    -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. - -

    -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 visitXxx -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. - -

    -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. - -

    -The size of the core ASM library, asm.jar, is only 45KB, which is much -smaller than the size of the -BCEL library (504KB), and than the -size of the -SERP 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 test/perf directory in the ASM -distribution)! - -@since ASM 1.3 - - diff --git a/parabotv2/src/org/objectweb/asm/signature/SignatureReader.java b/parabotv2/src/org/objectweb/asm/signature/SignatureReader.java index b559612..1083b3d 100644 --- a/parabotv2/src/org/objectweb/asm/signature/SignatureReader.java +++ b/parabotv2/src/org/objectweb/asm/signature/SignatureReader.java @@ -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 ClassSignature, MethodTypeSignature, 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 ClassSignature (such as the signature * parameter of the {@link org.objectweb.asm.ClassVisitor#visit * ClassVisitor.visit} method) or a MethodTypeSignature (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 FieldTypeSignature, such as the * signature parameter of the * {@link org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField} diff --git a/parabotv2/src/org/objectweb/asm/signature/SignatureVisitor.java b/parabotv2/src/org/objectweb/asm/signature/SignatureVisitor.java index 47c35bf..053c105 100644 --- a/parabotv2/src/org/objectweb/asm/signature/SignatureVisitor.java +++ b/parabotv2/src/org/objectweb/asm/signature/SignatureVisitor.java @@ -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): *

      *
    • ClassSignature = ( visitFormalTypeParameter @@ -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; } diff --git a/parabotv2/src/org/objectweb/asm/signature/SignatureWriter.java b/parabotv2/src/org/objectweb/asm/signature/SignatureWriter.java index 94fee79..ec475db 100644 --- a/parabotv2/src/org/objectweb/asm/signature/SignatureWriter.java +++ b/parabotv2/src/org/objectweb/asm/signature/SignatureWriter.java @@ -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); } // ------------------------------------------------------------------------ diff --git a/parabotv2/src/org/objectweb/asm/tree/AbstractInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/AbstractInsnNode.java index 49cc95e..583be7f 100644 --- a/parabotv2/src/org/objectweb/asm/tree/AbstractInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/AbstractInsnNode.java @@ -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 null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List 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 null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List 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(); + 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(); + 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; + } } diff --git a/parabotv2/src/org/objectweb/asm/tree/AnnotationNode.java b/parabotv2/src/org/objectweb/asm/tree/AnnotationNode.java index bd6c5d2..0e0f806 100644 --- a/parabotv2/src/org/objectweb/asm/tree/AnnotationNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/AnnotationNode.java @@ -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 null if there is no name value * pair. */ public List values; /** - * Constructs a new {@link org.objectweb.asm.tree.AnnotationNode}. Subclasses must not use this + * Constructs a new {@link AnnotationNode}. Subclasses must not use this * constructor. 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 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 diff --git a/parabotv2/src/org/objectweb/asm/tree/ClassNode.java b/parabotv2/src/org/objectweb/asm/tree/ClassNode.java index f6c31d6..2b21201 100644 --- a/parabotv2/src/org/objectweb/asm/tree/ClassNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/ClassNode.java @@ -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 null. + * {@link AnnotationNode} objects. May be null. * * @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 null. + * {@link AnnotationNode} objects. May be null. * * @associates org.objectweb.asm.tree.AnnotationNode * @label invisible */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this class. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this class. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this class. This list is a list of - * {@link org.objectweb.asm.Attribute} objects. May be null. + * {@link Attribute} objects. May be null. * * @associates org.objectweb.asm.Attribute */ @@ -165,20 +184,20 @@ public class ClassNode extends ClassVisitor { public List methods; /** - * Constructs a new {@link org.objectweb.asm.tree.ClassNode}. Subclasses must not use this + * Constructs a new {@link ClassNode}. Subclasses must not use this * constructor. 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(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(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)); diff --git a/parabotv2/src/org/objectweb/asm/tree/FieldInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/FieldInsnNode.java index 210b8e1..9b0c95f 100644 --- a/parabotv2/src/org/objectweb/asm/tree/FieldInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/FieldInsnNode.java @@ -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 labels) { - return new FieldInsnNode(opcode, owner, name, desc); + return new FieldInsnNode(opcode, owner, name, desc) + .cloneAnnotations(this); } } diff --git a/parabotv2/src/org/objectweb/asm/tree/FieldNode.java b/parabotv2/src/org/objectweb/asm/tree/FieldNode.java index 046e751..f9913ac 100644 --- a/parabotv2/src/org/objectweb/asm/tree/FieldNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/FieldNode.java @@ -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 null. + * {@link AnnotationNode} objects. May be null. * * @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 null. + * {@link AnnotationNode} objects. May be null. * * @associates org.objectweb.asm.tree.AnnotationNode * @label invisible */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this field. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this field. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this field. This list is a list of - * {@link org.objectweb.asm.Attribute} objects. May be null. + * {@link Attribute} objects. May be null. * * @associates org.objectweb.asm.Attribute */ public List attrs; /** - * Constructs a new {@link org.objectweb.asm.tree.FieldNode}. Subclasses must not use this + * Constructs a new {@link FieldNode}. Subclasses must not use this * constructor. 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}. Subclasses must not use this + * Constructs a new {@link FieldNode}. Subclasses must not use this * constructor. 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(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(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)); diff --git a/parabotv2/src/org/objectweb/asm/tree/FrameNode.java b/parabotv2/src/org/objectweb/asm/tree/FrameNode.java index 7757b9e..bd1ea70 100644 --- a/parabotv2/src/org/objectweb/asm/tree/FrameNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/FrameNode.java @@ -47,17 +47,17 @@ import org.objectweb.asm.Opcodes; * of the operand stack elements just before i is executed.
      *
      * (*) 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 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 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) { diff --git a/parabotv2/src/org/objectweb/asm/tree/IincInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/IincInsnNode.java index 745dd66..5305b35 100644 --- a/parabotv2/src/org/objectweb/asm/tree/IincInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/IincInsnNode.java @@ -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 labels) { - return new IincInsnNode(var, incr); + return new IincInsnNode(var, incr).cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/tree/InnerClassNode.java b/parabotv2/src/org/objectweb/asm/tree/InnerClassNode.java index 408e28f..5198cfb 100644 --- a/parabotv2/src/org/objectweb/asm/tree/InnerClassNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/InnerClassNode.java @@ -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 diff --git a/parabotv2/src/org/objectweb/asm/tree/InsnList.java b/parabotv2/src/org/objectweb/asm/tree/InsnList.java index a83bc93..5047b58 100644 --- a/parabotv2/src/org/objectweb/asm/tree/InsnList.java +++ b/parabotv2/src/org/objectweb/asm/tree/InsnList.java @@ -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. This + * A doubly linked list of {@link AbstractInsnNode} objects. This * implementation is not thread safe. */ 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 of this list. * @param insn * another instruction, which must not belong to any - * {@link org.objectweb.asm.tree.InsnList}. + * {@link InsnList}. */ public void set(final AbstractInsnNode location, final AbstractInsnNode insn) { AbstractInsnNode next = location.next; @@ -241,7 +241,7 @@ public class InsnList { * * @param insn * an instruction, which must not belong to any - * {@link org.objectweb.asm.tree.InsnList}. + * {@link InsnList}. */ public void add(final AbstractInsnNode insn) { ++size; @@ -287,7 +287,7 @@ public class InsnList { * * @param insn * an instruction, which must not belong to any - * {@link org.objectweb.asm.tree.InsnList}. + * {@link InsnList}. */ public void insert(final AbstractInsnNode insn) { ++size; @@ -336,7 +336,7 @@ public class InsnList { * inserted. * @param insn * the instruction to be inserted, which must not belong to - * any {@link org.objectweb.asm.tree.InsnList}. + * any {@link InsnList}. */ public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) { @@ -392,7 +392,7 @@ public class InsnList { * inserted. * @param insn * the instruction to be inserted, which must not belong to - * any {@link org.objectweb.asm.tree.InsnList}. + * any {@link InsnList}. */ 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) { diff --git a/parabotv2/src/org/objectweb/asm/tree/InsnNode.java b/parabotv2/src/org/objectweb/asm/tree/InsnNode.java index dbaec7c..f6feba7 100644 --- a/parabotv2/src/org/objectweb/asm/tree/InsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/InsnNode.java @@ -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 labels) { - return new InsnNode(opcode); + return new InsnNode(opcode).cloneAnnotations(this); } } diff --git a/parabotv2/src/org/objectweb/asm/tree/IntInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/IntInsnNode.java index 12aed8a..6d8e7cd 100644 --- a/parabotv2/src/org/objectweb/asm/tree/IntInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/IntInsnNode.java @@ -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 labels) { - return new IntInsnNode(opcode, operand); + return new IntInsnNode(opcode, operand).cloneAnnotations(this); } } diff --git a/parabotv2/src/org/objectweb/asm/tree/InvokeDynamicInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/InvokeDynamicInsnNode.java index 46ef951..55e3a6a 100644 --- a/parabotv2/src/org/objectweb/asm/tree/InvokeDynamicInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/InvokeDynamicInsnNode.java @@ -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 labels) { - return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs); + return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs) + .cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/tree/JumpInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/JumpInsnNode.java index d3a78ea..5c461f3 100644 --- a/parabotv2/src/org/objectweb/asm/tree/JumpInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/JumpInsnNode.java @@ -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 labels) { - return new JumpInsnNode(opcode, clone(label, labels)); + return new JumpInsnNode(opcode, clone(label, labels)) + .cloneAnnotations(this); } } diff --git a/parabotv2/src/org/objectweb/asm/tree/LabelNode.java b/parabotv2/src/org/objectweb/asm/tree/LabelNode.java index 72e0cdc..b6381bd 100644 --- a/parabotv2/src/org/objectweb/asm/tree/LabelNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/LabelNode.java @@ -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 { diff --git a/parabotv2/src/org/objectweb/asm/tree/LdcInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/LdcInsnNode.java index 2f7a86a..7441a42 100644 --- a/parabotv2/src/org/objectweb/asm/tree/LdcInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/LdcInsnNode.java @@ -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 labels) { - return new LdcInsnNode(cst); + return new LdcInsnNode(cst).cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/tree/LineNumberNode.java b/parabotv2/src/org/objectweb/asm/tree/LineNumberNode.java index 77f31d5..cda1694 100644 --- a/parabotv2/src/org/objectweb/asm/tree/LineNumberNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/LineNumberNode.java @@ -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 diff --git a/parabotv2/src/org/objectweb/asm/tree/LocalVariableAnnotationNode.java b/parabotv2/src/org/objectweb/asm/tree/LocalVariableAnnotationNode.java new file mode 100644 index 0000000..09b5322 --- /dev/null +++ b/parabotv2/src/org/objectweb/asm/tree/LocalVariableAnnotationNode.java @@ -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 null. + */ + public List 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 null. + */ + public List end; + + /** + * The local variable's index in each range. This list must have the same + * size as the 'start' list. Must not be null. + */ + public List index; + + /** + * Constructs a new {@link LocalVariableAnnotationNode}. Subclasses must + * not use this constructor. 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 + * null 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 + * null 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(start.length); + this.start.addAll(Arrays.asList(start)); + this.end = new ArrayList(end.length); + this.end.addAll(Arrays.asList(end)); + this.index = new ArrayList(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 + * true 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)); + } +} diff --git a/parabotv2/src/org/objectweb/asm/tree/LocalVariableNode.java b/parabotv2/src/org/objectweb/asm/tree/LocalVariableNode.java index 6abbb76..033f83e 100644 --- a/parabotv2/src/org/objectweb/asm/tree/LocalVariableNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/LocalVariableNode.java @@ -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. diff --git a/parabotv2/src/org/objectweb/asm/tree/LookupSwitchInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/LookupSwitchInsnNode.java index 24506d5..1249de3 100644 --- a/parabotv2/src/org/objectweb/asm/tree/LookupSwitchInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/LookupSwitchInsnNode.java @@ -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 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); } } diff --git a/parabotv2/src/org/objectweb/asm/tree/MethodInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/MethodInsnNode.java index 925786a..bd3d4a6 100644 --- a/parabotv2/src/org/objectweb/asm/tree/MethodInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/MethodInsnNode.java @@ -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 diff --git a/parabotv2/src/org/objectweb/asm/tree/MethodNode.java b/parabotv2/src/org/objectweb/asm/tree/MethodNode.java index eaf5afc..5b7b821 100644 --- a/parabotv2/src/org/objectweb/asm/tree/MethodNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/MethodNode.java @@ -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 exceptions; + /** + * The method parameter info (access flags and name) + */ + public List parameters; + /** * The runtime visible annotations of this method. This list is a list of - * {@link org.objectweb.asm.tree.AnnotationNode} objects. May be null. + * {@link AnnotationNode} objects. May be null. * * @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 null. + * {@link AnnotationNode} objects. May be null. * * @associates org.objectweb.asm.tree.AnnotationNode * @label invisible */ public List invisibleAnnotations; + /** + * The runtime visible type annotations of this method. This list is a list + * of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations of this method. This list is a + * list of {@link TypeAnnotationNode} objects. May be null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List invisibleTypeAnnotations; + /** * The non standard attributes of this method. This list is a list of - * {@link org.objectweb.asm.Attribute} objects. May be null. + * {@link Attribute} objects. May be null. * * @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 null. */ 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 null. + * lists of {@link AnnotationNode} objects. May be null. * * @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 null. + * are lists of {@link AnnotationNode} objects. May be null. * * @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 null + * {@link LocalVariableNode} objects. May be null * * @associates org.objectweb.asm.tree.LocalVariableNode */ public List localVariables; + /** + * The visible local variable annotations of this method. This list is a + * list of {@link LocalVariableAnnotationNode} objects. May be null + * + * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode + */ + public List visibleLocalVariableAnnotations; + + /** + * The invisible local variable annotations of this method. This list is a + * list of {@link LocalVariableAnnotationNode} objects. May be null + * + * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode + */ + public List invisibleLocalVariableAnnotations; + /** * If the accept method has been called on this object. */ private boolean visited; /** - * Constructs an uninitialized {@link org.objectweb.asm.tree.MethodNode}. Subclasses must not + * Constructs an uninitialized {@link MethodNode}. Subclasses must not * use this constructor. 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}. Subclasses must not use this + * Constructs a new {@link MethodNode}. Subclasses must not use this * constructor. 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(5); + } + parameters.add(new ParameterNode(name, access)); + } + + @SuppressWarnings("serial") + @Override public AnnotationVisitor visitAnnotationDefault() { return new AnnotationNode(new ArrayList(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(1); + } + visibleTypeAnnotations.add(an); + } else { + if (invisibleTypeAnnotations == null) { + invisibleTypeAnnotations = new ArrayList(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( + 1); + } + insn.visibleTypeAnnotations.add(an); + } else { + if (insn.invisibleTypeAnnotations == null) { + insn.invisibleTypeAnnotations = new ArrayList( + 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( + 1); + } + tcb.visibleTypeAnnotations.add(an); + } else { + if (tcb.invisibleTypeAnnotations == null) { + tcb.invisibleTypeAnnotations = new ArrayList( + 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( + 1); + } + visibleLocalVariableAnnotations.add(an); + } else { + if (invisibleLocalVariableAnnotations == null) { + invisibleLocalVariableAnnotations = new ArrayList( + 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; diff --git a/parabotv2/src/org/objectweb/asm/tree/MultiANewArrayInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/MultiANewArrayInsnNode.java index ad4aaad..8e42d2d 100644 --- a/parabotv2/src/org/objectweb/asm/tree/MultiANewArrayInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/MultiANewArrayInsnNode.java @@ -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 labels) { - return new MultiANewArrayInsnNode(desc, dims); + return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/signature/package.html b/parabotv2/src/org/objectweb/asm/tree/ParameterNode.java similarity index 57% rename from parabotv2/src/org/objectweb/asm/signature/package.html rename to parabotv2/src/org/objectweb/asm/tree/ParameterNode.java index 0c07d12..31360b8 100644 --- a/parabotv2/src/org/objectweb/asm/signature/package.html +++ b/parabotv2/src/org/objectweb/asm/tree/ParameterNode.java @@ -1,5 +1,4 @@ - - - -Provides support for type signatures. + */ +package org.objectweb.asm.tree; -@since ASM 2.0 - - +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 ACC_FINAL, ACC_SYNTHETIC and + * ACC_MANDATED. + */ + public int access; + + /** + * Constructs a new {@link ParameterNode}. + * + * @param access + * The parameter's access flags. Valid values are + * ACC_FINAL, ACC_SYNTHETIC or/and + * ACC_MANDATED (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); + } +} diff --git a/parabotv2/src/org/objectweb/asm/tree/TableSwitchInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/TableSwitchInsnNode.java index 1b8f51c..3e8937e 100644 --- a/parabotv2/src/org/objectweb/asm/tree/TableSwitchInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/TableSwitchInsnNode.java @@ -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 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 labels) { return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone( - this.labels, labels)); + this.labels, labels)).cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/tree/TryCatchBlockNode.java b/parabotv2/src/org/objectweb/asm/tree/TryCatchBlockNode.java index 7ed848a..7a33a9f 100644 --- a/parabotv2/src/org/objectweb/asm/tree/TryCatchBlockNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/TryCatchBlockNode.java @@ -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 + * null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label visible + */ + public List visibleTypeAnnotations; + + /** + * The runtime invisible type annotations on the exception handler type. + * This list is a list of {@link TypeAnnotationNode} objects. May be + * null. + * + * @associates org.objectweb.asm.tree.TypeAnnotationNode + * @label invisible + */ + public List 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)); + } } } diff --git a/parabotv2/src/org/objectweb/asm/tree/TypeAnnotationNode.java b/parabotv2/src/org/objectweb/asm/tree/TypeAnnotationNode.java new file mode 100644 index 0000000..f949c59 --- /dev/null +++ b/parabotv2/src/org/objectweb/asm/tree/TypeAnnotationNode.java @@ -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 + * null if the annotation targets 'typeRef' as a whole. + */ + public TypePath typePath; + + /** + * Constructs a new {@link AnnotationNode}. Subclasses must not use this + * constructor. 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 + * null 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 + * null 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; + } +} diff --git a/parabotv2/src/org/objectweb/asm/tree/TypeInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/TypeInsnNode.java index 351a624..859b57c 100644 --- a/parabotv2/src/org/objectweb/asm/tree/TypeInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/TypeInsnNode.java @@ -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 labels) { - return new TypeInsnNode(opcode, desc); + return new TypeInsnNode(opcode, desc).cloneAnnotations(this); } } \ No newline at end of file diff --git a/parabotv2/src/org/objectweb/asm/tree/VarInsnNode.java b/parabotv2/src/org/objectweb/asm/tree/VarInsnNode.java index 2e0105b..d813d6e 100644 --- a/parabotv2/src/org/objectweb/asm/tree/VarInsnNode.java +++ b/parabotv2/src/org/objectweb/asm/tree/VarInsnNode.java @@ -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 labels) { - return new VarInsnNode(opcode, var); + return new VarInsnNode(opcode, var).cloneAnnotations(this); } } \ No newline at end of file