I'm using Groovy to allow users to script and customize certain parts of my Java application. I am using static compilation of all user-provided scripts.
My question is: if my code expects to receive e.g. a value of type boolean as the result of the user script, is there any way for me to check whether or not the provided user script will always return a boolean without actually executing the script? In other words, how can I access the results of the type inference performed by the static groovy compiler? I would like to be able to tell the user "hey, your script does not always return a boolean" while they are editing the script content.
There is no straight-forward way, but it's possible. Boolean is especially hard as the compiler will happily apply all sorts of type-coersions (e.g. transform an int to boolean without complaining). I've had the exact same problem and did the following steps:
For 1:
Extend ClassCodeVisitorSupport
, in visitMethod
identify all methods you want to return boolean (e.g. check for matching naming conventions)
Set the returnType
of the MethodNode
to ClassHelper.boolean_TYPE
For 2:
For the same methods as above call org.codehaus.groovy.classgen.ReturnAdder.visitMethod
For 3:
Extend AbstractTypeCheckingExtension
, override afterVisitMethod
. At this point the AbstractTypeCheckingExtension
will have inferred the lower bound of all expressions inside the method. Use a ClassCodeVisitorSupport
subclass and override visitReturnStatement
. Use getType(statement.expression)
to get the inferred type. Note that this can be different from statement.expression.type
(the type according to the AST). Call addStaticTypeError
on non boolean type.
For 4:
Extend StaticTypesTransformation
Override newVisitor
and create a new StaticTypeCheckingVisitor
and call addTypeCheckingExtension
on it to add your TypeCheckingExtension
https://github.com/MeneDev/groovy-dsl-building-blocks-enforce-return-type
It may even be reusable as a dependency ;)