如何使用Scala 3反射获取指定包下所有包级对象的Expr[Any]列表
你遇到的报错是Scala 3 宏API的正常限制:包符号本身没有关联的语法树,调用.tree方法必然会触发断言失败,不需要尝试获取包对应的语法树来选择成员。
顶层对象的符号本身已经包含了完整的全局路径信息,可以直接通过quotes.reflect.Ref方法构造对应的Term,无需从包节点做选择。修正后的实现代码如下:
import scala.quoted.* object Macros: inline def packageToucher[T](something: T): List[Any] = ${ packageToucherImpl('something) } private def packageToucherImpl[T: Type](something: Expr[T])(using Quotes): Expr[List[Any]] = import quotes.reflect.* // 取传入顶层对象所属的包符号 val pkgSymbol = TypeRepr.of[T].typeSymbol.owner // 遍历包下声明的所有字段,过滤出顶层对象 val topLevelObjects = pkgSymbol.declaredFields.filter(_.isModuleDef) // 直接通过符号构造引用,无需包节点 val objectExprs = topLevelObjects.map(sym => Ref(sym).asExprOf[Any]) Expr.ofList(objectExprs)
将上述实现放入你的宏定义对象后,运行你给出的示例代码,就能得到预期的List(Actions, yelling, sleeping, typing)结果。如果需要筛选特定类型的包级成员(比如只继承自Action的对象),可以在过滤阶段通过symbol的类型信息做进一步判断即可。
内容的提问来源于stack exchange,提问作者Pyromuffin
相关产品推荐
相关产品推荐

