Skip to content

Commit

Permalink
Update scala 3 macro to support a hierarchy of sealed traits
Browse files Browse the repository at this point in the history
  • Loading branch information
coreywoodfield committed Jul 19, 2023
1 parent 74a7b36 commit 9792830
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ class ValueEnumSpec extends AnyFunSpec with Matchers with ValueEnumHelpers {
""" should (compile)
}

it("should compile when there is a hierarchy of sealed traits") {
"""
sealed abstract class Top(val value: Int) extends IntEnumEntry
sealed trait Middle extends Top
case object Top extends IntEnum[Top] {
case object One extends Top(1)
case object Two extends Top(2)
case object Three extends Top(3) with Middle
case object Four extends Top(4) with Middle
val values = findValues
}
""" should compile
}

it("should fail to compile when there are non literal values") {
"""
sealed abstract class ContentTypeRepeated(val value: Long, name: String) extends LongEnumEntry
Expand Down
18 changes: 16 additions & 2 deletions macros/src/main/scala-3/enumeratum/ValueEnumMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ object ValueEnumMacros {
tpe: Type[A],
valueTpe: Type[ValueType]
)(using cls: ClassTag[ValueType]): Expr[IndexedSeq[A]] = {
type TakeHead[Head <: A & Singleton, Tail <: Tuple] = Head *: Tail
type SingletonHead[Head <: A & Singleton, Tail <: Tuple] = Head *: Tail
type OtherHead[Head <: A, Tail <: Tuple] = Head *: Tail

type SumOf[X <: A, T <: Tuple] = Mirror.SumOf[X] {
type MirroredElemTypes = T
Expand Down Expand Up @@ -186,7 +187,7 @@ In SBT settings:
values: Map[TypeRepr, ValueType]
)(using tupleTpe: Type[T]): Either[String, Expr[List[A]]] =
tupleTpe match {
case '[TakeHead[h, tail]] => {
case '[SingletonHead[h, tail]] => {
val htpr = TypeRepr.of[h]

(for {
Expand Down Expand Up @@ -224,6 +225,19 @@ In SBT settings:
}
}

case '[OtherHead[h, tail]] =>
Expr.summon[Mirror.SumOf[h]] match {
case Some(sum) =>
sum.asTerm.tpe.asType match {
case '[SumOf[a, t]] => collect[Tuple.Concat[t, tail]](instances, values)

case _ => Left(s"Invalid `Mirror.SumOf[${TypeRepr.of[h].show}]")
}

case None =>
Left(s"Missing `Mirror.SumOf[${TypeRepr.of[h].show}]`")
}

case '[EmptyTuple] => {
val allowAlias = repr <:< TypeRepr.of[AllowAlias]

Expand Down

0 comments on commit 9792830

Please sign in to comment.