我正在尝试创建一个提供更新案例类的类型提供程序。
我如何拼接类型和默认值(或省略默认值)?
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
import Flag._
val result = {
annottees.map(_.tree).toList match {
case q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$body }" :: Nil =>
val valType = //TODO
val valDefault = //TODO
val helloVal = q"""val x: $valType = $valDefault"""
q"$mods class $name[..$tparams](..$first, $helloVal)(...$rest) extends ..$parents { $self => ..$body }"
}
}
c.Expr[Any](result)
}
我只是尝试了val valType = q"String"
,但后来我收到错误,好像找不到默认值:not enough arguments for method apply
我还尝试在定义为typeOf[String]
的val中拼接,我也尝试将ValDef
s列表拼接到我的q"$mods class...
中(就像我见过的那样)在此网站上的某些类似问题中q"def...
,但在每种情况下都有一个typer error。
任何提示?非常感谢您的光临。
答案 0 :(得分:2)
您可以在tq
的定义中使用valType
插值器来创建类型树。
其余的有点棘手。如果直接定义额外参数,它似乎工作正常:
q"""
$mods class $name[..$tparams](
..$first,
val x: $valType = $valDefault
)(...$rest) extends ..$parents { $self => ..$body }
"""
但是当你定义$helloVal
然后将其插入最终没有默认参数标志时。你可以这样写一个帮手:
def makeDefault(valDef: ValDef) = valDef match {
case ValDef(mods, name, tpt, rhs) => ValDef(
Modifiers(
mods.flags | DEFAULTPARAM, mods.privateWithin, mods.annotations
),
name, tpt, rhs
)
}
现在您可以写下以下内容:
val valType = tq"String"
val valDefault = q""""foo""""
val helloVal = makeDefault(q"val x: $valType = $valDefault")
一切都应该按预期工作。