summaryrefslogtreecommitdiff
path: root/cask
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2019-09-15 12:36:39 +0800
committerLi Haoyi <haoyi.sg@gmail.com>2019-09-15 12:36:39 +0800
commit0e098a93da94c251eb05d42bc7ef48394600508c (patch)
treeb4c3e7ec654e16aa50f149ce255ef187791461e7 /cask
parent38c6a84a0e8fbc3debb93bbacaf8c092e675ecb3 (diff)
downloadcask-0e098a93da94c251eb05d42bc7ef48394600508c.tar.gz
cask-0e098a93da94c251eb05d42bc7ef48394600508c.tar.bz2
cask-0e098a93da94c251eb05d42bc7ef48394600508c.zip
Break circular dependency by splitting `RouteEndpointMetadata` into its own file
Diffstat (limited to 'cask')
-rw-r--r--cask/src/cask/main/Decorators.scala23
-rw-r--r--cask/src/cask/main/Main.scala9
-rw-r--r--cask/src/cask/main/Routes.scala70
-rw-r--r--cask/src/cask/main/RoutesEndpointMetadata.scala68
-rw-r--r--cask/src/cask/package.scala2
5 files changed, 88 insertions, 84 deletions
diff --git a/cask/src/cask/main/Decorators.scala b/cask/src/cask/main/Decorators.scala
index 0a68cba..fb795ba 100644
--- a/cask/src/cask/main/Decorators.scala
+++ b/cask/src/cask/main/Decorators.scala
@@ -35,27 +35,28 @@ object Decorator{
* bindings passed from the router are aggregated with those from the `EndPoint` and
* used as the first argument list.
*/
- def invoke(ctx: Request,
- metadata: Routes.EndpointMetadata[_],
- routes: Routes,
- routeBindings: Map[String, String],
- remainingDecorators: List[RawDecorator],
- bindings: List[Map[String, Any]]): Router.Result[Any] = try {
+ def invoke[T](ctx: Request,
+ endpoint: Endpoint[_, _],
+ entryPoint: EntryPoint[T, _],
+ routes: T,
+ routeBindings: Map[String, String],
+ remainingDecorators: List[RawDecorator],
+ bindings: List[Map[String, Any]]): Router.Result[Any] = try {
remainingDecorators match {
case head :: rest =>
head.wrapFunction(
ctx,
- args => invoke(ctx, metadata, routes, routeBindings, rest, args :: bindings)
+ args => invoke(ctx, endpoint, entryPoint, routes, routeBindings, rest, args :: bindings)
.asInstanceOf[Router.Result[cask.model.Response.Raw]]
)
case Nil =>
- metadata.endpoint.wrapFunction(ctx, { (endpointBindings: Map[String, Any]) =>
- val mergedEndpointBindings = endpointBindings ++ routeBindings.mapValues(metadata.endpoint.wrapPathSegment)
+ endpoint.wrapFunction(ctx, { (endpointBindings: Map[String, Any]) =>
+ val mergedEndpointBindings = endpointBindings ++ routeBindings.mapValues(endpoint.wrapPathSegment)
val finalBindings = mergedEndpointBindings :: bindings
- metadata.entryPoint
- .asInstanceOf[EntryPoint[cask.main.Routes, cask.model.Request]]
+ entryPoint
+ .asInstanceOf[EntryPoint[T, cask.model.Request]]
.invoke(routes, ctx, finalBindings)
.asInstanceOf[Router.Result[Nothing]]
})
diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala
index fbcbff9..a5b4dc4 100644
--- a/cask/src/cask/main/Main.scala
+++ b/cask/src/cask/main/Main.scala
@@ -36,13 +36,13 @@ abstract class BaseMain{
lazy val routeList = for{
routes <- allRoutes
- route <- routes.caskMetadata.value.map(x => x: Routes.EndpointMetadata[_])
+ route <- routes.caskMetadata.value.map(x => x: EndpointMetadata[_])
} yield (routes, route)
lazy val routeTries = Seq("get", "put", "post", "websocket")
.map { method =>
- method -> DispatchTrie.construct[(Routes, Routes.EndpointMetadata[_])](0,
+ method -> DispatchTrie.construct[(Routes, EndpointMetadata[_])](0,
for ((route, metadata) <- routeList if metadata.endpoint.methods.contains(method))
yield (Util.splitPath(metadata.endpoint.path): collection.IndexedSeq[String], (route, metadata), metadata.endpoint.subpath)
)
@@ -91,7 +91,8 @@ abstract class BaseMain{
case Some(((routes, metadata), routeBindings, remaining)) =>
Decorator.invoke(
Request(exchange, remaining),
- metadata,
+ metadata.endpoint,
+ metadata.entryPoint.asInstanceOf[EntryPoint[Routes, _]],
routes,
routeBindings,
(mainDecorators ++ routes.decorators ++ metadata.decorators).toList,
@@ -123,7 +124,7 @@ abstract class BaseMain{
def handleEndpointError(exchange: HttpServerExchange,
routes: Routes,
- metadata: Routes.EndpointMetadata[_],
+ metadata: EndpointMetadata[_],
e: Router.Result.Error) = {
val statusCode = e match {
case _: Router.Result.Error.Exception => 500
diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala
index a6bdd65..be33581 100644
--- a/cask/src/cask/main/Routes.scala
+++ b/cask/src/cask/main/Routes.scala
@@ -1,84 +1,18 @@
package cask.main
-import cask.internal.Router.EntryPoint
-import scala.reflect.macros.blackbox.Context
import language.experimental.macros
-object Routes{
- case class EndpointMetadata[T](decorators: Seq[RawDecorator],
- endpoint: Endpoint[_, _],
- entryPoint: EntryPoint[T, _])
- case class RoutesEndpointsMetadata[T](value: EndpointMetadata[T]*)
- object RoutesEndpointsMetadata{
- implicit def initialize[T]: RoutesEndpointsMetadata[T] = macro initializeImpl[T]
- implicit def initializeImpl[T: c.WeakTypeTag](c: Context): c.Expr[RoutesEndpointsMetadata[T]] = {
- import c.universe._
- val router = new cask.internal.Router[c.type](c)
-
- val routeParts = for{
- m <- c.weakTypeOf[T].members
- annotations = m.annotations.filter(_.tree.tpe <:< c.weakTypeOf[Decorator[_, _]])
- if annotations.nonEmpty
- } yield {
- if(!(annotations.last.tree.tpe <:< weakTypeOf[Endpoint[_, _]])) c.abort(
- annotations.head.tree.pos,
- s"Last annotation applied to a function must be an instance of Endpoint, " +
- s"not ${annotations.last.tree.tpe}"
- )
- val allEndpoints = annotations.filter(_.tree.tpe <:< weakTypeOf[Endpoint[_, _]])
- if(allEndpoints.length > 1) c.abort(
- annotations.last.tree.pos,
- s"You can only apply one Endpoint annotation to a function, not " +
- s"${allEndpoints.length} in ${allEndpoints.map(_.tree.tpe).mkString(", ")}"
- )
-
- val annotObjects =
- for(annot <- annotations)
- yield q"new ${annot.tree.tpe}(..${annot.tree.children.tail})"
-
- val annotObjectSyms =
- for(_ <- annotations.indices)
- yield c.universe.TermName(c.freshName("annotObject"))
-
- val route = router.extractMethod(
- m.asInstanceOf[MethodSymbol],
- weakTypeOf[T],
- q"${annotObjectSyms.last}.convertToResultType",
- tq"cask.Request",
- annotObjectSyms.reverse.map(annotObjectSym => q"$annotObjectSym.getParamParser"),
- annotObjectSyms.reverse.map(annotObjectSym => tq"$annotObjectSym.InputTypeAlias")
- )
-
- val declarations =
- for((sym, obj) <- annotObjectSyms.zip(annotObjects))
- yield q"val $sym = $obj"
-
- val res = q"""{
- ..$declarations
- cask.main.Routes.EndpointMetadata(
- Seq(..${annotObjectSyms.dropRight(1)}),
- ${annotObjectSyms.last},
- $route
- )
- }"""
- res
- }
-
- c.Expr[RoutesEndpointsMetadata[T]](q"""cask.main.Routes.RoutesEndpointsMetadata(..$routeParts)""")
- }
- }
-}
trait Routes{
def decorators = Seq.empty[cask.main.RawDecorator]
- private[this] var metadata0: Routes.RoutesEndpointsMetadata[this.type] = null
+ private[this] var metadata0: RoutesEndpointsMetadata[this.type] = null
def caskMetadata =
if (metadata0 != null) metadata0
else throw new Exception("Routes not yet initialize")
- protected[this] def initialize()(implicit routes: Routes.RoutesEndpointsMetadata[this.type]): Unit = {
+ protected[this] def initialize()(implicit routes: RoutesEndpointsMetadata[this.type]): Unit = {
metadata0 = routes
}
}
diff --git a/cask/src/cask/main/RoutesEndpointMetadata.scala b/cask/src/cask/main/RoutesEndpointMetadata.scala
new file mode 100644
index 0000000..fa93a0c
--- /dev/null
+++ b/cask/src/cask/main/RoutesEndpointMetadata.scala
@@ -0,0 +1,68 @@
+package cask.main
+
+import cask.internal.Router.EntryPoint
+
+import language.experimental.macros
+import scala.reflect.macros.blackbox
+case class EndpointMetadata[T](decorators: Seq[RawDecorator],
+ endpoint: Endpoint[_, _],
+ entryPoint: EntryPoint[T, _])
+case class RoutesEndpointsMetadata[T](value: EndpointMetadata[T]*)
+object RoutesEndpointsMetadata{
+ implicit def initialize[T]: RoutesEndpointsMetadata[T] = macro initializeImpl[T]
+ implicit def initializeImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[RoutesEndpointsMetadata[T]] = {
+ import c.universe._
+ val router = new cask.internal.Router[c.type](c)
+
+ val routeParts = for{
+ m <- c.weakTypeOf[T].members
+ annotations = m.annotations.filter(_.tree.tpe <:< c.weakTypeOf[Decorator[_, _]])
+ if annotations.nonEmpty
+ } yield {
+ if(!(annotations.last.tree.tpe <:< weakTypeOf[Endpoint[_, _]])) c.abort(
+ annotations.head.tree.pos,
+ s"Last annotation applied to a function must be an instance of Endpoint, " +
+ s"not ${annotations.last.tree.tpe}"
+ )
+ val allEndpoints = annotations.filter(_.tree.tpe <:< weakTypeOf[Endpoint[_, _]])
+ if(allEndpoints.length > 1) c.abort(
+ annotations.last.tree.pos,
+ s"You can only apply one Endpoint annotation to a function, not " +
+ s"${allEndpoints.length} in ${allEndpoints.map(_.tree.tpe).mkString(", ")}"
+ )
+
+ val annotObjects =
+ for(annot <- annotations)
+ yield q"new ${annot.tree.tpe}(..${annot.tree.children.tail})"
+
+ val annotObjectSyms =
+ for(_ <- annotations.indices)
+ yield c.universe.TermName(c.freshName("annotObject"))
+
+ val route = router.extractMethod(
+ m.asInstanceOf[MethodSymbol],
+ weakTypeOf[T],
+ q"${annotObjectSyms.last}.convertToResultType",
+ tq"cask.Request",
+ annotObjectSyms.reverse.map(annotObjectSym => q"$annotObjectSym.getParamParser"),
+ annotObjectSyms.reverse.map(annotObjectSym => tq"$annotObjectSym.InputTypeAlias")
+ )
+
+ val declarations =
+ for((sym, obj) <- annotObjectSyms.zip(annotObjects))
+ yield q"val $sym = $obj"
+
+ val res = q"""{
+ ..$declarations
+ cask.main.EndpointMetadata(
+ Seq(..${annotObjectSyms.dropRight(1)}),
+ ${annotObjectSyms.last},
+ $route
+ )
+ }"""
+ res
+ }
+
+ c.Expr[RoutesEndpointsMetadata[T]](q"""cask.main.RoutesEndpointsMetadata(..$routeParts)""")
+ }
+} \ No newline at end of file
diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala
index f55d33d..f72e14b 100644
--- a/cask/src/cask/package.scala
+++ b/cask/src/cask/package.scala
@@ -35,7 +35,7 @@ package object cask {
// main
type MainRoutes = main.MainRoutes
type Routes = main.Routes
- val Routes = main.Routes
+
type Main = main.Main
type RawDecorator = main.RawDecorator
type HttpEndpoint[InnerReturned, Input] = main.HttpEndpoint[InnerReturned, Input]