• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.internal.bytecode;
2 
3 import java.lang.invoke.MethodHandle;
4 import java.lang.invoke.MethodType;
5 
6 /**
7  * This interface is used by Robolectric when instrumented classes are created and interacted with.
8  */
9 public interface ClassHandler {
10 
11   /**
12    * Called by Robolectric when an instrumented class is first loaded into a sandbox and is ready
13    * to be statically initialized.
14    *
15    * This happens *in place of* any static initialization that may be performed by the class being
16    * loaded. The class will have a method named `__staticInitializer__` which may be invoked to
17    * perform its normal initialization from `<clinit>`.
18    *
19    * @param clazz the class being loaded
20    */
classInitializing(Class clazz)21   void classInitializing(Class clazz);
22 
23   /**
24    * Called by Robolectric when a new instance of an instrumented class has been created and is
25    * ready to be initialized (but only on JVMs which don't support the `invokedynamic` instruction).
26    *
27    * This happens before constructor code executes on the new instance.
28    *
29    * Implementations may return an object which will be associated with the new instance and passed
30    * along on future calls to {@link #methodInvoked(String, boolean, Class)}.
31    *
32    * @param instance the newly-created instance
33    * @return a data value to be associated with the new instance
34    * @see #getShadowCreator(Class) for newer JVMs
35    */
initializing(Object instance)36   Object initializing(Object instance);
37 
38   /**
39    * Called by Robolectric when an instrumented method is invoked.
40    *
41    * Implementations should return an {@link Plan}, which will be invoked with details about the
42    * current instance and parameters.
43    *
44    * Implementations may also return `null`, in which case the method's original code will be
45    * executed.
46    *
47    * @param signature the JVM internal-format signature of the method being invoked (e.g.
48    *                  `android/view/View/measure(II)V`)
49    * @param isStatic true if the method is static
50    * @param theClass the class on which the method is declared
51    * @return an execution plan, or `null` if the original method's code should be executed
52    * @see #findShadowMethodHandle(Class, String, MethodType, boolean) for newer JVMs
53    */
methodInvoked(String signature, boolean isStatic, Class<?> theClass)54   Plan methodInvoked(String signature, boolean isStatic, Class<?> theClass);
55 
56   /**
57    * Called by Robolectric to determine how to create and initialize a shadow object when a new
58    * instance of an instrumented class has been instantiated. (but only on JVMs which support the
59    * `invokedynamic` instruction).
60    *
61    * The returned {@link MethodHandle} will be invoked after the new object has been allocated
62    * but before its constructor code is executed.
63    *
64    * Note that this is not directly analogous to {@link #initializing(Object)}; the return value
65    * from this method will be cached and used again for other instantiations of instances of the
66    * same class.
67    *
68    * @param theClass the instrumented class
69    * @return a data value to be associated with the new instance
70    * @see #getShadowCreator(Class) for older JVMs
71    * @see ShadowInvalidator for invalidating the returned {@link MethodHandle}
72    */
getShadowCreator(Class<?> theClass)73   MethodHandle getShadowCreator(Class<?> theClass);
74 
75   /**
76    * Called by Robolectric when an instrumented method is invoked.
77    *
78    * Implementations should return an {@link MethodHandle}, which will be invoked with details about
79    * the current instance and parameters.
80    *
81    * Implementations may also return `null`, in which case the method's original code will be
82    * executed.
83    *
84    * @param theClass the class on which the method is declared
85    * @param name the name of the method
86    * @param methodType the method type
87    * @param isStatic true if the method is static
88    * @return a method handle to invoke, or `null` if the original method's code should be executed
89    * @see #methodInvoked(String, boolean, Class) for older JVMs
90    * @see ShadowInvalidator for invalidating the returned {@link MethodHandle}
91    */
findShadowMethodHandle(Class<?> theClass, String name, MethodType methodType, boolean isStatic)92   MethodHandle findShadowMethodHandle(Class<?> theClass, String name, MethodType methodType,
93       boolean isStatic) throws IllegalAccessException;
94 
95   /**
96    * Called by Robolectric when an intercepted method is invoked.
97    *
98    * Unlike instrumented methods, calls to intercepted methods are modified in place by Robolectric
99    * in the calling code. This is useful when the method about to be invoked doesn't exist in the
100    * current JVM (e.g. because of Android differences).
101    *
102    * @param signature the JVM internal-format signature of the method being invoked (e.g.
103    *                  `android/view/View/measure(II)V`)
104    * @param instance the instance on which the method would have been invoked
105    * @param params the parameters to the method
106    * @param theClass the class on which the method is declared
107    * @return the value to be returned
108    * @throws Throwable if anything bad happens
109    */
intercept(String signature, Object instance, Object[] params, Class<?> theClass)110   Object intercept(String signature, Object instance, Object[] params, Class<?> theClass)
111       throws Throwable;
112 
113   /**
114    * Removes Robolectric noise from stack traces.
115    *
116    * @param throwable the exception to be stripped
117    * @param <T> the type of exception
118    * @return the stripped stack trace
119    */
stripStackTrace(T throwable)120   <T extends Throwable> T stripStackTrace(T throwable);
121 
122   /**
123    * An execution plan, which can be invoked to satisfy a requested method call.
124    */
125   interface Plan {
126 
run(Object instance, Object[] params)127     Object run(Object instance, Object[] params) throws Throwable;
128 
describe()129     String describe();
130   }
131 }
132