mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
let's handle invoke and array correctly
This commit is contained in:
parent
f7dba2d33d
commit
809b1aa57f
@ -121,11 +121,21 @@ public class SourceClassHandler extends BaseClassHandler {
|
|||||||
int stackLevel = ClassUtil.getParameterTypes(((MethodInsnNode)instructions[rangeEnd]).desc).size();
|
int stackLevel = ClassUtil.getParameterTypes(((MethodInsnNode)instructions[rangeEnd]).desc).size();
|
||||||
for (int i = rangeEnd - 1; i >= 0; i--) {
|
for (int i = rangeEnd - 1; i >= 0; i--) {
|
||||||
switch (instructions[i].getOpcode()) {
|
switch (instructions[i].getOpcode()) {
|
||||||
case Opcodes.INVOKEVIRTUAL:
|
|
||||||
case Opcodes.INVOKESPECIAL:
|
case Opcodes.INVOKESPECIAL:
|
||||||
|
stackLevel += ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size();
|
||||||
|
if (((MethodInsnNode)instructions[i]).name.equals(ConstPool.CONSTRUCTOR)) {
|
||||||
|
// constructor implicitly eat 2 more stack and return 1 value
|
||||||
|
stackLevel++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Opcodes.INVOKESTATIC:
|
case Opcodes.INVOKESTATIC:
|
||||||
case Opcodes.INVOKEINTERFACE:
|
|
||||||
case Opcodes.INVOKEDYNAMIC:
|
case Opcodes.INVOKEDYNAMIC:
|
||||||
|
// static and dynamic invoke implicitly return 1 value
|
||||||
|
stackLevel += (ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size() - 1);
|
||||||
|
break;
|
||||||
|
case Opcodes.INVOKEVIRTUAL:
|
||||||
|
case Opcodes.INVOKEINTERFACE:
|
||||||
|
// virtual and interface invoke implicitly eat 1 more stack and return 1 more value, deuce
|
||||||
stackLevel += ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size();
|
stackLevel += ClassUtil.getParameterTypes(((MethodInsnNode)instructions[i]).desc).size();
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
@ -179,6 +189,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
|||||||
mn.instructions.remove(instructions[end - 1]);
|
mn.instructions.remove(instructions[end - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// method with @TestableMock will be modified as public access, so INVOKEVIRTUAL is used
|
||||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, testClassName,
|
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, testClassName,
|
||||||
substitutionMethod, addFirstParameter(method.desc, ClassUtil.fitCompanionClassName(ownerClass)), false));
|
substitutionMethod, addFirstParameter(method.desc, ClassUtil.fitCompanionClassName(ownerClass)), false));
|
||||||
mn.instructions.remove(instructions[end]);
|
mn.instructions.remove(instructions[end]);
|
||||||
|
@ -51,14 +51,14 @@ public class BytecodeUtil {
|
|||||||
put(FSTORE, -1);
|
put(FSTORE, -1);
|
||||||
put(DSTORE, -1);
|
put(DSTORE, -1);
|
||||||
put(ASTORE, -1);
|
put(ASTORE, -1);
|
||||||
put(IASTORE, -1);
|
put(IASTORE, -3);
|
||||||
put(LASTORE, -1);
|
put(LASTORE, -3);
|
||||||
put(FASTORE, -1);
|
put(FASTORE, -3);
|
||||||
put(DASTORE, -1);
|
put(DASTORE, -3);
|
||||||
put(AASTORE, -1);
|
put(AASTORE, -3);
|
||||||
put(BASTORE, -1);
|
put(BASTORE, -3);
|
||||||
put(CASTORE, -1);
|
put(CASTORE, -3);
|
||||||
put(SASTORE, -1);
|
put(SASTORE, -3);
|
||||||
put(POP, -1);
|
put(POP, -1);
|
||||||
put(POP2, -2);
|
put(POP2, -2);
|
||||||
put(DUP, 1);
|
put(DUP, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user