Use type checked or compile static for Groovy scripts?

When you create a ‘script’ in Groovy, the type check or static compilation annotations cannot be applied to the script itself?
Updates

Background
Groovy has two features that improve it’s use as a “normal” application language: static type checking and static compilation. The first gives compile time feedback of issues instead of at runtime due to the dynamic nature of Groovy. The second slightly improves performance (in lieu of full JDK 7 “invoke dynamic”).

@TypeChecked and @CompileStatic can applied to a method or a class.

Groovy Scripts
Using Groovy as a dynamic scripting language is still very important, and the most direct use is to just write Groovy code in a text file. This sounds strange since Groovy is a scripting language, but a Groovy Script is a plain script that does not have a class declaration. They can have methods and nested classes. Internally Groovy compiles this text file to a standard JVM class that extends Groovy’s Script class, the original source script is wrapped in a ‘run’ method, and a main method is added as a convenient entry point. There are more details, of course.

An example groovy script:

println "Hello world!"

Scripts that start out small can grow to be very large and complex. Perhaps it would be useful to allow this script compilation to be statically type checked or statically compiled? From a web search attempt this does not seem to be a concern, however, P. Niederwieser has made this proposal.

Work around?
Since a script is just a Groovy class, one can just directly create a Groovy class with a main method. Example:

import groovy.transform.TypeChecked;

//@TypeChecked
class Hello {
	static int x = 1
	
	def run(msg){
		println "Hello $msgx"	
	}
	
	static main(args) {
		new Hello().run(x)
	
	}

}

When this is run we get:

Caught: groovy.lang.MissingPropertyException: No such property: msgx for class: Hello
Possible solutions: x
groovy.lang.MissingPropertyException: No such property: msgx for class: Hello
Possible solutions: x
        at Hello.run(Hello.groovy:8)
        at Hello$run.call(Unknown Source)
        at Hello.main(Hello.groovy:12)

Not too bad, at least we get some hints as to what the problem is. If we instead compile the Groovy script we get:

groovyc Hello.groovy

That’s right, nothing. Our script is compiled into Hello.class, and we won’t know there is a problem until run-time. Note that, when we ran the script, Groovy performed the compilation at run time, then executed the script.

If we uncomment the type check annotation and compile or just run the script with groovy Hello.groovy, we get:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Hello.groovy: 8: [Static type checking] - The variable [msgx] is undeclared.
 @ line 8, column 19.
          println "Hello $msgx"
               ^
1 error

This is the same behavior in an IDE. In Eclipse, with the annotation, the error is flagged and the mouse-over hover contains: Groovy:[Static type checking] – The variable [msgx] is undeclared.

Summary
Does Groovy need CompileStatic or TypeChecked on scripts? From the above illustration, type checking is useful. Yes, everyone checks their scripts, except when they don’t.

Addendum
Yup, didn’t go into compile static. That would involve micro-benchmarks which are difficult to do correctly.

Updates
Feb 26, 2014: Cédric Champeau, on Feb 9, 2014, has updated the nabble thread with info that this can indeed be done:

“It is possible to use @TypeChecked or @CompileStatic on a script, using the compiler configuration (see http://groovy.codehaus.org/Advanced+compiler+configuration, “static compilation by default“).”
 

References

Leave a Reply

Your email address will not be published. Required fields are marked *