将类型参数传递给scala元宏/注释

将类型参数传递给scala元宏/注释,scala,scala-macros,scalameta,Scala,Scala Macros,Scalameta,我想修改上面的宏并添加类型参数[A]。 我尝试了以下内容,但它无法编译 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 {

我想修改上面的宏并添加类型参数[A]。 我尝试了以下内容,但它无法编译

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]
  }
}

传入宏注释的参数作为元树传入

尽管可以通过Lit提取器提取Int/Double/String等文本。其他事情并非如此

当在meta中解析时

@someMacro1变成@someMacroLit1 @someMacroFoo变成@someMacroLitFoo 其他一切都像平常一样通过了

@someMacrofoo变成@someMacroTerm.Namefoo @someMacroOption2变为@someMacroTerm.ApplyTerm.NameOption,SeqLit2 这意味着您没有运行时访问此对象的权限。如果没有语义Api来解析符号等,您甚至无法正确实例化对象。在scalameta 2和paradise 4中,这可能是可能的,但现在肯定是不可能的。您可以做的是使运行时模式匹配以检查值

我在这里做了一些类似的事情注意这是非常在制品:

具体见


注意:这意味着在运行时(在该示例中恰好是编译时),如果传入的arg类型不正确,运行时异常

我只是想做一些与这里描述的类似的事情谢谢@David Dudson我在编译这个类时遇到了一个错误你能提供paradise_2.11.8-3.0.0-SNAPSHOT.jar吗?[错误]/Users/batemady/tools/scala/samples/meta/scalameta tutorial/src/main/scala/scala/meta/serialiser/MacroAnnotation.scala:14:;预期但def找到[error]val newStat=q$compileTimeOnly内联def applya:Any:Any=meta{..$inMetaBlockStats}我在尝试编译整个Elysium项目时遇到以下错误[error]缺少必需的插件:Macroparadise最终通过在添加项目正在使用此PR的Paradise插件的行中添加注释成功编译了它。Elysium不应该在没有PR的情况下编译,因为它处理生成其他宏的宏。我想做的是在扩展时使用传递给宏的类型参数。在下面的宏中,我可以打印传递给宏的参数,但不知道如何在生成返回的树defn import scala.annotation.StaticAnnotation类tparam[T,L]扩展StaticAnnotation{inline def applydefn:Any:Any=meta时使用并用传入的参数替换T和L{assertT.toString==Int assertL.toString==String printlnT.toString printlnL.toString defn}
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]
  }
}