Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue225 #259

Merged
merged 18 commits into from May 2, 2019
@@ -77,10 +77,11 @@ object Http4sServerGenerator {
case GetExtraRouteParams(tracing) =>
for {
_ <- Target.log.debug("Http4sServerGenerator", "server")(s"getExtraRouteParams(${tracing})")
res <- if (tracing) {
handlerWrapper = param"""handlerWrapper: (String, Request[F], F[Response[F]]) => F[Response[F]] = (_, _, r) => r"""
tracing <- if (tracing) {
Target.pure(List(param"""trace: String => Request[F] => TraceBuilder[F]"""))
} else Target.pure(List.empty)
} yield res
} yield handlerWrapper :: tracing

case GenerateSupportDefinitions(tracing) =>
Target.pure(List.empty)
@@ -501,8 +502,14 @@ object Http4sServerGenerator {
case Nil => responseInMatch
case generators => q"for {..${generators :+ enumerator"response <- $responseInMatch"}} yield response"
}
val routeBody = entityProcessor.fold[Term](responseInMatchInFor)(_.apply(responseInMatchInFor))
val fullRoute: Case = p"case req @ $fullRouteWithTracingMatcher => $routeBody"
val routeBody = entityProcessor.fold[Term](responseInMatchInFor)(_.apply(responseInMatchInFor))
val fullRoute: Case =
p"""case req @ $fullRouteWithTracingMatcher =>
val response = {
This conversation was marked as resolved by tomasherman

This comment has been minimized.

Copy link
@blast-hardcheese

blast-hardcheese Apr 28, 2019

Collaborator

This is really good -- The one consideration is that we are trying to reduce top-level bindings inside of an individual route. The way things are written currently, parameters named response will now conflict.

This comment has been minimized.

Copy link
@tomasherman

tomasherman Apr 28, 2019

Author Contributor

good point, i can skip the val response and just add the computation into the tuple directly, i did it this way to make the code nicer but it's not required to be this way

$routeBody
}
handlerWrapper($operationId, req, response)
"""

val respond: List[List[Term.Param]] = List(List(param"respond: $responseCompanionTerm.type"))

@@ -48,24 +48,33 @@ class Issue165 extends FunSuite with Matchers with SwaggerSpecRunner {
}
"""
val resource = q"""
class StoreResource[F[_]]()(implicit F: Async[F]) extends Http4sDsl[F] {
class StoreResource[F[_]](handlerWrapper: (String, Request[F], F[Response[F]]) => F[Response[F]] = (_, _, r) => r)(implicit F: Async[F]) extends Http4sDsl[F] {
def routes(handler: StoreHandler[F]): HttpRoutes[F] = HttpRoutes.of {
{
case req @ GET -> Root =>
handler.getRoot(GetRootResponse)() flatMap {
case GetRootResponse.Ok =>
Ok()
}
val response = {
handler.getRoot(GetRootResponse)() flatMap {
case GetRootResponse.Ok =>
Ok()
}
}
handlerWrapper("getRoot", req, response)
case req @ GET -> Root / "foo" =>
handler.getFoo(GetFooResponse)() flatMap {
case GetFooResponse.Ok =>
Ok()
val response = {
handler.getFoo(GetFooResponse)() flatMap {
case GetFooResponse.Ok =>
Ok()
}
}
handlerWrapper("getFoo", req, response)
case req @ GET -> Root / "foo" / "" =>
handler.getFooDir(GetFooDirResponse)() flatMap {
case GetFooDirResponse.Ok =>
Ok()
}
val response = {
handler.getFooDir(GetFooDirResponse)() flatMap {
case GetFooDirResponse.Ok =>
Ok()
}
}
handlerWrapper("getFooDir", req, response)
}
}
}
@@ -0,0 +1,61 @@
package core.issues

import com.twilio.guardrail.generators.Http4s
import com.twilio.guardrail.{ Context, Server, Servers }
import org.scalatest.{ FunSuite, Matchers }
import support.SwaggerSpecRunner

class Issue225 extends FunSuite with Matchers with SwaggerSpecRunner {

import scala.meta._

val swagger: String =
s"""
|swagger: '2.0'
|host: petstore.swagger.io
|paths:
| "/":
| get:
| operationId: getRoot
| responses:
| 200:
| description: description
|""".stripMargin

test("Ensure handlerWrapper is generated") {
val (_, _, Servers(Server(_, _, genHandler, genResource :: _) :: Nil, Nil)) = runSwaggerSpec(swagger)(Context.empty, Http4s)

val handler = q"""
trait Handler[F[_]] {
def getRoot(respond: GetRootResponse.type)(): F[GetRootResponse]
}
"""
val resource = q"""
class Resource[F[_]](handlerWrapper: (String, Request[F], F[Response[F]]) => F[Response[F]] = (_, _, r) => r)(implicit F: Async[F]) extends Http4sDsl[F] {
def routes(handler: Handler[F]): HttpRoutes[F] = HttpRoutes.of {
{
case req @ GET -> Root =>
val response = {
handler.getRoot(GetRootResponse)() flatMap {
case GetRootResponse.Ok =>
Ok()
}
}
handlerWrapper("getRoot", req, response)
}
}
}
"""

compare(genHandler, handler)

// Cause structure is slightly different but source code is the same the value converted to string and then parsed
compare(genResource.toString().parse[Stat].get, resource)
}

private def compare(actual: Tree, expected: Tree): Unit = {
println(s"actual: ${actual.syntax}")
This conversation was marked as resolved by tomasherman

This comment has been minimized.

Copy link
@blast-hardcheese

blast-hardcheese May 2, 2019

Collaborator

No printlns during normal operation please

This comment has been minimized.

Copy link
@tomasherman

tomasherman May 2, 2019

Author Contributor

sorry, leftover from debugging :)

println(s"expected: ${expected.syntax}")
actual.structure shouldEqual expected.structure
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.