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

StackOverflow https://stackoverflow.com/questions/19702186

Frage

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.

As an instance, I can call the new val as expected. But when I try to use the updated class as a type parameter, e.g. in Salat(parses a Scala sig) or Scalavro(uses 2.10 reflection), then the class appears still empty (i.e. as if the val was never added).

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. Yet it does appear that the signature includes info about the added val.

So how come the new val info is not accessible, and is there any way to make it so? Thanks for taking a look.

War es hilfreich?

Lösung

Just adding a val into a template doesn't automatically make it a constructor parameter. 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top