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

org.mockito.internal.ValueClassWrapper.scala Maven / Gradle / Ivy

package org.mockito.internal

import org.mockito.internal.MacroDebug.debugResult

import scala.reflect.ClassTag
import scala.reflect.macros.blackbox

trait ValueClassWrapper[VC] extends Serializable {
  def isValueClass: Boolean = true
  def wrap(vc: VC): Any
  def wrapAs[T](vc: VC): T = wrap(vc).asInstanceOf[T]
}

class NormalClassWrapper[T] extends ValueClassWrapper[T] {
  override def isValueClass: Boolean = false
  override def wrap(vc: T): Any      = vc
}

class ReflectionWrapper[VC: ClassTag] extends ValueClassWrapper[VC] {
  private def clazz[T](implicit classTag: ClassTag[T]): Class[T] = classTag.runtimeClass.asInstanceOf[Class[T]]

  override def wrap(vc: VC): Any =
    clazz.getConstructors
      .collectFirst {
        case c if c.getParameterCount == 1 => c.newInstance(vc.asInstanceOf[Object])
      }
      .getOrElse(throw new RuntimeException(s"Can't find a constructor for $clazz that takes a single param"))
}

object ValueClassWrapper {
  def apply[T: ValueClassWrapper]: ValueClassWrapper[T] = implicitly[ValueClassWrapper[T]]

  implicit def instance[VC]: ValueClassWrapper[VC] = macro materialise[VC]

  def materialise[VC: c.WeakTypeTag](c: blackbox.Context): c.Expr[ValueClassWrapper[VC]] = {
    import c.universe._
    val tpe          = weakTypeOf[VC]
    val typeSymbol   = tpe.typeSymbol
    val isValueClass = typeSymbol.isClass && typeSymbol.asClass.isDerivedValueClass

    val r =
      if (isValueClass)
        c.Expr[ValueClassWrapper[VC]](q"new _root_.org.mockito.internal.ReflectionWrapper[$tpe]")
      else
        c.Expr[ValueClassWrapper[VC]](q"new _root_.org.mockito.internal.NormalClassWrapper[$tpe]")

    debugResult(c)("mockito-print-wrapper")(r.tree)

    r
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy