• 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 /** 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