Scala宏得到封闭线

时间:2013-12-08 10:58:43

标签: scala scala-macros

我有以下宏

object Example {
  def doIt(s: String): String = macro doItImpl

  def doItImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = {
    import c.{ universe => u }
    import u._
    ???
  }
}

而不是???我想检查调用方法doIt的行,以检查方法的结果是否被使用(在赋值,方法调用或其他方面)。如果未使用结果,我会回复错误消息。

呼叫-示例:

val s: String = doIt("Hallo") // alright
doIt("Hallo") // ERROR!

有没有一种简单的方法可以获得整条线的树?

1 个答案:

答案 0 :(得分:4)

为了完整起见,这是我在上面提到的the solution的轻微改编版本:

import scala.language.experimental.macros
import scala.reflect.macros.Context

object Example {
  def doIt(s: String): String = macro doItImpl

  def doItImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = {
    import c.universe._

    c.enclosingClass.collect {
      case ValDef(_, name, _, rhs) if rhs.pos == c.macroApplication.pos =>
        c.literal(s"Okay, defining a variable named ${name.decoded}.")
    }.headOption.getOrElse(
      c.abort(c.enclosingPosition, "Not a valid application.")
    )
  }
}

现在在REPL中:

scala> import Example._
import Example._

scala> object Test1 { val x = doIt("foo") }
defined module Test1

scala> Test1.x
res0: String = Okay, defining a variable named x.

如果我们没有定义:

scala> object Test2 { doIt("foo") }
<console>:13: error: Not a valid application.
       object Test2 { doIt("foo") }
                          ^

正如所料。有关一些警告,请参阅上面链接的问题的评论,但除非您的实际用例更复杂,否则此方法应该可以正常工作。