lundi 25 octobre 2021

Find all package level objects with scala 3 reflection

I'm trying to get a list of Expr[Any] that corresponds to all package level objects. I can find the package symbol itself (by chasing up the symbol owner of any top level object), then iterate through the declaredFields. I can find the top level object ValDef nodes this way, but there is no associated Term in the ValDef. I also can't use Term.select on the package tree to get the declared members because I can't get the tree of of a package symbol.

It seems like it should be possible to get the Term (and not just the ValDef) associated with these top level singleton objects from their symbols somehow, but I can't figure it out.

Basically I would like to do something like this:

inline def packageToucher[T](something : T) : List[Any] = {
    ${ packageToucherImpl('something) } 
}

def packageToucherImpl[T](something : Expr[T])(using Quotes, Type[T]): Expr[List[Any]] = {
    import quotes.reflect.*
    // assume something is a top level object
    val _package = TypeRepr.of[T].typeSymbol.owner 
    val fields = _package.declaredFields
    val packageExpr = _package.tree.asExpr //  assertion failed: Cannot get tree of package symbol
    val packageTree = packageExpr.asTerm
    val fieldExprs : List[Expr[Any]] = fields.map( f => packageTree.select(f).asExpr)

    Expr.ofList(fieldExprs)
}

and an example of usage would be:

// in actions.scala
package potato

object Actions // dummy object for finding package

object yelling extends Action("yell")

object sleeping extends Action("sleep")

object typing extends Action("type")

and in main:

import potato.*
val actions = Macros.packageToucher(Actions) // should be List(Actions, yelling, sleeping, typing)

Any help would be appreciated. I am a bit of a noob when it comes to scala 3 macros.

Thanks!





Aucun commentaire:

Enregistrer un commentaire