2

更新されたケース クラスを提供する型プロバイダーを作成しようとしています。

タイプとデフォルト値をつなぎ合わせる (またはデフォルト値を省略する) にはどうすればよいですか?

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

また、 として定義された val でスプライシングを試みましたtypeOf[String]。 また、 のリストをValDefmy にスプライシングしようとしましたq"$mods class...(このサイトのいくつかの同様の質問で a に行われたようにq"def...) が、それぞれの場合にtyperがあります。エラー

任意のヒント?ご覧いただきありがとうございます。

4

1 に答える 1

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

そして、すべてが期待どおりに機能するはずです。

于 2014-01-11T15:14:07.420 に答える