6

背景。我正在编写一个 gradle 脚本,并希望使用 ConfigSlurper 内联一些默认配置。我已经能够从文件中解析配置,但似乎无法让内联配置工作。

我想做的是这样的:

myScript = {
   some {
     random {
        stuff = "You can access"
     }
   }
}

groovy.lang.Script script = new groovy.lang.Script() {
   @Override
   Object run() {
      theScript.call()
   }
}

ConfigSlurper slurper = new ConfigSlurper()
slurper.setBinding(["theScript": myScript])
ConfigObject parse = slurper.parse(script)
assert parse.some.random.stuff == "You can access"

这行不通。它说

Caught: groovy.lang.MissingMethodException: No signature of method: scriptStuff.some() is applicable for argument types: (scriptStuff$_run_closure1_closure2) values: [scriptStuff$_run_closure1_closure2@2aca5165]
Possible solutions: dump(), use([Ljava.lang.Object;), sleep(long), wait(), run(), run()
groovy.lang.MissingMethodException: No signature of method: scriptStuff.some() is applicable for argument types: (scriptStuff$_run_closure1_closure2) values: [scriptStuff$_run_closure1_closure2@2aca5165]
Possible solutions: dump(), use([Ljava.lang.Object;), sleep(long), wait(), run(), run()
    at scriptStuff$_run_closure1.doCall(scriptStuff.groovy:2)
    at scriptStuff$_run_closure1.doCall(scriptStuff.groovy)
    at scriptStuff$1.run(scriptStuff.groovy:12)
    at scriptStuff.run(scriptStuff.groovy:18)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

(scriptStuff 是指我运行粘贴脚本的文件:scriptStuff.groovy)

所以我不确定这是否朝着正确的方向发展。实际上,如果您可以将闭包直接传递给 Slurper,那就更好了。但是 Slurper 只接受 Script、脚本文件和 String。另一个方向是将clusure转换为String。这可能吗?

任何解决方案都会很好。

更新 只是想详细说明我的用例。我正在为我的 gradle 脚本创建一个插件。作为用户,我想写这样的东西:

projectConfiguration {
   //this one is easy to parse with ConfigSlurper
   confFile = "some/path/to/configuration.groovy"

   //this is difficult to parse
   inlineConf = {
      some {
         inlined {
            configuration = "Cool!"
         }
      }
   }
}

因此,即使我可以使用字符串表示法对其进行解析,但上面的表示法看起来更流畅,更像 gradle 脚本的其余部分。另一方面,我不介意解析 clojure 丑陋的代码。它只是插件内的用户。重要的是面向用户的部分是干净的。

4

2 回答 2

3

使用解决策略将您的委托设置Closure为脚本:DELEGATE_FIRST

class ClosureScript extends Script {
    Closure closure
    def run() {
        closure.resolveStrategy = Closure.DELEGATE_FIRST
        closure.delegate = this
        closure.call()
    }
}
script = new ClosureScript(closure: myScript)

请参阅从闭包创建 Groovy ConfigObject

于 2013-03-14T20:32:09.967 回答
1

您可以使用 ConfigSlurper 解析这样的字符串:

def myScript = '''
   some {
     random {
        stuff = "You can access"
     }
   }
'''
def config = new ConfigSlurper().parse(myScript)
assert config.some.random.stuff == "You can access"

如果你真的想传递一个 Script,那么你必须扩展 Script,因为它是一个抽象类。例如:

class MyConfiguration extends Script {  
    public Object run() { 
       some {
          random {
             stuff = "You can access"
          }
       }
    }
}

def config = new ConfigSlurper().parse(new MyConfiguration())
assert config.some.random.stuff=="You can access"
于 2013-03-14T15:13:09.023 回答