我正在评估创建宏注释来实现这一点的可能性和努力:
@txn class Foo(var bar: Int)
进入这个:
import concurrent.stm.{Ref, InTxn}
class Foo(bar0: Int) {
private val _bar = Ref(bar0)
def bar(implicit tx: InTxn): Int = _bar()
def bar_=(value: Int)(implicit tx: InTxn): Unit = _bar() = value
}
(或者也许Foo
用方法创建一个伴随对象apply
,还不确定)
现在我从ClassDef
身体上看到的是这样的
List(<paramaccessor> var bar: Int = _,
def <init>(bar: Int) = {
super.<init>();
()
})
Sobar
显示为没有 init ( _
) 的参数访问器,也显示为<init>
方法的参数。
我将如何重写那个身体?
import scala.reflect.macros.Context
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
class txn extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro txnMacro.impl
}
object txnMacro {
def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val inputs = annottees.map(_.tree).toList
def reportInvalidAnnotationTarget(): Unit =
c.error(c.enclosingPosition,
"This annotation can only be used on a class definition")
val expandees: List[Tree] = inputs match {
case cd @ ClassDef(mods, nme, tp, tmp @ Template(parents, self, body)) :: Nil =>
println(s"Body: $body")
???
case _ =>
reportInvalidAnnotationTarget()
inputs
}
val outputs = expandees
c.Expr[Any](Block(outputs, Literal(Constant(()))))
}
}