All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.internal.bytecode.ShadowImpl Maven / Gradle / Ivy

The newest version!
package org.robolectric.internal.bytecode;

import java.lang.reflect.InvocationTargetException;
import org.robolectric.internal.IShadow;
import org.robolectric.util.ReflectionHelpers;

public class ShadowImpl implements IShadow {

  private final ProxyMaker proxyMaker = new ProxyMaker(this::directMethodName);

  @Override
  @SuppressWarnings("TypeParameterUnusedInFormals")
  public  T extract(Object instance) {
    return (T) ((ShadowedObject) instance).$$robo$getData();
  }

  @Override
  public  T newInstanceOf(Class clazz) {
    return ReflectionHelpers.callConstructor(clazz);
  }

  @Override
  public  T newInstance(Class clazz, Class[] parameterTypes, Object[] params) {
    return ReflectionHelpers.callConstructor(
        clazz, ReflectionHelpers.ClassParameter.fromComponentLists(parameterTypes, params));
  }

  /**
   * Returns a proxy object that invokes the original $$robo$$-prefixed methods for {@code
   * shadowedObject}.
   *
   * @deprecated This is incompatible with JDK17+. Use a {@link
   *     org.robolectric.util.reflector.Reflector} interface with {@link
   *     org.robolectric.util.reflector.Direct}.
   */
  @Deprecated
  @Override
  public  T directlyOn(T shadowedObject, Class clazz) {
    return createProxy(shadowedObject, clazz);
  }

  @Override
  @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
  public  R directlyOn(
      Object shadowedObject,
      String clazzName,
      String methodName,
      ReflectionHelpers.ClassParameter... paramValues) {
    try {
      Class aClass =
          (Class) shadowedObject.getClass().getClassLoader().loadClass(clazzName);
      return directlyOn(shadowedObject, aClass, methodName, paramValues);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
  public  R directlyOn(
      T shadowedObject,
      Class clazz,
      String methodName,
      ReflectionHelpers.ClassParameter... paramValues) {
    String directMethodName = directMethodName(clazz.getName(), methodName);
    return (R)
        ReflectionHelpers.callInstanceMethod(clazz, shadowedObject, directMethodName, paramValues);
  }

  @Override
  @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
  public  R directlyOn(
      Class clazz, String methodName, ReflectionHelpers.ClassParameter... paramValues) {
    String directMethodName = directMethodName(clazz.getName(), methodName);
    return (R) ReflectionHelpers.callStaticMethod(clazz, directMethodName, paramValues);
  }

  private  T createProxy(T shadowedObject, Class clazz) {
    return proxyMaker.createProxy(clazz, shadowedObject);
  }

  @Override
  @SuppressWarnings(value = {"unchecked", "TypeParameterUnusedInFormals"})
  public  R invokeConstructor(
      Class clazz, R instance, ReflectionHelpers.ClassParameter... paramValues) {
    String directMethodName =
        directMethodName(clazz.getName(), ShadowConstants.CONSTRUCTOR_METHOD_NAME);
    return (R) ReflectionHelpers.callInstanceMethod(clazz, instance, directMethodName, paramValues);
  }

  @Override
  public String directMethodName(String className, String methodName) {
    return ShadowConstants.ROBO_PREFIX
        + className.replace('.', '_').replace('$', '_')
        + "$"
        + methodName;
  }

  @Override
  public String directNativeMethodName(String className, String methodName) {
    return ShadowConstants.ROBO_PREFIX + methodName + "$nativeBinding";
  }

  @Override
  public void directInitialize(Class clazz) {
    try {
      RobolectricInternals.performStaticInitialization(clazz);
    } catch (InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("failed to initialize " + clazz, e);
    }
  }
}