1 package org.robolectric.internal.bytecode; 2 3 import static org.objectweb.asm.Type.ARRAY; 4 import static org.objectweb.asm.Type.OBJECT; 5 6 import java.lang.reflect.Modifier; 7 import org.objectweb.asm.Opcodes; 8 import org.objectweb.asm.Type; 9 import org.objectweb.asm.commons.GeneratorAdapter; 10 import org.objectweb.asm.tree.MethodNode; 11 import org.robolectric.internal.bytecode.ClassInstrumentor.TryCatch; 12 13 /** 14 * GeneratorAdapter implementation specific to generate code for Robolectric purposes 15 */ 16 class RobolectricGeneratorAdapter extends GeneratorAdapter { 17 final boolean isStatic; 18 private final String desc; 19 RobolectricGeneratorAdapter(MethodNode methodNode)20 public RobolectricGeneratorAdapter(MethodNode methodNode) { 21 super(Opcodes.ASM4, methodNode, methodNode.access, methodNode.name, methodNode.desc); 22 this.isStatic = Modifier.isStatic(methodNode.access); 23 this.desc = methodNode.desc; 24 } 25 loadThisOrNull()26 public void loadThisOrNull() { 27 if (isStatic) { 28 loadNull(); 29 } else { 30 loadThis(); 31 } 32 } 33 isStatic()34 public boolean isStatic() { 35 return isStatic; 36 } 37 loadNull()38 public void loadNull() { 39 visitInsn(Opcodes.ACONST_NULL); 40 } 41 getReturnType()42 public Type getReturnType() { 43 return Type.getReturnType(desc); 44 } 45 46 /** 47 * Forces a return of a default value, depending on the method's return type 48 * 49 * @param type The method's return type 50 */ pushDefaultReturnValueToStack(Type type)51 public void pushDefaultReturnValueToStack(Type type) { 52 if (type.equals(Type.BOOLEAN_TYPE)) { 53 push(false); 54 } else if (type.equals(Type.INT_TYPE) || type.equals(Type.SHORT_TYPE) || type.equals(Type.BYTE_TYPE) || type.equals(Type.CHAR_TYPE)) { 55 push(0); 56 } else if (type.equals(Type.LONG_TYPE)) { 57 push(0L); 58 } else if (type.equals(Type.FLOAT_TYPE)) { 59 push(0f); 60 } else if (type.equals(Type.DOUBLE_TYPE)) { 61 push(0d); 62 } else if (type.getSort() == ARRAY || type.getSort() == OBJECT) { 63 loadNull(); 64 } 65 } 66 invokeMethod(String internalClassName, MethodNode method)67 void invokeMethod(String internalClassName, MethodNode method) { 68 invokeMethod(internalClassName, method.name, method.desc); 69 } 70 invokeMethod(String internalClassName, String methodName, String methodDesc)71 void invokeMethod(String internalClassName, String methodName, String methodDesc) { 72 if (isStatic()) { 73 loadArgs(); // this, [args] 74 visitMethodInsn(Opcodes.INVOKESTATIC, internalClassName, methodName, methodDesc, false); 75 } else { 76 loadThisOrNull(); // this 77 loadArgs(); // this, [args] 78 visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, methodName, methodDesc, false); 79 } 80 } 81 tryStart(Type exceptionType)82 public TryCatch tryStart(Type exceptionType) { 83 return new TryCatch(this, exceptionType); 84 } 85 } 86