in org.eclipse.sisu.inject/src/org/eclipse/sisu/space/asm/ClassReader.java [829:1024]
private int readMethod(final ClassVisitor classVisitor,
final Context context, int u) {
// reads the method declaration
char[] c = context.buffer;
context.access = readUnsignedShort(u);
context.name = readUTF8(u + 2, c);
context.desc = readUTF8(u + 4, c);
u += 6;
// reads the method attributes
int code = 0;
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;
int firstAttribute = u;
Attribute attributes = null;
for (int i = readUnsignedShort(u); i > 0; --i) {
String attrName = readUTF8(u + 2, c);
// tests are sorted in decreasing frequency order
// (based on frequencies observed on typical classes)
if ("Code".equals(attrName)) {
if ((context.flags & SKIP_CODE) == 0) {
code = u + 8;
}
} else if ("Exceptions".equals(attrName)) {
exceptions = new String[readUnsignedShort(u + 8)];
exception = u + 10;
for (int j = 0; j < exceptions.length; ++j) {
exceptions[j] = readClass(exception, c);
exception += 2;
}
} else if (SIGNATURES && "Signature".equals(attrName)) {
signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) {
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)) {
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);
if (attr != null) {
attr.next = attributes;
attributes = attr;
}
}
u += 6 + readInt(u + 4);
}
u += 2;
// visits the method declaration
MethodVisitor mv = classVisitor.visitMethod(context.access,
context.name, context.desc, signature, exceptions);
if (mv == null) {
return u;
}
/*
* if the returned MethodVisitor is in fact a MethodWriter, it means
* there is no method adapter between the reader and the writer. If, in
* addition, the writer's constant pool was copied from this reader
* (mw.cw.cr == this), and the signature and exceptions of the method
* have not been changed, then it is possible to skip all visit events
* and just copy the original code of the method to the writer (the
* access, name and descriptor can have been changed, this is not
* important since they are not copied as is from the reader).
*/
if (WRITER && mv instanceof MethodWriter) {
MethodWriter mw = (MethodWriter) mv;
if (mw.cw.cr == this && signature == mw.signature) {
boolean sameExceptions = false;
if (exceptions == null) {
sameExceptions = mw.exceptionCount == 0;
} else if (exceptions.length == mw.exceptionCount) {
sameExceptions = true;
for (int j = exceptions.length - 1; j >= 0; --j) {
exception -= 2;
if (mw.exceptions[j] != readUnsignedShort(exception)) {
sameExceptions = false;
break;
}
}
}
if (sameExceptions) {
/*
* we do not copy directly the code into MethodWriter to
* save a byte array copy operation. The real copy will be
* done in ClassWriter.toByteArray().
*/
mw.classReaderOffset = firstAttribute;
mw.classReaderLength = u - firstAttribute;
return u;
}
}
}
// 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();
readAnnotationValue(dann, c, null, dv);
if (dv != null) {
dv.visitEnd();
}
}
if (ANNOTATIONS && anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), true));
}
}
if (ANNOTATIONS && ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true,
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(mv, context, mpanns, true);
}
if (ANNOTATIONS && impanns != 0) {
readParameterAnnotations(mv, context, impanns, false);
}
// visits the method attributes
while (attributes != null) {
Attribute attr = attributes.next;
attributes.next = null;
mv.visitAttribute(attributes);
attributes = attr;
}
// visits the method code
if (code != 0) {
mv.visitCode();
readCode(mv, context, code);
}
// visits the end of the method
mv.visitEnd();
return u;
}