Scala 宏注释上的类型参数 [英] Type Parameters on Scala Macro Annotations

查看:49
本文介绍了Scala 宏注释上的类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Scala 中使用宏注释,其中我的宏注释将采用另一种类型的参数.然后它会使用scala反射来查看传入的类型,并根据需要添加一些方法.例如.

I'm trying to use macro annotations in scala, where my macro annotation would take an argument of another type. It would then use scala reflection to look at the passed in type, and add some methods as appropriate.Eg.

trait MyTrait {
  def x: Int
  def y: Float
}

@MyAnnotation class MyClass //<-- somehow, this annotation should reference MyTrait

class MyAnnotation(val target: Any) extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro MyAnnotationImpl.impl
}
object MyAnnotationImpl {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    // if I can get a handle on the type MyTrait in here
    // then I can call .members on it, etc.
    ...
  }
}

基本上与在Scala宏中使用Scala反射相同,除了使用宏注释.但是,当我尝试使用 TypeTag 对宏注释进行模板化时

Basically, the same thing as Using Scala reflection in Scala macros, except using macro annotations. However, when I try to template my macro annotation with a TypeTag

class MyAnnotation[T](val target: Any) extends StaticAnnotation {
  def macroTransform[T](annottees: Any*) = macro MyAnnotationImpl.impl[T]
}
object MyAnnotationImpl {
  def impl[T: c.WeakTypeTag](c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    ...
  }
}

我明白

[error] /Users/imran/other_projs/learn_macros/macros/src/main/scala/com/imranrashid/oleander/macros/MacrosWithReflection.scala:7: macro annotation has wrong shape:
[error]   required: def macroTransform(annottees: Any*) = macro ...
[error]   found   : def macroTransform[T](annottees: Any*) = macro ...
[error] class MyAnnotation[T](val target: Any) extends StaticAnnotation {
[error]       ^

我还尝试将类型作为我的注释的参数,所以我会像 @MyAnnotation(MyTrait) class Foo ... 一样使用它.我可以将名称​​作为字符串提取,例如

I've also tried to make the type an argument to my annotation, so I would use it like @MyAnnotation(MyTrait) class Foo .... I can extract the name as a String with something like

val targetTrait = c.prefix.tree match {
  case Apply(Select(New(Ident(_)), nme.CONSTRUCTOR), List(Ident(termName))) => termName
}

但是,我不确定我能用那个 String 做什么来恢复完整类型.我也尝试过像 @MyAnnotation(typeOf[MyTrait]) class Foo ... 这样的变体,然后在 typeOf 上使用 c.eval> 在我的宏中,但也不能编译.

but, I'm not sure what I can do w/ that String to get back the full type. I've also tried variants like @MyAnnotation(typeOf[MyTrait]) class Foo ..., and then use c.eval on the typeOf inside my macro, but that doesn't compile either.

推荐答案

在宏天堂 2.0.0-SNAPSHOT 中,我们有一个非常棘手的方法来访问宏注释的类型参数(当我们有专用的 API 时,这种情况会有所改善为此,但现在在宏天堂中向 scala-reflect.jar 引入新功能非常困难,因此当前的 API 有点粗糙).

In macro paradise 2.0.0-SNAPSHOT we have quite a tricky way of accessing type parameters for macro annotations (the situation will improve later on when we have dedicated APIs for that, but right now it's very difficult to introduce new functionality to scala-reflect.jar in macro paradise, so the current API is a bit rough).

现在需要在注解类上指定类型参数,而不是在 macroTransform 方法上声明任何类型参数.然后,在宏展开中,访问c.macroApplication,提取传入的类型参数对应的无类型树.然后,按照 处理宏注释时无法访问父成员.

For now it's necessary to specify the type parameter on the annotation class and not to declare any type parameters on the macroTransform method. Then, in macro expansion, access c.macroApplication and extract the untyped tree corresponding to the passed type parameter. Afterwards, do c.typeCheck as described in Can't access Parent's Members while dealing with Macro Annotations.

这篇关于Scala 宏注释上的类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆