Background. I'm working on a gradle script and want to inline some default configuration using the ConfigSlurper. I'm already able to parse configurations from files, but can't seem to get the inlined configuration to work.
What i want to do is something like this:
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"
This doesn't work. It says
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 refers to the file i run the pasted script from: scriptStuff.groovy)
So i'm not sure this in the correct direction. Actually it would be nicer if you could just pass the closure directly to the Slurper. But the Slurper only takes Script, script file, and String. Another direction would be to convert the clusure to a String. Is this possible?
Any solution would be nice.
Update Just wanted to elaborate a bit on my use case. I am creating a plugin to my gradle scripts. As a user i want to write something like this:
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!"
}
}
}
}
So even though i could have parsed it using a string notation, then the notation above looks a lot slicker, and more like the rest of the gradle script. On the other hand i don't mind the code parsing the clojure beeing ugly. It's only user inside the plugin. The important ting is that the user facing part is clean.
Set the delegate on your Closure
to the script with a DELEGATE_FIRST
resolve strategy:
class ClosureScript extends Script {
Closure closure
def run() {
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.delegate = this
closure.call()
}
}
script = new ClosureScript(closure: myScript)
See Creating a Groovy ConfigObject from a Closure.
You can use ConfigSlurper to parse a String like this:
def myScript = '''
some {
random {
stuff = "You can access"
}
}
'''
def config = new ConfigSlurper().parse(myScript)
assert config.some.random.stuff == "You can access"
If you really want to pass a Script, then you must extends Script because it is an abstract class. For example:
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With