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.
Implicit parameters are the parameters that are passed to a function with implicit keyword in Scala, which means the values will be taken from the context in which they are called.
When an implicit value is required, the Scala compiler would first look into the current scope to find the required implicit value that can act as a function for the type conversion required. The current scope used as implicit scope include: Local scope.
Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class's primary constructor available for implicit conversions when the class is in scope. Implicit classes were proposed in SIP-13.
In Scala, objects and values are treated mostly the same. An implicit object can be thought of as a value which is found in the process of looking up an implicit of its type.
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.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With