Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
addSbtPlugin("com.frugalmechanic" % "fm-sbt-s3-resolver" % "0.23.0")
addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.30.0")
addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.3")
addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.4")
10 changes: 6 additions & 4 deletions src/main/scala/scalats/ReflectionUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ trait ReflectionUtils {
case '{ ${_}: scala.deriving.Mirror.Singleton } => MirrorType.Singleton
case '{ ${_}: scala.deriving.Mirror.Product } => MirrorType.Product
case '{ ${_}: scala.deriving.Mirror.Sum } => MirrorType.Sum
}
}: @annotation.nowarn("msg=match may not be exhaustive")
}

/**
Expand All @@ -48,8 +48,8 @@ trait ReflectionUtils {
mets <- findMemberType(mirrorTpe, "MirroredElemTypes").map(tupleTypeElements(_)).orElse(Some(Seq.empty))
ml <- findMemberType(mirrorTpe, "MirroredLabel")
mels <- findMemberType(mirrorTpe, "MirroredElemLabels").map { mels =>
tupleTypeElements(mels).map { case ConstantType(StringConstant(l)) => l }
}.orElse(Some(Seq.empty))
tupleTypeElements(mels).map { case ConstantType(StringConstant(l)) => l }: @annotation.nowarn("msg=match may not be exhaustive")
}.orElse(Some(Seq.empty))
} yield {
val ConstantType(StringConstant(ml0)) = ml: @unchecked
Mirror(mt, mmt, mets, ml0, mels, MirrorType.from(mirror))
Expand All @@ -58,7 +58,9 @@ trait ReflectionUtils {

/** Parse a [[scalats.ReflectionUtils.Mirror]] from a `scala.quoted.Quotes.TypeRepr` */
def apply(tpe: TypeRepr): Option[Mirror] =
tpe.asType match { case '[t] => Expr.summon[scala.deriving.Mirror.Of[t]].flatMap(Mirror(_)) }
tpe.asType match {
case '[t] => Expr.summon[scala.deriving.Mirror.Of[t]].flatMap(Mirror(_))
}: @annotation.nowarn("msg=match may not be exhaustive")
}

private def tupleTypeElements(tp: TypeRepr): List[TypeRepr] = {
Expand Down
26 changes: 17 additions & 9 deletions src/main/scala/scalats/TsParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
case AppliedType(tpe, params) if params.nonEmpty =>
AppliedType(tpe, params.zipWithIndex.map { case (_, i) => typeParamTypes(i) }).asType match {
case '[t] => parse[t](true)
}
}: @annotation.nowarn("msg=match may not be exhaustive")
case t if t.typeSymbol.isAliasType && t.typeArgs.isEmpty =>
'{ TsModel.TypeAlias(${ mkTypeName(t) }, ${ parse[A](false) }) }
case t =>
Expand Down Expand Up @@ -109,7 +109,7 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
Type.of[T] match {
case '[*:[h, t]] => parse[h](false) :: unroll[t]
case '[EmptyTuple] => Nil
}
}: @annotation.nowarn("msg=match may not be exhaustive")
'{ TsModel.Tuple($typeName, ${ Expr.ofList(unroll[h *: t]) }) }
case '[t] if typeRepr <:< TypeRepr.of[Tuple] =>
'{ TsModel.Tuple($typeName, ${ mkTypeArgs(TypeRepr.of[t]) }) }
Expand All @@ -125,14 +125,16 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
case None =>
'{ TsModel.Unknown($typeName, ${ mkTypeArgs(typeRepr) }) }
})
}
}: @annotation.nowarn("msg=match may not be exhaustive")
}

private def mkTypeName(typeRepr: TypeRepr): Expr[TypeName] =
'{ T(${ Expr(typeRepr.show) }) }

private def mkTypeArgs(typeRepr: TypeRepr): Expr[List[TsModel]] =
Expr.ofList(typeRepr.typeArgs.map(_.asType match { case '[a] => parse[a](false) }))
Expr.ofList(typeRepr.typeArgs.map(_.asType match {
case '[a] => parse[a](false)
}: @annotation.nowarn("msg=match may not be exhaustive")))

/** Parse an `enum` definiton into its [[scalats.TsModel]] representation */
private def parseEnum[A: Type](mirror: Mirror): Expr[TsModel] = {
Expand All @@ -150,8 +152,12 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
m.types.toList
.filter(t => getTypeConstructor(t.baseType(tycon.typeSymbol)) =:= tycon)
.flatMap(Mirror(_).fold(Nil)(parseMembers))
case MirrorType.Product => List(m.mirroredType.asType match { case '[t] => parseCaseClass[t](m, Some(typeRepr)) })
case MirrorType.Singleton => List(m.mirroredType.asType match { case '[t] => parseObject[t](Some(typeRepr)) })
case MirrorType.Product => List(m.mirroredType.asType match {
case '[t] => parseCaseClass[t](m, Some(typeRepr))
}: @annotation.nowarn("msg=match may not be exhaustive"))
case MirrorType.Singleton => List(m.mirroredType.asType match {
case '[t] => parseObject[t](Some(typeRepr))
}: @annotation.nowarn("msg=match may not be exhaustive"))
}
}

Expand Down Expand Up @@ -207,7 +213,7 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
TsModel.UnionTypeRef(
${ mkTypeName(typeRepr) },
${ mkTypeArgs(typeRepr) },
${ Expr.ofList(ts.map(_.asType match { case '[t] => parse[t](false) })) }
${ Expr.ofList(ts.map(_.asType match { case '[t] => parse[t](false) }: @annotation.nowarn("msg=match may not be exhaustive"))) }
)
})
}
Expand All @@ -217,7 +223,9 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
private def parseCaseClass[A: Type](mirror: Mirror, parent: Option[TypeRepr]): Expr[TsModel.Interface] = {
val typeRepr = TypeRepr.of[A]
val fields = mirror.types.toList.zip(mirror.labels).map { case (tpe, name) =>
tpe.asType match { case '[t] => '{ TsModel.InterfaceField(${ Expr(name) }, ${ parse[t](false) }) } }
tpe.asType match {
case '[t] => '{ TsModel.InterfaceField(${ Expr(name) }, ${ parse[t](false) }) }
}: @annotation.nowarn("msg=match may not be exhaustive")
}
'{
TsModel.Interface(
Expand Down Expand Up @@ -269,7 +277,7 @@ final class TsParser()(using override val ctx: Quotes) extends ReflectionUtils {
val members = valMembers(typeRepr)
val fields = Expr.ofList(members.map(s => valDefType(typeRepr, s).asType match {
case '[a] => '{ TsModel.ObjectField(${ Expr(s.name) }, ${ parse[a](false) }, ${ Select('{ $value.value }.asTerm, s).asExpr }) }
}))
}: @annotation.nowarn("msg=match may not be exhaustive")))
'{
TsModel.Object(
${ mkTypeName(typeRepr) },
Expand Down