任何知道如何在Groovy中打印闭包源的人?
例如,我有这个闭包(绑定到a
)
def a = { it.twice() }
我想要String
“it.twice()”或“{it.twice()}”
只是一个简单的toString
课程不起作用:
a.toString(); //results in: Script1$_run_closure1_closure4_closure6@12f1bf0
答案 0 :(得分:28)
简短的回答是你做不到的。答案很长:
根据你需要的代码,你可能会侥幸逃脱
// file: example1.groovy
def a = { it.twice() }
println a.metaClass.classNode.getDeclaredMethods("doCall")[0].code.text
// prints: { return it.twice() }
BUT
您需要在类路径AT RUNTIME中提供的脚本源代码,如
groovy.lang.MetaClass#getClassNode()
“获得原始参考 如果是MetaClass的AST 在运行时可用 @return 原始AST或null如果不能 返回“
和
text 技巧并没有真正返回相同的代码,只是像AST的表示一样的代码,可以在这个脚本中看到
// file: example2.groovy
def b = {p-> p.twice() * "p"}
println b.metaClass.classNode.getDeclaredMethods("doCall")[0].code.text
// prints: { return (p.twice() * p) }
如果您只是想快速浏览一下,它可能会很有用
并且,如果你手上有太多时间并且不知道该怎么做,你可以写自己的org.codehaus.groovy.ast.GroovyCodeVisitor
来打印它
或者,只是窃取现有的groovy.inspect.swingui.AstNodeToScriptVisitor
// file: example3.groovy
def c = {w->
[1,2,3].each {
println "$it"
(1..it).each {x->
println 'this seems' << ' somewhat closer' << ''' to the
original''' << " $x"
}
}
}
def node = c.metaClass.classNode.getDeclaredMethods("doCall")[0].code
def writer = new StringWriter()
node.visit new groovy.inspect.swingui.AstNodeToScriptVisitor(writer)
println writer
// prints: return [1, 2, 3].each({
// this.println("$it")
// return (1.. it ).each({ java.lang.Object x ->
// return this.println('this seems' << ' somewhat closer' << ' to the \n original' << " $x")
// })
// })
现在。
如果你想要原始,精确,可运行的代码......你运气不好
我的意思是,您可以使用源行信息,但上次我检查时,它并没有真正使它们正确
// file: example1.groovy
....
def code = a.metaClass.classNode.getDeclaredMethods("doCall")[0].code
println "$code.lineNumber $code.columnNumber $code.lastLineNumber $code.lastColumnNumber"
new File('example1.groovy').readLines()
... etc etc you get the idea.
尽管,行号仍然至少接近原始代码
答案 1 :(得分:6)
这在groovy中是不可能的。即使直接运行groovy脚本而不先编译它,脚本也会转换为JVM字节码。闭包不会有任何不同的处理,它们像常规方法一样编译。到运行代码时,源代码不再可用。