我被以下(宏注释)阻止了
情况。假设我有一个名为@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
),但tpe
和symbol
字段均为空。
对我来说,访问A
AST非常棒。但是,我认为这是不可行的。因此,任何符号或类型(指向父类型或当前类型)都足够好。
如果您想查看更多实施细节,我已将项目上传至https://github.com/jesuslopez-gonzalez/cool-factory。它可以为本地值生成apply
。
答案 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。
将当前范围从类型检查中排除的决定不是最终决定。本周我将更多地思考宏注释应如何与封闭范围进行交互,并且可能会将其更改为您希望它执行的操作。我现在正在进行更改,但我需要确保不会因为这种改变而产生任何疯狂的行为。