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