只需将一个val添加到模板中,不会自动使其成为构造函数参数。为此,构造函数本身也需要进行调整。幸运的是,我们有quasiquotes,与手动树构建相比,这大大简化了这项任务。
case q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$body }" :: Nil =>
val CASEACCESSOR = (1 << 24).toLong.asInstanceOf[FlagSet]
val PARAMACCESSOR = (1 << 29).toLong.asInstanceOf[FlagSet]
val helloMods = Modifiers(CASEACCESSOR | PARAMACCESSOR | DEFAULTPARAM)
val helloVal = q"""$helloMods val x: String = "hello macro!""""
q"$mods class $name[..$tparams](..$first, $helloVal)(...$rest) extends ..$parents { $self => ..$body }"
注意几个怪癖:1)我们需要设置CASEACCESSOR和PARAMACCESSOR标志不存在官方的API中为了避免撞车萨拉特,2),我们需要以设定DEFAULTPARAM到确保scalac将默认参数识别为默认参数,3)默认参数不能推断它们的类型,所以我们需要在这里显式地提供String。
太棒了!我需要quasiquotes的例子,谢谢一堆(同时,好的错误信息正在帮助我)。我已更新我的项目以显示工作示例。 –
随着最新的quasiquotes,你不需要任何caseaccessor | paramacessor魔法,这些标志将自动设置在幕后。 –
p.s.实际上DEFAULTPARAM也不是必需的。只需创建一个val并将其拼接到参数位置,它应该可以正常工作。 –