• 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 public 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 
42   @Override
getReturnType()43   public Type getReturnType() {
44     return Type.getReturnType(desc);
45   }
46 
47   /**
48    * Forces a return of a default value, depending on the method's return type
49    *
50    * @param type The method's return type
51    */
pushDefaultReturnValueToStack(Type type)52   public void pushDefaultReturnValueToStack(Type type) {
53     if (type.equals(Type.BOOLEAN_TYPE)) {
54       push(false);
55     } else if (type.equals(Type.INT_TYPE) || type.equals(Type.SHORT_TYPE) || type.equals(Type.BYTE_TYPE) || type.equals(Type.CHAR_TYPE)) {
56       push(0);
57     } else if (type.equals(Type.LONG_TYPE)) {
58       push(0L);
59     } else if (type.equals(Type.FLOAT_TYPE)) {
60       push(0f);
61     } else if (type.equals(Type.DOUBLE_TYPE)) {
62       push(0d);
63     } else if (type.getSort() == ARRAY || type.getSort() == OBJECT) {
64       loadNull();
65     }
66   }
67 
invokeMethod(String internalClassName, MethodNode method)68   public void invokeMethod(String internalClassName, MethodNode method) {
69     invokeMethod(internalClassName, method.name, method.desc);
70   }
71 
invokeMethod(String internalClassName, String methodName, String methodDesc)72   void invokeMethod(String internalClassName, String methodName, String methodDesc) {
73     if (isStatic()) {
74       loadArgs();                                             // this, [args]
75       visitMethodInsn(Opcodes.INVOKESTATIC, internalClassName, methodName, methodDesc, false);
76     } else {
77       loadThisOrNull();                                       // this
78       loadArgs();                                             // this, [args]
79       visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, methodName, methodDesc, false);
80     }
81   }
82 
tryStart(Type exceptionType)83   public TryCatch tryStart(Type exceptionType) {
84     return new TryCatch(this, exceptionType);
85   }
86 }
87