如何在Scala中找到隐式的来源?

jhe*_*dus 5 scala intellij-idea implicit spray

简短问题:

有没有办法让scala编译器告诉我程序中给定点使用的某个隐式声明在哪里?

如果没有,是否可以手动遵循一种算法来找出隐式声明的位置?

长问题:

我正在遵循简单的Spray Crud 教程

在下面的代码片段中(作为教程的仓库):

pathEnd {
  post {
    entity(as[Question]) { question =>
      completeWithLocationHeader(
        resourceId = questionService.createQuestion(question),
        ifDefinedStatus = 201, ifEmptyStatus = 409)
      }
    }
} ~
Run Code Online (Sandbox Code Playgroud)

as接受一个隐式类型FromRequestUnmarshaller[T]此处为完整资料):

  def as[T](implicit um: FromRequestUnmarshaller[T]) = um
Run Code Online (Sandbox Code Playgroud)

当我问IntelliJ时,这个隐式是从哪里来的(使用CMD + SHIFT + P),我得到:

在此处输入图片说明 当我遵循第一个提示时,我得到了:

trait UnmarshallerLifting {

  implicit def fromRequestUnmarshaller[T](implicit um: FromMessageUnmarshaller[T]): FromRequestUnmarshaller[T] =
    new FromRequestUnmarshaller[T] {
      def apply(request: HttpRequest): Deserialized[T] = um(request)
    }
...
Run Code Online (Sandbox Code Playgroud)

这并不能帮助我确定隐式FromRequestUnmarshaller[T]函数的来源,因为如果我检查类层次结构,就无法确定特征是如何UnmarshallerLifting混合的QuestionResource

在此处输入图片说明

我检查了看起来可能包含此隐含特征的特征,例如,特征,但其中不包含隐含特征:

trait MarshallingDirectives {
  import BasicDirectives._
  import MiscDirectives._
  import RouteDirectives._

  /**
   * Unmarshalls the requests entity to the given type passes it to its inner Route.
   * If there is a problem with unmarshalling the request is rejected with the [[spray.routing.Rejection]]
   * produced by the unmarshaller.
   */
  def entity[T](um: FromRequestUnmarshaller[T]): Directive1[T] =
    extract(_.request.as(um)).flatMap[T :: HNil] {
      case Right(value)                            ? provide(value)
      case Left(ContentExpected)                   ? reject(RequestEntityExpectedRejection)
      case Left(UnsupportedContentType(supported)) ? reject(UnsupportedRequestContentTypeRejection(supported))
      case Left(MalformedContent(errorMsg, cause)) ? reject(MalformedRequestContentRejection(errorMsg, cause))
    } & cancelAllRejections(ofTypes(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection]))

  /**
   * Returns the in-scope FromRequestUnmarshaller for the given type.
   */
  def as[T](implicit um: FromRequestUnmarshaller[T]) = um

  /**
   * Uses the marshaller for the given type to produce a completion function that is passed to its inner route.
   * You can use it do decouple marshaller resolution from request completion.
   */
  def produce[T](marshaller: ToResponseMarshaller[T]): Directive[(T ? Unit) :: HNil] =
    extract { ctx ? (value: T) ? ctx.complete(value)(marshaller) } & cancelAllRejections(ofType[UnacceptedResponseContentTypeRejection])

  /**
   * Returns the in-scope Marshaller for the given type.
   */
  def instanceOf[T](implicit m: ToResponseMarshaller[T]) = m

  /**
   * Completes the request using the given function. The input to the function is produced with the in-scope
   * entity unmarshaller and the result value of the function is marshalled with the in-scope marshaller.
   */
  def handleWith[A, B](f: A ? B)(implicit um: FromRequestUnmarshaller[A], m: ToResponseMarshaller[B]): Route =
    entity(um) { a ? RouteDirectives.complete(f(a)) }
}

object MarshallingDirectives extends MarshallingDirectives
Run Code Online (Sandbox Code Playgroud)

看了20个不同的地方后,我感到沮丧。

有没有办法问Scala编译器告诉我哪里有一定隐含的(在这个例子FromRequestUnmarshaller[T]在程序给定的点使用)(在这个例子在这里)被宣布?

如果没有,是否可以手动遵循一种算法来找出隐式声明的位置?

我在Google / SOF上寻找了这个问题,但发现的提示没有帮助。我也经历了这一点,但我仍然不知道从哪里来FromRequestUnmarshaller[T]

exp*_*ert 4

通常我会-Xlog-implicits在编译器中启用以查看隐式发生了什么。

此外,spray 已被弃用,取而代之的是 akka-http。我建议切换。