问题
Short question:
Is there a way to ask the scala compiler to tell me where a certain implicit used at a given point in a program was declared ?
If not, is there an algorithm that I can follow manually to find out myself where an implicit was declared ?
Long question:
I am following simple spray crud tutorial.
In the code snippet below (coming the this repo for the tutorial):
pathEnd {
post {
entity(as[Question]) { question =>
completeWithLocationHeader(
resourceId = questionService.createQuestion(question),
ifDefinedStatus = 201, ifEmptyStatus = 409)
}
}
} ~
as
takes an implicit of type FromRequestUnmarshaller[T]
(full source here):
def as[T](implicit um: FromRequestUnmarshaller[T]) = um
and when I ask IntelliJ where this implicit comes from (using CMD+SHIFT+P), I get:
and when I follow the first hint I get this:
trait UnmarshallerLifting {
implicit def fromRequestUnmarshaller[T](implicit um: FromMessageUnmarshaller[T]): FromRequestUnmarshaller[T] =
new FromRequestUnmarshaller[T] {
def apply(request: HttpRequest): Deserialized[T] = um(request)
}
...
this does not help me to figure out where the implicit FromRequestUnmarshaller[T]
comes from because I cannot figure out how the trait UnmarshallerLifting
gets mixed into QuestionResource
if I inspect the class hierarchy:
I inspect the traits that look like they might contain this implict, for example this trait,but it does not contain the implicit:
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
after looking at 20 different places I become frustrated.
Is there a way to ask the scala compiler to tell me where a certain implicit (in this example FromRequestUnmarshaller[T]
) used at a given point in a program (in this example here) was declared ?
If not, is there an algorithm that I can follow manually to find out myself where an implicit was declared ?
I looked for this question on Google/SOF but the hints I found did not help. I also went through this and I still don't know where the FromRequestUnmarshaller[T]
comes from.
回答1:
Typically I enable -Xlog-implicits
in compiler to see what's going on with implicits.
Also spray is deprecated in favor of akka-http. I recommend to switch.
回答2:
I did this (as suggested in Michael's comment):
import scala.reflect.runtime.universe.reify
println(reify(entity(as[Question])))
It printed:
Expr[spray.routing.Directive1[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question]](QuestionResource.entity(QuestionResource.as[Question](Deserializer.fromRequestUnmarshaller(Deserializer.fromMessageUnmarshaller(QuestionResource.json4sUnmarshaller(ManifestFactory.classType(classOf[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question])))))))
This tells directly where the implicit is coming from : Deserializer.fromRequestUnmarshaller
Also, here is an other way, by using InteliJ's search usage function:
来源:https://stackoverflow.com/questions/41382408/how-can-i-locate-where-an-implicit-comes-from-in-scala