yanns
June 2, 2021, 3:50pm
1
Hi,
I’m trying to port a project using macros to visit sum and product types to scala 3: GitHub - sangria-graphql/macro-visit: A macro-based generic visitor generator
This library is using knownDirectSubclasses to fetch the sum types of a sealed trait:
private def collectKnownSubtypes(s: Symbol): Set[Symbol] = {
s.typeSignature // triggers some side-effects (without which `isCaseClass` does not work)
if (s.isModule || s.isModuleClass)
Set(s)
else if (s.isClass) {
val cs = s.asClass
if (cs.isCaseClass) Set(cs)
else if ((cs.isTrait || cs.isAbstract) && cs.isSealed)
cs.knownDirectSubclasses.flatMap(collectKnownSubtypes(_))
else Set.empty
} else Set.empty
}
def reportErrors(errors: Seq[(Position, String)]) = {
require(errors.nonEmpty)
val (lastPos, lastError) = errors.last
errors.dropRight(1).foreach { case (pos, error) => c.error(pos, error) }
I’m trying to do the same in scala 3, but could not find how.
The Mirror.Of
seems to work only if we want to derive a typeclass AFAIU. In this library, we go through the sum and product types without type classes.
Thanks in advance for any help.
1 Like
yanns
August 13, 2021, 12:06pm
2
I’ve got a start:
private def collectKnownSubtypes[T](using quotes: Quotes, tpe: Type[T]): Set[quotes.reflect.Symbol] = {
import quotes.reflect._
val children: List[Symbol] = TypeTree.of[T].symbol.children
children.flatMap { s =>
val flags = s.flags
if (flags.is(Flags.Sealed) && flags.is(Flags.Trait)) {
println("sealed trait " + s)
// TODO: fetch children of sealed trait
// println(boxTpe.memberType(s))
// val childTpe: TypeTree = TypeIdent(s)
// val childType: TypeRepr = childTpe.tpe
// val tt = Type.of(childType)
// collectKnownSubtypes[tt.Underlying](quotes, childType)
s :: Nil
} else {
s :: Nil
}
}
children.toSet
}
But I still need to recursively extract children of any intermediate sealed traits.