如何在Scala quasiquotes中拼接类型和默认值?

时间:2014-01-11 07:15:45

标签: scala scala-macros scala-quasiquotes

我正在尝试创建一个提供更新案例类的类型提供程序。

我如何拼接类型和默认值(或省略默认值)?

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

任何提示?非常感谢您的光临。

1 个答案:

答案 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")

一切都应该按预期工作。

相关问题