带有导入语句的 Scala 宏不起作用
scala macro with a import statement not working
我正在注释一个特征,例如:
@ScreenModel
trait TestTrait {
.......
}
然后我得到了 @ScreenModel 的实现,类似:
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val output : List[Tree] = annottees.map(_.tree) match {
case(cd @ q"$mods trait $name[..$tparams] extends ..$parents { ..$body }") :: Nil =>
val compObjVar = s"""{
import models.presentation.blocks.BlockModel;
class AAAA {
class BBBB {
}
}
}""";
val rawTree=c.parse(compObjVar)
val merged = q"{..$rawTree}";
merged :: Nil
case _ => c.abort(c.enclosingPosition, "Invalid test target")
}
c.Expr[Any](q"..$output")
}
所以,我得到:
"top-level class without companion can only expand either into an eponymous class or into a block"
但是,如果我将导入移动到 AAA class 之前的 AAA class 之前,那么它就可以工作了:
val compObjVar = s"""{
class AAAA {
import models.presentation.blocks.BlockModel;
class BBBB {
}
}
}""";
为什么?
它打破了 documentation 的这条规则:
Top-level expansions must retain the number of annottees, their flavors and their names, with the only exception that a class might expand into a same-named class plus a same-named module, in which case they automatically become companions as per previous rule.
这意味着,如果您要转换带有宏注释的 class 或 trait,它必须扩展为同名的 class,或带有同伴的 class同名。也就是说,我们保留正在扩展的树的根。
如果我们尝试将 class A
扩展为:
import package.name
class A
我们正在扩展的树的根不再是 class A
的根,而是包含 class 和新导入的树,但它是什么?不可能什么都没有。减少可能的扩展量会降低插件的复杂性,从而减少可能出错的数量。
如果必须添加导入,可以在 class 中添加。如果导入需要同时出现在 class 和伴随对象中,则可以将它们分解到自己的 Tree
中进行拼接。
我正在注释一个特征,例如:
@ScreenModel
trait TestTrait {
.......
}
然后我得到了 @ScreenModel 的实现,类似:
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val output : List[Tree] = annottees.map(_.tree) match {
case(cd @ q"$mods trait $name[..$tparams] extends ..$parents { ..$body }") :: Nil =>
val compObjVar = s"""{
import models.presentation.blocks.BlockModel;
class AAAA {
class BBBB {
}
}
}""";
val rawTree=c.parse(compObjVar)
val merged = q"{..$rawTree}";
merged :: Nil
case _ => c.abort(c.enclosingPosition, "Invalid test target")
}
c.Expr[Any](q"..$output")
}
所以,我得到:
"top-level class without companion can only expand either into an eponymous class or into a block"
但是,如果我将导入移动到 AAA class 之前的 AAA class 之前,那么它就可以工作了:
val compObjVar = s"""{
class AAAA {
import models.presentation.blocks.BlockModel;
class BBBB {
}
}
}""";
为什么?
它打破了 documentation 的这条规则:
Top-level expansions must retain the number of annottees, their flavors and their names, with the only exception that a class might expand into a same-named class plus a same-named module, in which case they automatically become companions as per previous rule.
这意味着,如果您要转换带有宏注释的 class 或 trait,它必须扩展为同名的 class,或带有同伴的 class同名。也就是说,我们保留正在扩展的树的根。
如果我们尝试将 class A
扩展为:
import package.name
class A
我们正在扩展的树的根不再是 class A
的根,而是包含 class 和新导入的树,但它是什么?不可能什么都没有。减少可能的扩展量会降低插件的复杂性,从而减少可能出错的数量。
如果必须添加导入,可以在 class 中添加。如果导入需要同时出现在 class 和伴随对象中,则可以将它们分解到自己的 Tree
中进行拼接。