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

com.softwaremill.macwire.internals.DependencyResolver.scala Maven / Gradle / Ivy

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

import com.softwaremill.macwire.internals.EligibleValuesFinder.Scope.LocalForward

import scala.reflect.macros.blackbox

class DependencyResolver[C <: blackbox.Context, TypeC <: C#Type, TreeC <: C#Tree](val c: C, debug: Logger)(
    resolutionFallback: TypeC => TreeC
) {

  import c.universe._

  private val eligibleValuesFinder = new EligibleValuesFinder[c.type](c, debug)

  private lazy val eligibleValues = eligibleValuesFinder.find()

  /** Look for a single instance of type `t`. If either no instance or multiple instances are found, a compilation error
    * is reported and `None` is returned.
    */
  def resolve(param: Symbol, t: Type): Tree = {
    eligibleValues.findInFirstScope(t).toList match {
      case Nil => resolutionFallback(t.asInstanceOf[TypeC]).asInstanceOf[Tree]
      case value :: Nil =>
        val forwardValues = eligibleValues.findInScope(t, LocalForward)
        if (forwardValues.nonEmpty) {
          c.warning(
            c.enclosingPosition,
            s"Found [$value] for parameter [${param.name}], " +
              s"but a forward reference [${forwardValues.mkString(", ")}] was also eligible"
          )
        }
        value
      case values => c.abort(c.enclosingPosition, s"Found multiple values of type [$t]: [$values]")
    }
  }

  /** @return
    *   all the instances of type `t` that are accessible.
    */
  def resolveAll(t: Type): Iterable[Tree] = {
    eligibleValues.findInAllScope(t)
  }
}

object DependencyResolver {
  def throwErrorOnResolutionFailure[C <: blackbox.Context, TypeC <: C#Type, TreeC <: C#Tree](c: C, debug: Logger) =
    new DependencyResolver[C, TypeC, TreeC](c, debug)(t =>
      c.abort(c.enclosingPosition, s"Cannot find a value of type: [$t]")
    )
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy