【问题标题】:Getting the contents of closure, in groovy以常规方式获取闭包的内容
【发布时间】:2012-09-22 05:21:16
【问题描述】:

我是 Groovy 的新手。我想实现这个:

def a = { assert 1 == 1 }

def method(def a)
{
    println a
}
method(a)

println 现在打印 ConsoleScript1$_run_closure1@72e9108f。但我希望它能打印assert 1 == 1。那可能吗?

【问题讨论】:

标签: groovy


【解决方案1】:

使用answer I linked to as a duplicate of this,如果你保存:

import groovy.inspect.swingui.AstNodeToScriptVisitor

def a = { assert 1 == 1 }

def method( def a ) {
  new StringWriter().with { writer ->
    a.metaClass.classNode.getDeclaredMethods("doCall")[0].code.visit new AstNodeToScriptVisitor( writer )
    println "{\n$writer}"
  }
}

method( a )

到文件test.groovy 然后执行:

groovy test.groovy

你得到输出:

{
assert 1 == 1 : null
return null
}

我认为这与您将要得到的一样接近...不使用code 变量(这是Groovy Statement class)中的位置数据来获取行/列号并将文件解析为文本来提取它...

【讨论】:

  • 这行得通。但是如果你像这样调用replaceAll 方法:"{$writer}".replaceAll(/ (null)|(return)|\n|:|/,"") 我得到更清晰的输出:{assert 'someting' == 2 }
  • 在 grails 中这似乎不起作用。我将关闭从控制器传递到服务。我在服务中定义了method。当我尝试调用method(closure) 时,我收到此错误:Cannot invoke method getDeclaredMethods() on null object。哪里出了问题?
  • 啊……你没有说这是在 Grails 中。我猜在 Grails 中运行时,它找不到对象的原始classNode,所以返回null。可能有办法解决这个问题,但重新考虑您的要求可能更容易。为什么需要这个功能?
  • 我们正在创建一个内置的测试工具。我会将 assert 语句作为关闭传递给我的服务。在服务中,我将执行断言闭包并查找错误。最后我们需要将结果放入 NoSql 中,我需要在其中保存测试用例的详细信息。所以我的想法是从传递的闭包本身获取内容,但这似乎不起作用!
  • 您能否将闭包作为字符串传递,然后使用Eval.me 之类的东西评估字符串(并运行它)?然后你有一个闭包,以及它的字符串......
【解决方案2】:

您正在寻找类似 Javascript 的功能,其中在函数上调用 toString() 会打印其源代码。

Groovy 被编译为 JVM 字节码。 groovy 编译器不会在编译后的 JVM 类文件中保留源代码。

【讨论】:

    【解决方案3】:

    在 Odersky & Co. 的《Programming in Scala》一书中有一个用 Scala 编写的著名示例。

    基本上,你必须:

    • 列出文件
    • 对于每个匹配 *.groovy 的文件
    • 修剪/grep 想要的行

    Groovy SDK 中,有一个Groovy 方法directory.eachFileMatch 可以让您找到正确的文件,还有一个File.filterLine() 方法可以让您抓取正确的行。

    【讨论】:

    • 您可以从 AST 中获取该信息,这将比有效地使用正则表达式解析源文件提供更好的结果
    猜你喜欢
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    相关资源
    最近更新 更多