简体   繁体   English

Scala宏注释-当我将其用作类型参数时,为什么类似乎没有更新?

[英]Scala Macro Annotations - Why doesn't my class appear to be updated when I use it as a type parameter?

I used Eugene Burmako's macro annotation example from Macro Paradise (thanks Eugene!) and modified here it to add a val to an empty class here . 我用尤金Burmako宏观注释例如,从宏观天堂 (感谢尤金!),并在这里修改了它的添加val到一个空的类在这里

As an instance, I can call the new val as expected. 作为一个实例,我可以按预期的那样调用新的val But when I try to use the updated class as a type parameter, eg in Salat (parses a Scala sig) or Scalavro (uses 2.10 reflection), then the class appears still empty (ie as if the val was never added). 但是,当我尝试将更新的类用作类型参数时,例如在Salat (解析为Scala sig)或Scalavro (使用2.10反射)中,则该类仍然显示为空(即,好像从未添加过val )。

Since Salat parses the Scala signature, I checked and it's shorter than a normal signature by about 30 entries, and the order of the entries differs. 由于Salat解析了Scala签名,因此我进行了检查,它比正常签名短约30个条目,并且条目的顺序有所不同。 Yet it does appear that the signature includes info about the added val . 但是似乎签名确实包含有关添加的val

So how come the new val info is not accessible, and is there any way to make it so? 那么,为什么无法访问新的val信息,有什么办法可以做到呢? Thanks for taking a look. 谢谢参观。

Just adding a val into a template doesn't automatically make it a constructor parameter. 仅将val添加到模板中并不会自动使其成为构造函数参数。 To do that, the constructor itself also needs to be adjusted. 为此,构造函数本身也需要进行调整。 Luckily we have quasiquotes, which greatly simplify this task in comparison with manual tree construction. 幸运的是,我们有准引用,与手动树构建相比,它大大简化了此任务。

case q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$body }" :: Nil =>
  val CASEACCESSOR = (1 << 24).toLong.asInstanceOf[FlagSet]
  val PARAMACCESSOR = (1 << 29).toLong.asInstanceOf[FlagSet]
  val helloMods = Modifiers(CASEACCESSOR | PARAMACCESSOR | DEFAULTPARAM)
  val helloVal = q"""$helloMods val x: String = "hello macro!""""
  q"$mods class $name[..$tparams](..$first, $helloVal)(...$rest) extends ..$parents { $self => ..$body }"

Note a couple of quirks: 1) we need to set CASEACCESSOR and PARAMACCESSOR flags that aren't present in the official API in order to avoid crash in Salat, 2) we need to set DEFAULTPARAM in order to make sure that scalac recognizes our default parameter as default, 3) default parameters can't have their types inferred, so we need to explicitly provide String here. 请注意几个怪癖:1)我们需要设置官方API中不存在的CASEACCESSOR和PARAMACCESSOR标志,以避免Salat崩溃; 2)我们需要设置DEFAULTPARAM,以确保scalac能够识别默认值参数为默认值,3)无法推断默认参数的类型,因此我们需要在此处显式提供String。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM