gpt4 book ai didi

scala - 如何在Scala编译器插件中添加新类?

转载 作者:行者123 更新时间:2023-12-03 07:52:11 25 4
gpt4 key购买 nike

在一个Scala编译器插件中,我试图创建一个实现预先存在特征的新类。到目前为止,我的代码如下所示:

def trait2Impl(original: ClassDef, newName: String): ClassDef = {
val impl = original.impl
// Seems OK to have same self, but does not make sense to me ...
val self = impl.self
// TODO: implement methods ...
val body = impl.body
// We implement original
val parents = original :: impl.parents
val newImpl = treeCopy.Template(impl, parents, self, body)
val name = newTypeName(newName)
// We are a syntheic class, not a user-defined trait
val mods = (original.mods | SYNTHETIC) &~ TRAIT
val tp = original.tparams
val result = treeCopy.ClassDef(original, mods, name, tp, newImpl)
// Same Package?
val owner = original.symbol.owner
// New symbol. What's a Position good for?
val symbol = new TypeSymbol(owner, NoPosition, name)
result.setSymbol(symbol)
symbol.setFlag(SYNTHETIC)
symbol.setFlag(ABSTRACT)
symbol.resetFlag(INTERFACE)
symbol.resetFlag(TRAIT)
owner.info.decls.enter(symbol)
result
}

但是它似乎没有添加到程序包中。我怀疑这是因为实际上该包在导致生成的特征之前已经“遍历”了,和/或因为TypingTransformer的“override def transform(tree:Tree):Tree”方法只能为每个Tree返回一棵Tree它收到的数据,因此它实际上不能产生新的Tree,而只能修改其中的一棵。

那么,如何将新类添加到现有包中?如果我在“transform(Tree)”获得包时对其进行了转换,则可能会起作用,但是我现在还不知道包的内容,所以我不能提早生成新的类(或者可以吗?) 。还是与符号的“位置”参数有关?

到目前为止,我发现了几个修改树的示例,但没有找到在编译器插件中创建全新类的示例。

最佳答案

完整的源代码在这里:https://gist.github.com/1794246

诀窍是存储新创建的ClassDef,并在创建新的PackageDef时使用它们。请注意,您需要同时处理符号和树:包符号只是一个句柄。为了生成代码,您需要生成AST(就像一个类一样,其中的符号包含类的名称和类型,但是代码在ClassDef树中)。

如您所述,包定义在树上比类要高,因此您需要先递归(假设您将从现有类中生成新类)。然后,一旦遍历了子树,就可以使用新类准备一个新的PackageDef(每个编译单元都有一个包定义,默认情况下为空包)。

在示例中,假设源代码为

class Foo {
def foo {
"spring"
}
}

编译器将其包装到
package <empty> {
class Foo {
def foo {
"spring"
}
}
}

然后插件将其转换为
package <empty> {
class Foo {
def foo {
"spring"
}
}
package mypackage {
class MyClass extends AnyRef
}
}

关于scala - 如何在Scala编译器插件中添加新类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7797769/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com