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

com.softwaremill.macwire.akkasupport.internals.Crimper.scala Maven / Gradle / Ivy

The newest version!
package com.softwaremill.macwire.akkasupport.internals

import akka.actor.{ActorRef, ActorRefFactory, IndirectActorProducer, Props}
import com.softwaremill.macwire.internals.{ConstructorCrimper, Logger, DependencyResolver}

import scala.reflect.macros.blackbox

private[macwire] final class Crimper[C <: blackbox.Context, T: C#WeakTypeTag](val c: C, log: Logger) {
  import c.universe._
  lazy val dependencyResolver = DependencyResolver.throwErrorOnResolutionFailure[c.type, Type, Tree](c, log)
  lazy val cc = new ConstructorCrimper[c.type, T](c, new Logger)(implicitly[c.type#WeakTypeTag[T]])

  lazy val targetType: Type = cc.targetType

  lazy val args: List[Tree] = cc
    .constructorArgsWithImplicitLookups(dependencyResolver)
    .getOrElse(c.abort(c.enclosingPosition, s"Cannot find a public constructor for [$targetType]"))
    .flatten

  lazy val propsTree = q"akka.actor.Props(classOf[$targetType], ..$args)"

  lazy val wireProps: c.Expr[Props] = log.withBlock(s"wireProps[$targetType]: at ${c.enclosingPosition}") {
    log("Generated code: " + showRaw(propsTree))
    c.Expr[Props](propsTree)
  }

  lazy val actorRefFactoryTree: Tree = log.withBlock("Looking for ActorRefFactory") {
    val actorRefType = typeOf[ActorRefFactory]
    val tree = dependencyResolver.resolve(actorRefType.typeSymbol, actorRefType)
    log(s"Found ${showCode(tree)}")
    tree
  }

  lazy val wireAnonymousActor: c.Expr[ActorRef] = log.withBlock(
    s"Constructing ActorRef. Trying to find arguments for constructor of: [$targetType] at ${c.enclosingPosition}"
  ) {
    val tree = q"$actorRefFactoryTree.actorOf($propsTree)"
    log("Generated code: " + showRaw(tree))
    c.Expr[ActorRef](tree)
  }

  def wireActor(name: c.Expr[String]): c.Expr[ActorRef] =
    log.withBlock(s"wireActor[$targetType]: at ${c.enclosingPosition}") {
      val tree = q"$actorRefFactoryTree.actorOf($propsTree, ${name.tree})"
      log("Generated code: " + showRaw(tree))
      c.Expr[ActorRef](tree)
    }

  lazy val wirePropsWithProducer: c.Expr[Props] = weakTypeOf[T] match {
    case t if t <:< typeOf[IndirectActorProducer] => wireProps
    case _ => c.abort(c.enclosingPosition, s"wirePropsWith does not support the type: [$targetType]")
  }

  lazy val wireAnonymousActorWithProducer: c.Expr[ActorRef] = weakTypeOf[T] match {
    case t if t <:< typeOf[IndirectActorProducer] => wireAnonymousActor
    case _ => c.abort(c.enclosingPosition, s"wireAnonymousActorWith does not support the type: [$targetType]")
  }

  def wireActorWithProducer(name: c.Expr[String]): c.Expr[ActorRef] = weakTypeOf[T] match {
    case t if t <:< typeOf[IndirectActorProducer] => wireActor(name)
    case _ => c.abort(c.enclosingPosition, s"wireActorWith does not support the type: [$targetType]")
  }

  def wirePropsWithFactory(factory: c.Tree): c.Expr[Props] =
    log.withBlock(s"wireProps[$targetType]: at ${c.enclosingPosition}") {
      import com.softwaremill.macwire.MacwireMacros._

      val funTree = wireWith_impl(c)(factory)
      val propsTree = q"akka.actor.Props($funTree)"
      log("Generated code: " + showRaw(propsTree))
      c.Expr[Props](propsTree)
    }

  def wireAnonymousActorWithFactory(factory: c.Tree): c.Expr[ActorRef] = log.withBlock(
    s"Constructing ActorRef. Trying to find arguments for constructor of: [$targetType] at ${c.enclosingPosition}"
  ) {
    import com.softwaremill.macwire.MacwireMacros._

    val funTree = wireWith_impl(c)(factory)
    val propsTree = q"akka.actor.Props($funTree)"
    val tree = q"$actorRefFactoryTree.actorOf($propsTree)"
    log("Generated code: " + showRaw(tree))
    c.Expr[ActorRef](tree)
  }

  def wireActorWithFactory(factory: c.Tree)(name: c.Expr[String]): c.Expr[ActorRef] =
    log.withBlock(s"wireActorWithProducer[$targetType]: at ${c.enclosingPosition}") {
      import com.softwaremill.macwire.MacwireMacros._

      val funTree = wireWith_impl(c)(factory)
      val propsTree = q"akka.actor.Props($funTree)"
      val tree = q"$actorRefFactoryTree.actorOf($propsTree, ${name.tree})"
      log("Generated code: " + showRaw(tree))
      c.Expr[ActorRef](tree)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy