• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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