如果我有一个宏,其中tranforms
代码例如:
(src: a.b.c.TestEntity) =>
{
z.y.TestTable(None)
}
为了匹配该 AST 的 None 部分,我可以使用提取器,例如:
object NoneExtractor {
def unapply(t: Tree): Boolean = t match {
case Select(Ident(scala), none) if scala.encoded == "scala" && none.encoded == "None" => true
case _ => false
}
}
由于showRaw
AST 的 None 部分看起来像:
Select(Ident(scala), None)
但是,如果我想编写一个单元测试,NoneExtractor
我不想编译和重建宏并将测试托管在宏正在编译的项目中。我想对宏项目中的提取器进行单元测试,这表明运行时反射是一种方法:
val t = reify {
(src: a.b.c.TestEntity) =>
{
z.y.TestTable(None)
}
}.tree
然而,这棵树完全不同,在showRaw
那棵树中,None 看起来像:
Ident(scala.None)
这对于编写负面测试和检查我的宏的错误处理来说是个坏消息。您不能使用来自另一个项目的宏为宏编写负面测试,因为代码不会编译(并且您不能调试带有编译错误的负面测试)。
为什么像 None 这样基本的东西的表示在编译时反射和运行时反射之间如此不同?有没有办法在宏项目中创建可测试的树片段,它与编译时反射期间传递给宏的 AST 相同?