From adc83bd211024badb2dd4056c71b129c1fc2c128 Mon Sep 17 00:00:00 2001 From: Hugh Simpson Date: Mon, 13 Jan 2025 10:53:07 +0000 Subject: [PATCH] make annotation type signature more specific --- src/core/impl.scala | 11 +++--- src/core/interface.scala | 38 +++++++++---------- src/core/macro.scala | 79 ++++++++++++++++++++-------------------- src/core/magnolia.scala | 7 ++-- 4 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/core/impl.scala b/src/core/impl.scala index 85d344dd..4b1f0d9b 100644 --- a/src/core/impl.scala +++ b/src/core/impl.scala @@ -1,5 +1,6 @@ package magnolia2 +import scala.annotation.Annotation import scala.compiletime.* import scala.deriving.Mirror import scala.reflect.* @@ -85,7 +86,7 @@ object CaseClassDerivation: parameters, IArray(anns[A]*), IArray(inheritedAnns[A]*), - IArray[Any](typeAnns[A]*) + IArray[Annotation](typeAnns[A]*) ): def construct[PType: ClassTag](makeParam: Param => PType): A = product.fromProduct(Tuple.fromArray(params.map(makeParam).to(Array))) @@ -120,9 +121,9 @@ object CaseClassDerivation: } inline def paramsFromMaps[Typeclass[_], A, Labels <: Tuple, Params <: Tuple]( - annotations: Map[String, List[Any]], - inheritedAnnotations: Map[String, List[Any]], - typeAnnotations: Map[String, List[Any]], + annotations: Map[String, List[Annotation]], + inheritedAnnotations: Map[String, List[Annotation]], + typeAnnotations: Map[String, List[Annotation]], repeated: Map[String, Boolean], defaults: Map[String, Option[() => Any]], idx: Int = 0 @@ -165,7 +166,7 @@ trait SealedTraitDerivation: typeInfo[A], IArray(subtypesFromMirror[A, m.MirroredElemTypes](m)*), IArray.from(anns[A]), - IArray(paramTypeAnns[A]*), + IArray.from(paramTypeAnns[A]), isEnum[A], IArray.from(inheritedAnns[A]) ) diff --git a/src/core/interface.scala b/src/core/interface.scala index db67cd35..dccb3ceb 100644 --- a/src/core/interface.scala +++ b/src/core/interface.scala @@ -1,6 +1,6 @@ package magnolia2 -import scala.annotation.tailrec +import scala.annotation.{Annotation, tailrec} import scala.reflect.* case class TypeInfo( @@ -15,8 +15,8 @@ object CaseClass: val label: String, val index: Int, val repeated: Boolean, - val annotations: IArray[Any], - val typeAnnotations: IArray[Any] + val annotations: IArray[Annotation], + val typeAnnotations: IArray[Annotation] ) extends Serializable: type PType @@ -42,7 +42,7 @@ object CaseClass: * default argument value, if any */ def default: Option[PType] - def inheritedAnnotations: IArray[Any] = IArray.empty[Any] + def inheritedAnnotations: IArray[Annotation] = IArray.empty[Annotation] override def toString: String = s"Param($label)" object Param: @@ -53,9 +53,9 @@ object CaseClass: repeated: Boolean, cbn: CallByNeed[F[P]], defaultVal: CallByNeed[Option[P]], - annotations: IArray[Any], - inheritedAnns: IArray[Any], - typeAnnotations: IArray[Any] + annotations: IArray[Annotation], + inheritedAnns: IArray[Annotation], + typeAnnotations: IArray[Annotation] ): Param[F, T] = new CaseClass.Param[F, T]( name, @@ -89,9 +89,9 @@ abstract class CaseClass[Typeclass[_], Type]( val isObject: Boolean, val isValueClass: Boolean, val params: IArray[CaseClass.Param[Typeclass, Type]], - val annotations: IArray[Any], - val inheritedAnnotations: IArray[Any] = IArray.empty[Any], - val typeAnnotations: IArray[Any] + val annotations: IArray[Annotation], + val inheritedAnnotations: IArray[Annotation] = IArray.empty[Annotation], + val typeAnnotations: IArray[Annotation] ) extends Serializable: type Param = CaseClass.Param[Typeclass, Type] @@ -113,9 +113,9 @@ abstract class CaseClass[Typeclass[_], Type]( repeated: Boolean, cbn: CallByNeed[Typeclass[P]], defaultVal: CallByNeed[Option[P]], - annotations: IArray[Any], - inheritedAnns: IArray[Any], - typeAnnotations: IArray[Any] + annotations: IArray[Annotation], + inheritedAnns: IArray[Annotation], + typeAnnotations: IArray[Annotation] ): Param = new CaseClass.Param[Typeclass, Type]( name, @@ -141,10 +141,10 @@ end CaseClass case class SealedTrait[Typeclass[_], Type]( typeInfo: TypeInfo, subtypes: IArray[SealedTrait.Subtype[Typeclass, Type, _]], - annotations: IArray[Any], - typeAnnotations: IArray[Any], + annotations: IArray[Annotation], + typeAnnotations: IArray[(String, List[Annotation])], isEnum: Boolean, - inheritedAnnotations: IArray[Any] + inheritedAnnotations: IArray[Annotation] ) extends Serializable: type Subtype[S] = SealedTrait.SubtypeValue[Typeclass, Type, S] @@ -191,9 +191,9 @@ object SealedTrait: */ class Subtype[Typeclass[_], Type, SType]( val typeInfo: TypeInfo, - val annotations: IArray[Any], - val inheritedAnnotations: IArray[Any], - val typeAnnotations: IArray[Any], + val annotations: IArray[Annotation], + val inheritedAnnotations: IArray[Annotation], + val typeAnnotations: IArray[(String, List[Annotation])], val isObject: Boolean, callByNeed: CallByNeed[Typeclass[SType]], isType: Type => Boolean, diff --git a/src/core/macro.scala b/src/core/macro.scala index 93249ecb..35092884 100644 --- a/src/core/macro.scala +++ b/src/core/macro.scala @@ -3,6 +3,7 @@ package magnolia2 import scala.quoted.* import scala.annotation.meta.field import scala.annotation.Annotation +import scala.reflect.ClassTag object Macro: @@ -15,19 +16,19 @@ object Macro: inline def isEnum[T]: Boolean = ${ isEnum[T] } - inline def anns[T]: List[Any] = + inline def anns[T]: List[Annotation] = ${ anns[T] } - inline def inheritedAnns[T]: List[Any] = + inline def inheritedAnns[T]: List[Annotation] = ${ inheritedAnns[T] } - inline def typeAnns[T]: List[Any] = + inline def typeAnns[T]: List[Annotation] = ${ typeAnns[T] } - inline def paramAnns[T]: List[(String, List[Any])] = + inline def paramAnns[T]: List[(String, List[Annotation])] = ${ paramAnns[T] } - inline def inheritedParamAnns[T]: List[(String, List[Any])] = + inline def inheritedParamAnns[T]: List[(String, List[Annotation])] = ${ inheritedParamAnns[T] } inline def isValueClass[T]: Boolean = @@ -36,7 +37,7 @@ object Macro: inline def defaultValue[T]: List[(String, Option[() => Any])] = ${ defaultValue[T] } - inline def paramTypeAnns[T]: List[(String, List[Any])] = + inline def paramTypeAnns[T]: List[(String, List[Annotation])] = ${ paramTypeAnns[T] } inline def repeated[T]: List[(String, Boolean)] = @@ -60,26 +61,26 @@ object Macro: def paramTypeAnns[T: Type](using q: Quotes - ): Expr[List[(String, List[Any])]] = + ): Expr[List[(String, List[Annotation])]] = new CollectAnnotations[q.type, T].paramTypeAnns - def anns[T: Type](using q: Quotes): Expr[List[Any]] = + def anns[T: Type](using q: Quotes): Expr[List[Annotation]] = new CollectAnnotations[q.type, T].anns - def inheritedAnns[T: Type](using q: Quotes): Expr[List[Any]] = + def inheritedAnns[T: Type](using q: Quotes): Expr[List[Annotation]] = new CollectAnnotations[q.type, T].inheritedAnns - def typeAnns[T: Type](using q: Quotes): Expr[List[Any]] = + def typeAnns[T: Type](using q: Quotes): Expr[List[Annotation]] = new CollectAnnotations[q.type, T].typeAnns def paramAnns[T: Type](using q: Quotes - ): Expr[List[(String, List[Any])]] = + ): Expr[List[(String, List[Annotation])]] = new CollectAnnotations[q.type, T].paramAnns def inheritedParamAnns[T: Type](using q: Quotes - ): Expr[List[(String, List[Any])]] = + ): Expr[List[(String, List[Annotation])]] = new CollectAnnotations[q.type, T].inheritedParamAnns def isValueClass[T: Type](using Quotes): Expr[Boolean] = @@ -192,14 +193,14 @@ object Macro: val tpe: TypeRepr = TypeRepr.of[T] - def anns: Expr[List[Any]] = + def anns: Expr[List[Annotation]] = Expr.ofList { tpe.typeSymbol.annotations .filter(filterAnnotation) - .map(_.asExpr.asInstanceOf[Expr[Any]]) + .map(_.asExpr.asInstanceOf[Expr[Annotation]]) } - def inheritedAnns: Expr[List[Any]] = + def inheritedAnns: Expr[List[Annotation]] = Expr.ofList { tpe.baseClasses .filterNot(isObjectOrScala) @@ -208,10 +209,10 @@ object Macro: } // skip self .flatten .filter(filterAnnotation) - .map(_.asExpr.asInstanceOf[Expr[Any]]) + .map(_.asExpr.asInstanceOf[Expr[Annotation]]) } - def typeAnns: Expr[List[Any]] = + def typeAnns: Expr[List[Annotation]] = val symbol: Option[Symbol] = if tpe.typeSymbol.isNoSymbol then None else Some(tpe.typeSymbol) @@ -231,7 +232,7 @@ object Macro: } .flatMap(loopForAnnotations) .filter(filterAnnotation) - .map { _.asExpr.asInstanceOf[Expr[Any]] } + .map { _.asExpr.asInstanceOf[Expr[Annotation]] } case _ => List.empty } @@ -248,8 +249,8 @@ object Macro: } .filter(_._2.nonEmpty) - def paramTypeAnns: Expr[List[(String, List[Any])]] = - liftTermsDict(paramTypeAnnsOnTerms) + def paramTypeAnns: Expr[List[(String, List[Annotation])]] = + liftTermsDict(paramTypeAnnsOnTerms).asInstanceOf[Expr[List[(String, List[Annotation])]]] def paramAnnsOnTerms: List[(String, List[Term])] = val terms = (annotationsFromConstructorOnTerms( @@ -259,8 +260,8 @@ object Macro: groupByNameOnTerms(terms) - def paramAnns: Expr[List[(String, List[Any])]] = - liftTermsDict(paramAnnsOnTerms) + def paramAnns: Expr[List[(String, List[Annotation])]] = + liftTermsDict(paramAnnsOnTerms).asInstanceOf[Expr[List[(String, List[Annotation])]]] def inheritedParamAnnsOnTerms: List[(String, List[Term])] = val annTerms: List[(String, List[Term])] = @@ -279,8 +280,8 @@ object Macro: groupByNameOnTerms(annTerms) - def inheritedParamAnns: Expr[List[(String, List[Any])]] = - liftTermsDict(inheritedParamAnnsOnTerms) + def inheritedParamAnns: Expr[List[(String, List[Annotation])]] = + liftTermsDict(inheritedParamAnnsOnTerms).asInstanceOf[Expr[List[(String, List[Annotation])]]] private def loopForAnnotations(t: TypeRepr): List[Term] = t match @@ -310,10 +311,10 @@ object Macro: private def annotationsfromConstructor( from: Symbol - ): List[(String, List[Expr[Any]])] = + ): List[(String, List[Expr[Annotation]])] = annotationsFromConstructorOnTerms(from) .map { p => - p._1 -> p._2.map(_.asExpr.asInstanceOf[Expr[Any]]) + p._1 -> p._2.map(_.asExpr.asInstanceOf[Expr[Annotation]]) } private def annotationsFromDeclarationsOnTerms( @@ -327,10 +328,10 @@ object Macro: private def annotationsFromDeclarations( from: Symbol - ): List[(String, List[Expr[Any]])] = + ): List[(String, List[Expr[Annotation]])] = annotationsFromDeclarationsOnTerms(from) .map { p => - p._1 -> p._2.map(_.asExpr.asInstanceOf[Expr[Any]]) + p._1 -> p._2.map(_.asExpr.asInstanceOf[Expr[Annotation]]) } private def groupByNameOnTerms( @@ -346,7 +347,7 @@ object Macro: bc.fullName.startsWith("scala.") private def filterAnnotation(a: Term): Boolean = - (a.tpe <:< TypeRepr.of[scala.annotation.Annotation]) && + (a.tpe <:< TypeRepr.of[Annotation]) && (a.tpe.typeSymbol.maybeOwner.isNoSymbol || a.tpe.typeSymbol.owner.fullName != "scala.annotation.internal") @@ -384,7 +385,7 @@ object Macro: case Some(expr) => '{ new CallByNeed(() => Some(($expr).asInstanceOf[P])) } - def selectFromDict( + def selectFromDict[T: Type]( dict: List[(String, List[Term])], name: String ) = @@ -394,11 +395,11 @@ object Macro: dict, name ) - .map(_.asExpr) + .map(_.asExprOf[T]) } - def toIArray(es: Expr[List[Any]]): Expr[IArray[Any]] = - '{ IArray($es: _*) } + def toAnnIArray(es: Expr[List[Annotation]]): Expr[IArray[Annotation]] = + '{ IArray[Annotation]($es: _*) } extension [B: Type](e: Expr[B]) def asCallByNeedExpr: Expr[CallByNeed[B]] = @@ -438,24 +439,24 @@ object Macro: selectDefault[p](defaultValueOnTerms[a], paramSymbol.name) val annotations = - toIArray( - selectFromDict( + toAnnIArray( + selectFromDict[Annotation]( new CollectAnnotations[q.type, A].paramAnnsOnTerms, paramSymbol.name ) ) val inheritedAnnotations = - toIArray( - selectFromDict( + toAnnIArray( + selectFromDict[Annotation]( new CollectAnnotations[q.type, A].inheritedParamAnnsOnTerms, paramSymbol.name ) ) val typeAnnotations = - toIArray( - selectFromDict( + toAnnIArray( + selectFromDict[Annotation]( new CollectAnnotations[q.type, A].paramTypeAnnsOnTerms, paramSymbol.name ) diff --git a/src/core/magnolia.scala b/src/core/magnolia.scala index 02384683..bdff5244 100644 --- a/src/core/magnolia.scala +++ b/src/core/magnolia.scala @@ -1,5 +1,6 @@ package magnolia2 +import scala.annotation.Annotation import scala.compiletime.* import scala.deriving.Mirror import scala.reflect.* @@ -30,9 +31,9 @@ trait CommonDerivation[TypeClass[_]]: ): Typeclass[A] = join(CaseClassDerivation.fromMirror(product)) inline def getParams__[T, Labels <: Tuple, Params <: Tuple]( - annotations: Map[String, List[Any]], - inheritedAnnotations: Map[String, List[Any]], - typeAnnotations: Map[String, List[Any]], + annotations: Map[String, List[Annotation]], + inheritedAnnotations: Map[String, List[Annotation]], + typeAnnotations: Map[String, List[Annotation]], repeated: Map[String, Boolean], defaults: Map[String, Option[() => Any]], idx: Int = 0