处理宏注释时无法访问Parent的成员

时间:2013-10-15 10:54:08

标签: scala macros annotations code-generation companion-object

我被以下(宏注释)阻止了 情况。假设我有一个名为@factory的注释 旨在为相应的伴随对象中的带注释的特征生成apply方法。例如,给定trait A

@factory
trait A {
  val a1: Int
}

要生成的预期代码如下:

object A extends Factory[A] {
  def apply(_a1: Int) = new A {
    val a1 = _a1
  }
}

现在假设我们有一个特性B,它继承自A

@factory
trait B extends A {
  val b1: String
}

应该生成:

object B extends Factory[B] {
  def apply(_a1: Int, _b1: String) = new B {
    val a1 = _a1
    val b1 = _b1
  }
}

在后一种情况下,我需要知道A中存在哪些属性,但我不知道如何获取有关它们的任何信息。在处理宏注释时,我只能访问B特征AST(作为ClassDef)。虽然其template包含对父母的引用(TypeTrees),但tpesymbol字段均为空。

对我来说,访问A AST非常棒。但是,我认为这是不可行的。因此,任何符号或类型(指向父类型或当前类型)都足够好。

如果您想查看更多实施细节,我已将项目上传至https://github.com/jesuslopez-gonzalez/cool-factory。它可以为本地值生成apply

1 个答案:

答案 0 :(得分:10)

进入宏注释参数的树是有目的地无类型的。但是,运行c.typeCheck(q"(??? : <tree that represents the parent>)").tpe将提供缺少的信息。在类型检查之前不要忘记duplicate那棵树,因为c.typeCheck会使树变异,这可能是不可取的。

如果父和子都声明在同一个非顶层范围内,则会出现typeCheck看不到父节点的问题,因为宏注释中的c.typeCheck是在父词法范围内执行的,因此注释不会看不到半构造的范围。这里报道了类似的事情:https://github.com/aztek/scala-workflow/issues/2#issuecomment-23947943

将当前范围从类型检查中排除的决定不是最终决定。本周我将更多地思考宏注释应如何与封闭范围进行交互,并且可能会将其更改为您希望它执行的操作。我现在正在进行更改,但我需要确保不会因为这种改变而产生任何疯狂的行为。