• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.internal.bytecode;
2 
3 import com.google.auto.service.AutoService;
4 import javax.annotation.Priority;
5 import org.objectweb.asm.Opcodes;
6 import org.objectweb.asm.Type;
7 import org.objectweb.asm.tree.FieldNode;
8 import org.objectweb.asm.tree.MethodNode;
9 
10 /** Decorator which adds Robolectric's shadowing behavior to a class. */
11 @AutoService(ClassInstrumentor.Decorator.class)
12 @Priority(Integer.MIN_VALUE)
13 public class ShadowDecorator implements ClassInstrumentor.Decorator {
14   private static final String OBJECT_DESC = Type.getDescriptor(Object.class);
15   private static final Type OBJECT_TYPE = Type.getType(Object.class);
16   private static final String GET_ROBO_DATA_SIGNATURE = "()Ljava/lang/Object;";
17 
18   @Override
decorate(MutableClass mutableClass)19   public void decorate(MutableClass mutableClass) {
20     mutableClass.addInterface(Type.getInternalName(ShadowedObject.class));
21 
22     mutableClass.addField(
23         0,
24         new FieldNode(
25             Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT,
26             ShadowConstants.CLASS_HANDLER_DATA_FIELD_NAME,
27             OBJECT_DESC,
28             OBJECT_DESC,
29             null));
30 
31     addRoboGetDataMethod(mutableClass);
32   }
33 
addRoboGetDataMethod(MutableClass mutableClass)34   private void addRoboGetDataMethod(MutableClass mutableClass) {
35     MethodNode initMethodNode =
36         new MethodNode(
37             Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
38             ShadowConstants.GET_ROBO_DATA_METHOD_NAME,
39             GET_ROBO_DATA_SIGNATURE,
40             null,
41             null);
42     RobolectricGeneratorAdapter generator = new RobolectricGeneratorAdapter(initMethodNode);
43     generator.loadThis(); // this
44     generator.getField(
45         mutableClass.classType,
46         ShadowConstants.CLASS_HANDLER_DATA_FIELD_NAME,
47         OBJECT_TYPE); // contents of __robo_data__
48     generator.returnValue();
49     generator.endMethod();
50     mutableClass.addMethod(initMethodNode);
51   }
52 }
53