Hi all,

yesterday I was playing around with joint compilation and I want to
share some thoughts:

current state (afaik): V0

Groovy creates stubs, Javac compiles Java and stubs, Groov compiles
against generated classes. Annotationprocessing on Java should work, on
Groovy it depends on the phase. Reading constants from Java compiled
classes should work for Groovy, I the stubs contain these too, therefore
Java can read the constants as well. Since this runs the Groovy compiler
and the Java compiler together, this consumes quite a bit of memory.

In summary this works quite well with some problems in the stubs here
and there, memory consumption is not so nice, limitations on Groovy
annotations are not so nice.

The stubs also allow annotation processors to run on them. Of course
this does not make sense for Lombok, but if a processor is collecting
meta data for example then this is a different matter altogether.


Now I will list a few variants I will not specifically mention the
eclipse plugin, I would leave that to Eric to add if he wants to.


V1:
In this version I use javaparser to ClassNodes the Groovy compiler does
understand and then let the Groovy compiler proceed normally. The result
is a compilation of only the Groovy classes. All information relevant in
the java classes (modifiers, referenced classes, members, field
constants, imports) have to be resolved in a limited way. Limited means
that we assume any class we cannot resolve comes from Groovy and is to
be resolved by the Groovy compiler later on. In a second step we would
call Javac to compile against the files Groovyc produced. This approach
is less memory consuming than V0, since we can completely end the groovy
compilation. In fact this architecture would be somewhat extensible to
support other languages as well. Also the Java compilation would always
see the fully applied Groovy annotations. A potential problem is
annotations processors working on Java, since there is no Javac
compatible source tree. I am not sure this problem can be solved
satisfactory. An example would be compiling against a Java class using
Lombok and then not seeing methods generated by Lombok.

V2:
Collect class data from javac using annotation processing and feed that
to groovyc. This would then be a 3 stage process. First we use javac to
get the class information, but javac cannot complete compilation, since
not all classes are resolved. Then we use the extracted information to
compile Groovy. And finally we compile normally with Java.

I tried this years ago and did not manage to get this working properly.
I would have to investigate what exactly was the problem since I tried
this maybe 8 years ago. But I think I actually was able to extract the
information and my problem was more making the classes then known to
Groovy. If not done in-memory this can probably be done easily.

V3:
in-process joint compilation by sharing ASTs with Javac. This we tried
more or less with a the Google Summer of Code project. The idea is that
we let both compilers progress in parallel and concurrently resolve
missing types against each other.

This has numerous problems, mostly the lack of control over Javac, but
even Groovyc does not work as required for this. Because for this to
work you would need to progress a unit at a time as much as possible.
Otherwise Java cannot see the changes by transforms on Groovy. And then
you are basically in the same position as V0 with additional drawbacks.

V4:
Mix of V3 and V2. Use javac to extract information instead of annotation.

Frankly I am not sure we get all that many advantages of V3 and V4. If
the goal is to have completely transformed Groovy classes available to
javac, then I see possible advantages. Memorywise I don't see them. But
annotation processing would then work on both, just Groovy seeing a
method added by lombok probably not.

V5/V6:
Use ECJ/JDT instead of javac.

V7:
maybe there is a variant with language server infrastructure? I did not
really look into that the last years. Last time I spoke with the guys I
suggested adding some kind of type resolving bridge where multiple
language server can exchange type data, but they did not see a need for
this back then. Today's situation might be different.


Well... what do others think? Are we happy with our joint compilation.
Did I list something that sounds like a better alternative?

bye Jochen

Reply via email to