From f2c88eda1384cd4c940621de40e021db112094ad Mon Sep 17 00:00:00 2001 From: Miklos Szots Date: Wed, 5 Jan 2022 19:26:54 +0100 Subject: [PATCH] Feature/sangria support (#356) --- .github/workflows/ci.yml | 2 +- build.sbt | 10 ++++ .../core/src/main/scala/derevo/Derevo.scala | 4 ++ .../main/scala/derevo/sangria/package.scala | 29 ++++++++++ .../sangria/SangriaDerivationSpec.scala | 58 +++++++++++++++++++ project/Dependencies.scala | 3 + 6 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 modules/sangria/src/main/scala/derevo/sangria/package.scala create mode 100644 modules/sangria/src/test/scala/derevo/sangria/SangriaDerivationSpec.scala diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e381bac7..cd8cadc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: run: sbt ++${{ matrix.scala }} test - name: Compress target directories - run: tar cf targets.tar modules/tests/target modules/tethys/target modules/pureconfig/target modules/catsTagless/target modules/ciris/target modules/scalacheck/target modules/circeMagnolia/target modules/circe/target target modules/tethysMagnolia/target modules/cats/target modules/core/target modules/reactivemongo/target project/target + run: tar cf targets.tar modules/tests/target modules/tethys/target modules/pureconfig/target modules/catsTagless/target modules/ciris/target modules/scalacheck/target modules/circeMagnolia/target modules/circe/target target modules/tethysMagnolia/target modules/cats/target modules/core/target modules/sangria/target modules/reactivemongo/target project/target - name: Upload target directories uses: actions/upload-artifact@v2 diff --git a/build.sbt b/build.sbt index 4e72a9e8..57529529 100644 --- a/build.sbt +++ b/build.sbt @@ -50,6 +50,7 @@ lazy val derevo = project scalacheck, tethys, tethysMagnolia, + sangria, tests, ) @@ -154,6 +155,15 @@ lazy val scalacheck = ) .dependsOn(core) +lazy val sangria = + (project in file("modules/sangria")) + .settings(publishSettings) + .settings( + name := "derevo-sangria", + libraryDependencies ++= Seq(Dependencies.sangria), + ) + .dependsOn(core) + lazy val tests = (project in file("modules/tests")) .settings(noPublishSettings) diff --git a/modules/core/src/main/scala/derevo/Derevo.scala b/modules/core/src/main/scala/derevo/Derevo.scala index 5fce20e0..e1ccdfaa 100644 --- a/modules/core/src/main/scala/derevo/Derevo.scala +++ b/modules/core/src/main/scala/derevo/Derevo.scala @@ -68,6 +68,10 @@ class Derevo(val c: blackbox.Context) { def delegateParam[TC[_], I, Arg](arg: c.Expr[Arg]): c.Expr[TC[I]] = c.Expr(delegation(c.prefix.tree, Some((method, args) => q"$method($arg, ..$args)"))) + def delegateParamsV[TC[_], I, Arg](arg: c.Expr[Arg]*): c.Expr[TC[I]] = { + c.Expr(delegation(c.prefix.tree, Some((method, args) => q"$method(..${arg.map(_.tree) ++ args})"))) + + } def delegateParams2[TC[_], I, Arg1, Arg2](arg1: c.Expr[Arg1], arg2: c.Expr[Arg2]): c.Expr[TC[I]] = c.Expr(delegation(c.prefix.tree, Some((method, args) => q"$method($arg1, $arg2, ..$args)"))) diff --git a/modules/sangria/src/main/scala/derevo/sangria/package.scala b/modules/sangria/src/main/scala/derevo/sangria/package.scala new file mode 100644 index 00000000..26ded6ae --- /dev/null +++ b/modules/sangria/src/main/scala/derevo/sangria/package.scala @@ -0,0 +1,29 @@ +package derevo + +import derevo.Derivation +import derevo.delegating +import derevo.Derevo +import _root_.sangria.schema._ +import _root_.sangria.macros.derive._ + +package object sangria { + + type Ctx = Any + type CtxObjectType[A] = ObjectType[Ctx, A] + type DeriveObjectSettingNoContext[A] = DeriveObjectSetting[Ctx, A] + + @delegating("sangria.macros.derive.deriveInputObjectType") + object inputObjectType extends Derivation[InputObjectType] { + + def apply[A](arg: DeriveInputObjectSetting*): InputObjectType[A] = + macro Derevo.delegateParamsV[InputObjectType, A, DeriveInputObjectSetting] + + } + + @delegating("sangria.macros.derive.deriveObjectType") + object objectType extends Derivation[CtxObjectType] { + + def apply[A](arg: DeriveObjectSettingNoContext[A]*): CtxObjectType[A] = + macro Derevo.delegateParamsV[CtxObjectType, A, DeriveObjectSettingNoContext[A]] + } +} diff --git a/modules/sangria/src/test/scala/derevo/sangria/SangriaDerivationSpec.scala b/modules/sangria/src/test/scala/derevo/sangria/SangriaDerivationSpec.scala new file mode 100644 index 00000000..4feaf4dc --- /dev/null +++ b/modules/sangria/src/test/scala/derevo/sangria/SangriaDerivationSpec.scala @@ -0,0 +1,58 @@ +package derevo.sangria + +import derevo.derive +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import sangria.schema.InputObjectType +import sangria.macros.derive.InputObjectTypeName +import sangria.macros.derive.ExcludeInputFields +import sangria.macros.derive.ObjectTypeName +import sangria.macros.derive.RenameField + +class SangriaDerivationSpec extends AnyFlatSpec with Matchers { + "Sangria input object derivation" should "derive input object without customization" in { + val derived = implicitly[InputObjectType[SangriaDerivationSpec.Input]] + + assertResult("Input")(derived.name) + derived.fields.map(_.name) should contain theSameElementsAs List("stringParam", "intParam") + } + + it should "derive input object with customization" in { + val derived = + implicitly[InputObjectType[SangriaDerivationSpec.InputCustom]] + + assertResult("Renamed")(derived.name) + derived.fields.map(_.name) should contain theSameElementsAs List("stringParam", "fooInner") + } + + "Sangria object derivation" should "derive object without customization" in { + val derived = + implicitly[CtxObjectType[SangriaDerivationSpec.Response]] + + assertResult("Response")(derived.name) + derived.fields.map(_.name) should contain theSameElementsAs List("data") + } + + "Sangria object derivation" should "derive object with customization" in { + val derived = + implicitly[CtxObjectType[SangriaDerivationSpec.ResponseCustom]] + + assertResult("RenamedResponse")(derived.name) + derived.fields.map(_.name) should contain theSameElementsAs List("content") + } +} + +object SangriaDerivationSpec { + @derive(inputObjectType()) case class Input(stringParam: String, intParam: Int) + @derive(inputObjectType(InputObjectTypeName("Renamed"), ExcludeInputFields("intParam"))) case class InputCustom( + stringParam: String, + intParam: Int, + fooInner: Input + ) + + @derive(objectType()) + case class Response(data: String) + + @derive(objectType(ObjectTypeName("RenamedResponse"), RenameField("data", "content"))) + case class ResponseCustom(data: String) +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 665c974a..671724db 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -39,6 +39,8 @@ object Dependencies { val kindProjector = "0.13.2" val macroParadise = "2.1.1" + + val sangria = "2.1.6" } lazy val magnolia = "com.propensive" %% "magnolia" % Version.magnolia @@ -56,6 +58,7 @@ object Dependencies { lazy val tethysCore = "com.tethys-json" %% "tethys-core" % Version.tethys lazy val tethysDerivation = "com.tethys-json" %% "tethys-derivation" % Version.tethys lazy val scalacheck = "org.scalacheck" %% "scalacheck" % Version.scalacheck + lazy val sangria = "org.sangria-graphql" %% "sangria" % Version.sangria lazy val circeParser = "io.circe" %% "circe-parser" % Version.circe lazy val tethysJackson = "com.tethys-json" %% "tethys-jackson" % Version.tethys