使用Intellij的(几乎未记录的)gdsl脚本,可以向类中添加动态方法:
contributor(context(ctype: "my.Type")) {
method name: "doIt", params: [body: {}], type: void
}
还可以配置闭包的委托:
contributor(context(scope: closureScope())) {
def call = enclosingCall("doIt")
if (call) {
def method = call.bind()
def clazz = method?.containingClass
if (clazz?.qualName == 'my.Type') {
delegatesTo(findClass('my.Inner'))
}
}
}
当doIt
是代码中定义的方法(未动态添加)时,也可以按设计工作。
但是,将closureScope
与之前的创建的方法一起使用时,containing
类方法始终为null
,这意味着我无法安全地委托对已解决的my.Inner
类的闭包。
我想要的是添加一个等同于:
的动态方法void doIt(@DelegatesTo(my.Inner) Closure)...
即。我希望该方法在代码完成中可用(这是有效的),并且在创建的闭包内部,我希望在解决my.Inner
的方法时正确完成代码。
到目前为止,我尝试了各种方法:
doIt
的所有闭包委托给my.Inner
,但这不是可行的解决方案,因为我有多个doIt
方法(在不同的类上)委托给不同的目标。那么,我如何让IDEA按预期行事并委托给正确的目标呢?
编辑以使其更清晰:
鉴于以下类别:
package my
class Type {
void doIt(Closure) {}
}
class Inner {
void inInner() {}
}
以及以下gdsl:
contributor(context(scope: closureScope())) {
def call = enclosingCall("doIt")
if (call) {
def method = call.bind()
def clazz = method?.containingClass
println clazz?.qualName
if (clazz?.qualName == 'my.Type') {
delegatesTo(findClass('my.Inner'))
}
}
}
当我开始输入新脚本时:
new Type().doIt {
inInner()
}
当在封闭内部时,我得到以下内容:
inInner
inInner
显示为有效my.Type
(来自println
)inInner
上的Ctrl-B正确链接到源代码。(当使用doIt
@DelegatesTo(Inner)
方法注释闭包参数时,可以在没有gdsl的情况下达到相同的行为
但是,我不想在Type的源代码中手动包含doIt
方法,它是由AST Transformation生成的,所以我的源文件现在看起来像这样:
package my
class Type {
}
class Inner {
void inInner() {}
}
我可以使用以下gdsl片段
告诉IntelliJ有关新方法的信息contributor(context(ctype: "my.Type")) {
method name: "doIt", params: [body: {}], type: void
}
现在IDE正确识别带闭包参数的doIt方法。但是,在Closure中,会发生以下情况:
inInner
,有时在更改内容之后,它没有(当使用原始代码修复类型时,它显示,但后来声明为“未解析”),经过代码更改后这个编辑过的例子,它不再显示了......)inInner
也会显示“无法解析符号”装饰null
显示为clazz
,即找到方法但未链接到所有者ASTNode Inner
所以我想要的是注入doIt
方法(通过Gdsl)与源代码中包含的方法相同的行为,即我希望gdsl向委托注入doIt
方法关闭(到Inner)进入type
类。
答案 0 :(得分:1)
这有助于我将ctype添加到从方法
中查找类类型的范围contributor(context(scope: closureScope(), ctype: 'my.Type')) {
def call = enclosingCall("doIt")
if (call) {
delegatesTo(findClass('my.Inner'))
}
}