My verdict on AST level joint compilation

Jochen Theodorou <[email protected]> Fri, 24 Apr 2026 01:08:18 +0200
Newsgroups gmane.comp.lang.groovy.devel
Message-ID <[email protected]>
Hi all,

I recently spend some time talking with AI about this project I had in 
mind for a long time: a new joint compiler working on the AST level.

The goal was to allow transforms in Groovy to run and add methods and 
other class structures and give the Javacode a chance to see them.
Basic problem:

A.groovy:
package pa
@MyTransform
class A{def b}

B.java:
package pb;
import pa.*;
public class B extends A {}

C.groovy:
package pc
import pb.*
class C extends B {}

D.java:
package pd;
import pc.C;
public class D extends C {}


To compile the java code you need the Groovy code, but to compile the 
Groovy code you also need the Java code.

Current solution: generate stubs for the Groovy code
This is a lot like having headers in C, where you compile against those 
instead of the full source files. But the real problem is resolving 
classes. In C.groovy we cannot resolve B, since it is in Java. Thus we 
write the import also in the stub and just assume, that Java will 
resolve the class the same way Groovy would do. Which is a "mostly true" 
assumption, but not fully. While the property b in A is no problem, if 
MyTransform adds a method or anything like that in a late phase, then it 
will not be visible to the Java compiler when compiling against the stubs.

So the idea was to create AST ClassNodes from the Java files, compile 
the Groovy code and then compile the java code against the final Groovy 
class files.
The problem here is that class names need to be resolved. And that would 
then happen in the Groovy compiler. Basically an extra resolver for 
those Java source based ClassNodes for resolving in a "Java manner". 
This can become quite complex.

Then I was wondering if the Java compiler could help or maybe a JDT 
based solution. But the resolver in the Java compiler is not made for 
this kind of usage really. You need internals and they will change. JDT 
is better suited but here too it is not quite doing what we want. Both 
will try to resolve too much.

So my thinking was that a hand-written resolver will be needed for this. 
And here I was wondering if it is really worth it. I mean the complexity 
and somebody needs to maintain it as well. In the end the situation is 
like this: if java uses something like lombok, which may add 
constructors fields and methods then we will not see  these things in 
Groovy. It is a bit like a reversal of the situation with the transforms.

The  best solution so far is for me to not mix groovy and java code in 
one src folder, and keep them in different sub projects. The situation 
on top of the post would mandate 4 such sub projects. Advantages are 
that you may not need to compile everything again, you do not generate 
hundreds of small files, that need to be parsed by Javac... 
Disadvantages are of course that you pay for the startup of the 
compilers several times and you can not freely mix.

Do you think I am wrong? I really would like to hear some opinions.... 
even if it is like "joint compilation is not important to us"

bye Jochen