From 3c4ab1fe6f219d09e9af3caef4b82dfdcf3352aa Mon Sep 17 00:00:00 2001 From: Pierre Ricadat Date: Fri, 20 Oct 2023 14:55:39 +0200 Subject: [PATCH] Use custom macro for getting annotations (#1950) * Use custom macro for getting annotations * Format --- .../caliban/schema/ArgBuilderDerivation.scala | 5 ++- .../caliban/schema/SchemaDerivation.scala | 8 ++--- .../caliban/schema/macros/Macros.scala | 31 +++++++++++++++++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala-3/caliban/schema/ArgBuilderDerivation.scala b/core/src/main/scala-3/caliban/schema/ArgBuilderDerivation.scala index ab771e260b..2afe659240 100644 --- a/core/src/main/scala-3/caliban/schema/ArgBuilderDerivation.scala +++ b/core/src/main/scala-3/caliban/schema/ArgBuilderDerivation.scala @@ -6,7 +6,6 @@ import caliban.Value.* import caliban.schema.Annotations.GQLDefault import caliban.schema.Annotations.GQLName import caliban.schema.macros.Macros -import magnolia1.Macro as MagnoliaMacro import scala.deriving.Mirror import scala.compiletime.* @@ -22,7 +21,7 @@ trait CommonArgBuilderDerivation { recurse[P, names, ts]( ( constValue[name].toString, - MagnoliaMacro.anns[t], { + Macros.annotations[t], { if (Macros.isEnumField[P, t]) if (!Macros.implicitExists[ArgBuilder[t]]) derived[t] else summonInline[ArgBuilder[t]] @@ -43,7 +42,7 @@ trait CommonArgBuilderDerivation { case m: Mirror.ProductOf[A] => makeProductArgBuilder( recurse[A, m.MirroredElemLabels, m.MirroredElemTypes](), - MagnoliaMacro.paramAnns[A].to(Map) + Macros.paramAnnotations[A].to(Map) )(m.fromProduct) } diff --git a/core/src/main/scala-3/caliban/schema/SchemaDerivation.scala b/core/src/main/scala-3/caliban/schema/SchemaDerivation.scala index 48fb963f59..21485c0b4b 100644 --- a/core/src/main/scala-3/caliban/schema/SchemaDerivation.scala +++ b/core/src/main/scala-3/caliban/schema/SchemaDerivation.scala @@ -48,7 +48,7 @@ trait CommonSchemaDerivation { else ( constValue[name].toString, - MagnoliaMacro.anns[t], { + Macros.annotations[t], { if (Macros.isEnumField[P, t]) if (!Macros.implicitExists[Schema[R, t]]) derived[R, t] else summonInline[Schema[R, t]] @@ -65,15 +65,15 @@ trait CommonSchemaDerivation { makeSumSchema[R, A]( recurse[R, A, m.MirroredElemLabels, m.MirroredElemTypes]()(), MagnoliaMacro.typeInfo[A], - MagnoliaMacro.anns[A] + Macros.annotations[A] )(m.ordinal) case m: Mirror.ProductOf[A] => makeProductSchema[R, A]( recurse[R, A, m.MirroredElemLabels, m.MirroredElemTypes]()(), MagnoliaMacro.typeInfo[A], - MagnoliaMacro.anns[A], - MagnoliaMacro.paramAnns[A].toMap + Macros.annotations[A], + Macros.paramAnnotations[A].toMap ) } diff --git a/core/src/main/scala-3/caliban/schema/macros/Macros.scala b/core/src/main/scala-3/caliban/schema/macros/Macros.scala index 95b3d3c321..da4f196943 100644 --- a/core/src/main/scala-3/caliban/schema/macros/Macros.scala +++ b/core/src/main/scala-3/caliban/schema/macros/Macros.scala @@ -7,9 +7,34 @@ import scala.quoted.* export magnolia1.TypeInfo object Macros { - inline def isFieldExcluded[P, T]: Boolean = ${ isFieldExcludedImpl[P, T] } - inline def isEnumField[P, T]: Boolean = ${ isEnumFieldImpl[P, T] } - inline def implicitExists[T]: Boolean = ${ implicitExistsImpl[T] } + inline def annotations[T]: List[Any] = ${ annotationsImpl[T] } + inline def paramAnnotations[T]: List[(String, List[Any])] = ${ paramAnnotationsImpl[T] } + inline def isFieldExcluded[P, T]: Boolean = ${ isFieldExcludedImpl[P, T] } + inline def isEnumField[P, T]: Boolean = ${ isEnumFieldImpl[P, T] } + inline def implicitExists[T]: Boolean = ${ implicitExistsImpl[T] } + + private def annotationsImpl[T: Type](using qctx: Quotes): Expr[List[Any]] = { + import qctx.reflect.* + val tpe = TypeRepr.of[T] + Expr.ofList { + tpe.typeSymbol.annotations.filter { a => + a.tpe.typeSymbol.maybeOwner.isNoSymbol || (a.tpe.typeSymbol.owner.fullName != "scala.annotation.internal" && a.tpe.typeSymbol.owner.fullName != "jdk.internal") + }.map(_.asExpr.asInstanceOf[Expr[Any]]) + } + } + + private def paramAnnotationsImpl[T: Type](using qctx: Quotes): Expr[List[(String, List[Any])]] = { + import qctx.reflect.* + val tpe = TypeRepr.of[T] + Expr.ofList { + tpe.typeSymbol.primaryConstructor.paramSymss.flatten.map { field => + Expr(field.name) -> field.annotations.filter { a => + a.tpe.typeSymbol.maybeOwner.isNoSymbol || + (a.tpe.typeSymbol.owner.fullName != "scala.annotation.internal" && a.tpe.typeSymbol.owner.fullName != "jdk.internal") + }.map(_.asExpr.asInstanceOf[Expr[Any]]) + }.filter(_._2.nonEmpty).map((name, anns) => Expr.ofTuple(name, Expr.ofList(anns))) + } + } /** * Tests whether type argument [[FieldT]] in [[Parent]] is annotated with [[GQLExcluded]]