From c417d727da4ec7978948105d4b1da7780a28c39a Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Fri, 22 May 2015 09:06:50 +0200 Subject: [PATCH] =htp add explicit result types to formField/parameter implicits Otherwise, the applicability of the implicit conversions can depend on the order of compiler-internal loading/typing which is hardly predictable. --- .../FormFieldDirectivesExamplesSpec.scala | 3 -- .../ParameterDirectivesExamplesSpec.scala | 3 -- .../directives/FormFieldDirectives.scala | 32 +++++++++---------- .../directives/ParameterDirectives.scala | 29 +++++++++-------- 4 files changed, 31 insertions(+), 36 deletions(-) diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala b/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala index 813c1e1225..9c2d7e3b42 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala +++ b/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala @@ -9,9 +9,6 @@ import akka.http.scaladsl.server.Route import akka.http.scaladsl.model._ class FormFieldDirectivesExamplesSpec extends RoutingSpec { - // FIXME: investigate why it doesn't work without this import - import akka.http.scaladsl.server.directives.FormFieldDirectives.FieldMagnet - "formFields" in { val route = formFields('color, 'age.as[Int]) { (color, age) => diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala b/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala index a42ed429b0..a3ae378212 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala +++ b/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala @@ -9,9 +9,6 @@ import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Route class ParameterDirectivesExamplesSpec extends RoutingSpec { - // FIXME: investigate why it doesn't work without this import - import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet - "example-1" in { val route = parameter('color) { color => diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala index a29a4b2bef..f9c8525f30 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala @@ -35,20 +35,20 @@ object FormFieldDirectives extends FormFieldDirectives { def apply(): Out } object FieldMagnet { - implicit def apply[T](value: T)(implicit fdef: FieldDef[T]) = + implicit def apply[T](value: T)(implicit fdef: FieldDef[T]): FieldMagnet { type Out = fdef.Out } = new FieldMagnet { type Out = fdef.Out def apply() = fdef(value) } } + type FieldDefAux[A, B] = FieldDef[A] { type Out = B } sealed trait FieldDef[T] { type Out def apply(value: T): Out } - object FieldDef { - def fieldDef[A, B](f: A ⇒ B) = + def fieldDef[A, B](f: A ⇒ B): FieldDefAux[A, B] = new FieldDef[A] { type Out = B def apply(value: A) = f(value) @@ -63,7 +63,7 @@ object FormFieldDirectives extends FormFieldDirectives { //////////////////// "regular" formField extraction //////////////////// - private def extractField[A, B](f: A ⇒ Directive1[B]) = fieldDef(f) + private def extractField[A, B](f: A ⇒ Directive1[B]): FieldDefAux[A, Directive1[B]] = fieldDef(f) private def fieldOfForm[T](fieldName: String, fu: Unmarshaller[Option[StrictForm.Field], T])(implicit sfu: SFU): RequestContext ⇒ Future[T] = { ctx ⇒ import ctx.executionContext sfu(ctx.request.entity).fast.flatMap(form ⇒ fu(form field fieldName)) @@ -78,21 +78,21 @@ object FormFieldDirectives extends FormFieldDirectives { } } } - implicit def forString(implicit sfu: SFU, fu: FSFFU[String]) = + implicit def forString(implicit sfu: SFU, fu: FSFFU[String]): FieldDefAux[String, Directive1[String]] = extractField[String, String] { fieldName ⇒ filter(fieldName, fu) } - implicit def forSymbol(implicit sfu: SFU, fu: FSFFU[String]) = + implicit def forSymbol(implicit sfu: SFU, fu: FSFFU[String]): FieldDefAux[Symbol, Directive1[String]] = extractField[Symbol, String] { symbol ⇒ filter(symbol.name, fu) } - implicit def forNR[T](implicit sfu: SFU, fu: FSFFU[T]) = + implicit def forNR[T](implicit sfu: SFU, fu: FSFFU[T]): FieldDefAux[NameReceptacle[T], Directive1[T]] = extractField[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fu) } - implicit def forNUR[T](implicit sfu: SFU) = + implicit def forNUR[T](implicit sfu: SFU): FieldDefAux[NameUnmarshallerReceptacle[T], Directive1[T]] = extractField[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um)) } - implicit def forNOR[T](implicit sfu: SFU, fu: FSFFOU[T]) = + implicit def forNOR[T](implicit sfu: SFU, fu: FSFFOU[T]): FieldDefAux[NameOptionReceptacle[T], Directive1[Option[T]]] = extractField[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fu) } - implicit def forNDR[T](implicit sfu: SFU, fu: FSFFOU[T]) = + implicit def forNDR[T](implicit sfu: SFU, fu: FSFFOU[T]): FieldDefAux[NameDefaultReceptacle[T], Directive1[T]] = extractField[NameDefaultReceptacle[T], T] { nr ⇒ filter(nr.name, fu withDefaultValue nr.default) } - implicit def forNOUR[T](implicit sfu: SFU) = + implicit def forNOUR[T](implicit sfu: SFU): FieldDefAux[NameOptionUnmarshallerReceptacle[T], Directive1[Option[T]]] = extractField[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) } - implicit def forNDUR[T](implicit sfu: SFU) = + implicit def forNDUR[T](implicit sfu: SFU): FieldDefAux[NameDefaultUnmarshallerReceptacle[T], Directive1[T]] = extractField[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, (StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) withDefaultValue nr.default) } //////////////////// required formField support //////////////////// @@ -105,9 +105,9 @@ object FormFieldDirectives extends FormFieldDirectives { case _ ⇒ reject } } - implicit def forRVR[T](implicit sfu: SFU, fu: FSFFU[T]) = + implicit def forRVR[T](implicit sfu: SFU, fu: FSFFU[T]): FieldDefAux[RequiredValueReceptacle[T], Directive0] = fieldDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fu, rvr.requiredValue) } - implicit def forRVDR[T](implicit sfu: SFU) = + implicit def forRVDR[T](implicit sfu: SFU): FieldDefAux[RequiredValueUnmarshallerReceptacle[T], Directive0] = fieldDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, StrictForm.Field.unmarshallerFromFSU(rvr.um), rvr.requiredValue) } //////////////////// tuple support //////////////////// @@ -115,11 +115,11 @@ object FormFieldDirectives extends FormFieldDirectives { import akka.http.scaladsl.server.util.TupleOps._ import akka.http.scaladsl.server.util.BinaryPolyFunc - implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]) = + implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]): FieldDefAux[T, fold.Out] = fieldDef[T, fold.Out](fold(pass, _)) object ConvertParamDefAndConcatenate extends BinaryPolyFunc { - implicit def from[P, TA, TB](implicit fdef: FieldDef[P] { type Out = Directive[TB] }, ev: Join[TA, TB]) = + implicit def from[P, TA, TB](implicit fdef: FieldDefAux[P, Directive[TB]], ev: Join[TA, TB]) = at[Directive[TA], P] { (a, t) ⇒ a & fdef(t) } } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/ParameterDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/ParameterDirectives.scala index 677fcf2538..a9c3b64be0 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/ParameterDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/ParameterDirectives.scala @@ -59,19 +59,20 @@ object ParameterDirectives extends ParameterDirectives { def apply(): Out } object ParamMagnet { - implicit def apply[T](value: T)(implicit pdef: ParamDef[T]) = + implicit def apply[T](value: T)(implicit pdef: ParamDef[T]): ParamMagnet { type Out = pdef.Out } = new ParamMagnet { type Out = pdef.Out def apply() = pdef(value) } } + type ParamDefAux[T, U] = ParamDef[T] { type Out = U } sealed trait ParamDef[T] { type Out def apply(value: T): Out } object ParamDef { - def paramDef[A, B](f: A ⇒ B) = + def paramDef[A, B](f: A ⇒ B): ParamDefAux[A, B] = new ParamDef[A] { type Out = B def apply(value: A) = f(value) @@ -85,7 +86,7 @@ object ParameterDirectives extends ParameterDirectives { //////////////////// "regular" parameter extraction ////////////////////// - private def extractParameter[A, B](f: A ⇒ Directive1[B]) = paramDef(f) + private def extractParameter[A, B](f: A ⇒ Directive1[B]): ParamDefAux[A, Directive1[B]] = paramDef(f) private def filter[T](paramName: String, fsou: FSOU[T]): Directive1[T] = extractRequestContext flatMap { ctx ⇒ import ctx.executionContext @@ -95,21 +96,21 @@ object ParameterDirectives extends ParameterDirectives { case Failure(x) ⇒ reject(MalformedQueryParamRejection(paramName, x.getMessage.nullAsEmpty, Option(x.getCause))) } } - implicit def forString(implicit fsu: FSU[String]) = + implicit def forString(implicit fsu: FSU[String]): ParamDefAux[String, Directive1[String]] = extractParameter[String, String] { string ⇒ filter(string, fsu) } - implicit def forSymbol(implicit fsu: FSU[String]) = + implicit def forSymbol(implicit fsu: FSU[String]): ParamDefAux[Symbol, Directive1[String]] = extractParameter[Symbol, String] { symbol ⇒ filter(symbol.name, fsu) } - implicit def forNR[T](implicit fsu: FSU[T]) = + implicit def forNR[T](implicit fsu: FSU[T]): ParamDefAux[NameReceptacle[T], Directive1[T]] = extractParameter[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fsu) } - implicit def forNUR[T] = + implicit def forNUR[T]: ParamDefAux[NameUnmarshallerReceptacle[T], Directive1[T]] = extractParameter[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, nr.um) } - implicit def forNOR[T](implicit fsou: FSOU[T]) = + implicit def forNOR[T](implicit fsou: FSOU[T]): ParamDefAux[NameOptionReceptacle[T], Directive1[Option[T]]] = extractParameter[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fsou) } - implicit def forNDR[T](implicit fsou: FSOU[T]) = + implicit def forNDR[T](implicit fsou: FSOU[T]): ParamDefAux[NameDefaultReceptacle[T], Directive1[T]] = extractParameter[NameDefaultReceptacle[T], T] { nr ⇒ filter[T](nr.name, fsou withDefaultValue nr.default) } - implicit def forNOUR[T] = + implicit def forNOUR[T]: ParamDefAux[NameOptionUnmarshallerReceptacle[T], Directive1[Option[T]]] = extractParameter[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter(nr.name, nr.um: FSOU[T]) } - implicit def forNDUR[T] = + implicit def forNDUR[T]: ParamDefAux[NameDefaultUnmarshallerReceptacle[T], Directive1[T]] = extractParameter[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter[T](nr.name, (nr.um: FSOU[T]) withDefaultValue nr.default) } //////////////////// required parameter support //////////////////// @@ -122,9 +123,9 @@ object ParameterDirectives extends ParameterDirectives { case _ ⇒ reject } } - implicit def forRVR[T](implicit fsu: FSU[T]) = + implicit def forRVR[T](implicit fsu: FSU[T]): ParamDefAux[RequiredValueReceptacle[T], Directive0] = paramDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fsu, rvr.requiredValue) } - implicit def forRVDR[T] = + implicit def forRVDR[T]: ParamDefAux[RequiredValueUnmarshallerReceptacle[T], Directive0] = paramDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, rvr.um, rvr.requiredValue) } //////////////////// tuple support //////////////////// @@ -132,7 +133,7 @@ object ParameterDirectives extends ParameterDirectives { import akka.http.scaladsl.server.util.TupleOps._ import akka.http.scaladsl.server.util.BinaryPolyFunc - implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]) = + implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]): ParamDefAux[T, fold.Out] = paramDef[T, fold.Out](fold(BasicDirectives.pass, _)) object ConvertParamDefAndConcatenate extends BinaryPolyFunc {