将类型参数传递给 scala meta macro/annotations
Passing type parameter to scala meta macro/annotations
package scalaworld.macros
import scala.meta._
class Argument(arg: Int) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
println(this.structure)
val arg = this match {
// The argument needs to be a literal like `1` or a string like `"foobar"`.
// You can't pass in a variable name.
case q"new $_(${Lit(arg: Int)})" => arg
// Example if you have more than one argument.
case q"new $_(${Lit(arg: Int)}, ${Lit(foo: String)})" => arg
case _ => ??? // default value
}
println(s"Arg is $arg")
defn.asInstanceOf[Stat]
}
}
我想修改上面的宏并添加类型参数[A]。
我尝试了以下但它没有编译
package scalaworld.macros
import scala.meta._
class Argument2[A](arg: A) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
println(this.structure)
val arg = this match {
case q"new $_(${Lit(arg: A)})" => arg
case q"new $_(${Lit(arg: A)}, ${Lit(foo: String)})" => arg
case _ => ???
}
println(s"Arg is $arg")
defn.asInstanceOf[Stat]
}
}
传入宏注释的参数作为元树传入。
尽管 Int/Double/String 等文字可以通过 Lit()
提取器提取。其他事情不是这样。
在元中解析时
@someMacro(1)
变为 @someMacro(Lit(1))
@someMacro("Foo")
变为 @someMacro(Lit("Foo"))
其他一切都正常通过
@someMacro(foo)
变为 @someMacro(Term.Name("foo"))
@someMacro(Option(2))
变为 @someMacro(Term.Apply(Term.Name("Option"), Seq(Lit(2))))
这意味着您没有运行时访问这个东西。如果没有语义 Api 解析符号等,您甚至无法正确实例化一个对象。它 可能 在 scalameta 2 和天堂 4 中是可能的,但现在肯定是不可能的。您可以做的是进行运行时模式匹配以检查值。
我在这里做了一些类似的事情(注意这是非常 WIP):
https://github.com/DavidDudson/Elysium/blob/master/gen/src/main/scala/nz/daved/elysium/gen/MacroAnnotation.scala
注意:这意味着在运行时(在该示例中恰好是编译时),如果传入的 arg 类型不正确,则会出现运行时异常
package scalaworld.macros
import scala.meta._
class Argument(arg: Int) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
println(this.structure)
val arg = this match {
// The argument needs to be a literal like `1` or a string like `"foobar"`.
// You can't pass in a variable name.
case q"new $_(${Lit(arg: Int)})" => arg
// Example if you have more than one argument.
case q"new $_(${Lit(arg: Int)}, ${Lit(foo: String)})" => arg
case _ => ??? // default value
}
println(s"Arg is $arg")
defn.asInstanceOf[Stat]
}
}
我想修改上面的宏并添加类型参数[A]。 我尝试了以下但它没有编译
package scalaworld.macros
import scala.meta._
class Argument2[A](arg: A) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
println(this.structure)
val arg = this match {
case q"new $_(${Lit(arg: A)})" => arg
case q"new $_(${Lit(arg: A)}, ${Lit(foo: String)})" => arg
case _ => ???
}
println(s"Arg is $arg")
defn.asInstanceOf[Stat]
}
}
传入宏注释的参数作为元树传入。
尽管 Int/Double/String 等文字可以通过 Lit()
提取器提取。其他事情不是这样。
在元中解析时
@someMacro(1)
变为@someMacro(Lit(1))
@someMacro("Foo")
变为@someMacro(Lit("Foo"))
其他一切都正常通过
@someMacro(foo)
变为@someMacro(Term.Name("foo"))
@someMacro(Option(2))
变为@someMacro(Term.Apply(Term.Name("Option"), Seq(Lit(2))))
这意味着您没有运行时访问这个东西。如果没有语义 Api 解析符号等,您甚至无法正确实例化一个对象。它 可能 在 scalameta 2 和天堂 4 中是可能的,但现在肯定是不可能的。您可以做的是进行运行时模式匹配以检查值。
我在这里做了一些类似的事情(注意这是非常 WIP): https://github.com/DavidDudson/Elysium/blob/master/gen/src/main/scala/nz/daved/elysium/gen/MacroAnnotation.scala
注意:这意味着在运行时(在该示例中恰好是编译时),如果传入的 arg 类型不正确,则会出现运行时异常