Reputation: 7254
I want to embed Groovy to enable scripting capabilities in my Java application. I want to use static type checking, and in addition I want to pass some additional (global) variables to the script. Here is my configuration:
String script = "println(name)"; // this script was entered by the user
// compiler configuration for static type checking
CompilerConfiguration config = new CompilerConfiguration();
config.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
// compile the script
GroovyShell shell = new GroovyShell(config);
Script script = shell.parse(script);
// later, when we actually need to execute it...
Binding binding = new Binding();
binding.setVariable("name", "John");
script.setBinding(binding);
script.run();
As you can see, the user-provided script uses the global variable name
, which is injected via script.setBinding(...)
. Now there is a problem:
name
in the user script (e.g. String name;
), then the binding has no effect because the variable already exists in the script.name
was not declared.The question is: how do I solve this? How can I tell the type checker that the script will receive a global variable of a certain type when it is called?
Upvotes: 4
Views: 1196
Reputation: 9177
From the doc,
You can use extensions
parameter,
config.addCompilationCustomizers(
new ASTTransformationCustomizer(
TypeChecked,
extensions:['robotextension.groovy'])
)
Then add robotextension.groovy to your classpath:
unresolvedVariable { var ->
if ('name'==var.name) {
storeType(var, classNodeFor(String))
handled = true
}
}
Here, we’re telling the compiler that if an unresolved variable is found and that the name of the variable is name, then we can make sure that the type of this variable is String
.
Upvotes: 1