将参数传递给scalameta paradise宏
我正在尝试创建宏注释,但需要传递参数将参数传递给scalameta paradise宏,scala,macros,scala-macros,scalameta,Scala,Macros,Scala Macros,Scalameta,我正在尝试创建宏注释,但需要传递参数 class ToPojo(param1: String, param2: String) extends StaticAnnotation { inline def apply(defn: Any): Any = meta { ... } } 它被用作 @ToPojo("p1", "p2") case class Entity(a: Int, m: Map[Long, Boolean]) 上面代码的问题是,实体已经以defn的形式
class ToPojo(param1: String, param2: String) extends StaticAnnotation {
inline def apply(defn: Any): Any = meta {
...
}
}
它被用作
@ToPojo("p1", "p2")
case class Entity(a: Int, m: Map[Long, Boolean])
上面代码的问题是,实体已经以defn的形式获取apply,并且注释已被剥离,因此我无法从那里获取参数。此外,由于apply方法是内联的,因此无法从apply方法访问param1和param2字段
您能告诉我使用scala meta克服此问题的最简单方法吗?我考虑使用两个注释
@ToPojo
@ToPojoParams("p1", "p2")
case class Entity(a: Int, m: Map[Long, Boolean])
但那是又黑又丑的
非常感谢如第节“ScalaMeta天堂描述”中所述 您可以将其作为Scalameta树进行匹配 请注意,这段代码有点幼稚,不处理命名参数。如果您有许多参数,那么编写所有可能的常用参数和命名参数的组合是很无聊的。因此,您可以尝试以下方法:
package examples
import scala.collection.immutable
import scala.meta._
class MyMacro(p1: String, p2: Int) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
val params = Params.extractParams(this)
//some implementation
...
}
}
case class Params(p1: String, p2: Int) {
def update(name: String, value: Any): Params = name match {
case "p1" => copy(p1 = value.asInstanceOf[String])
case "p2" => copy(p2 = value.asInstanceOf[Int])
case _ => ???
}
}
object Params {
private val paramsNames = List("p1", "p2")
def extractParams(tree: Stat): Params = {
val args: immutable.Seq[Term.Arg] = tree.asInstanceOf[Term.New].templ.parents.head.asInstanceOf[Term.Apply].args
args.zipWithIndex.foldLeft(Params(null, 0))((acc, argAndIndex) => argAndIndex._1 match {
case q"${Lit(value)}" => acc.update(paramsNames(argAndIndex._2), value)
case q"${Term.Arg.Named(name, Lit(value))}" => acc.update(name.value, value)
})
}
}
package examples
import scala.collection.immutable
import scala.meta._
class MyMacro(p1: String, p2: Int) extends scala.annotation.StaticAnnotation {
inline def apply(defn: Any): Any = meta {
val params = Params.extractParams(this)
//some implementation
...
}
}
case class Params(p1: String, p2: Int) {
def update(name: String, value: Any): Params = name match {
case "p1" => copy(p1 = value.asInstanceOf[String])
case "p2" => copy(p2 = value.asInstanceOf[Int])
case _ => ???
}
}
object Params {
private val paramsNames = List("p1", "p2")
def extractParams(tree: Stat): Params = {
val args: immutable.Seq[Term.Arg] = tree.asInstanceOf[Term.New].templ.parents.head.asInstanceOf[Term.Apply].args
args.zipWithIndex.foldLeft(Params(null, 0))((acc, argAndIndex) => argAndIndex._1 match {
case q"${Lit(value)}" => acc.update(paramsNames(argAndIndex._2), value)
case q"${Term.Arg.Named(name, Lit(value))}" => acc.update(name.value, value)
})
}
}