May 26, 2009

Grails built with Eclipse JDT Incremental Joint groovy/java compiler

Just a quick entry on this. Each time I tackle compiling a new mixed java/groovy codebase, a new set of issues appear. No surprises really, just features I knew were not implemented yet that the particular codebase exploits. But here is the good news (this is Eclipse JDT compiler debug output):

>FULL BUILD STATS for: grails
> compiled 139801 lines in 63692ms:2194.9lines/s
> parse: 7437 ms (11.6%), resolve: 1150 ms (1.8%),
> analyze: 50634 ms (79.4%), generate: 2836 ms (4.4%)
Recording new state : State for grails (#0 @ Tue May 26 11:47:22 PDT 2009)
Remember, those 'lines' counts are just including the java code right now. And don't read much into the time taken as I have more debug code than real code right now :)

Anyway, there were a couple of interesting cases in getting grails to compile that are worth talking about, just to give a feel for what is possible with this incremental compiler:

Properties
In Grails, the GROOVY type Mapping defines:
  boolean tablePerHierarchy = true
This is then referenced from a JAVA type (GrailsDomainBinder) through
  mapping.isTablePerHierarchy()
The modified JDT compiler handles this no problem.


Default parameter values
The GROOVY type GrailsPluginUtils defines this method with a default value for the closure parameter:

static synchronized Resource[] getArtefactResources(
String basedir,
Closure resourceResolver = DEFAULT_RESOURCE_RESOLVER) {
The JAVA type GrailsAwareGroovyTestSuite then accesses it through:
GrailsPluginUtils.getArtefactResources(grailsSettings.getBaseDir().getPath());
(supplying just the first parameter on the call)

The modified JDT compiler handles this no problem.


Generics
The GROOVY type NaturalId looks like this:

public class NaturalId {
List<String> propertyNames = []
boolean mutable = false
}

The JAVA type GrailsDomainBinder then attempts to access the propertyNames through a getter and treat the elements as Strings.

for (String propertyName : naturalId.getPropertyNames()) {
The modified JDT compiler handles this no problem.



But, of course, the best thing is that incremental compilation works. Let me break that property 'propertyNames' - change the type to just 'List' and save:

Starting build of grails @ Tue May 26 12:11:56 PDT 2009
Found source delta for: grails
Clearing last state : State for grails (#3 @ Tue May 26 11:58:31 PDT 2009)
INCREMENTAL build
Compile this changed source file src/.../NaturalId.groovy
About to compile src/.../NaturalId.groovy
Type has structural changes ...\NaturalId
will look for dependents of NaturalId in org/codehaus/groovy/grails/orm/hibernate/cfg
Writing changed class file NaturalId.class
Found match in org.codehaus.groovy.grails.orm.hibernate.cfg to NaturalId
adding affected source file src/.../GrailsDomainBinder.java
... edited out a list of other affected types ...
About to compile src/.../GrailsDomainBinder.java
Recording new state : State for grails (#4 @ Tue May 26 12:11:56 PDT 2009)
Finished build of grails @ Tue May 26 12:12:04 PDT 2009

it recognized that GrailsDomainBinder need a rebuild and now recorded an error against the attempted iteration:

Type mismatch: cannot convert from element type Object to String

Fixing the problem (converting propertyNames back to type List<String>) and resaving gives a similar incremental build log and the problem vanishes.

Anyway, that is probably the last codebase I'll experiment upon - the size of the task ahead is apparent, so the focus now is making what there is robust enough to distribute to other users.

8 comments:

Jeff Brown said...

Fantastic! Thanks for the great work Andrew. -- Jeff

breskeby said...

looking forward to switch back to eclipse for my groovy / grails projects...

regards,
René

Jim Shingler said...

Woohooo! Keep up the good work

Daniel K said...

Brilliant. You, sir, are a genius.

Adam said...

Great news!

dserodio said...

Awesome work, keep us posted on your progress! You made me optimistic about the future of Groovy IDE support again.

Dominic said...

you mention you're using eclipse 3.4 right now, any idea if the changes will be easy to port to eclipse 3.5 now that it's out?

Andy Clement said...

port to eclipse 3.5 is done. update site is listed in a comment on the springsource blog article (http://blog.springsource.com).

Surprisingly porting these compiler changes to 3.5 was trivial, compared to what I normally have to do migrating AspectJ to a new compiler level.

Post a Comment