One feature that I like Java2Script is its full integration with Eclipse JDT’s incremental building.
Java2Script reuses Eclipse JDT to compile *.java into *.js. As Eclipse JDT supports incremental building, so Java2Script also supports this feature. The magic is that when a *.java file is passed into JDT’s ImageCompiler, it is also passed through Java2ScriptImageCompiler.
To understand JDT’s incremental building, when a *.java is modified and compiled, this file will be compiled, and as always, this modification may affect other *.java files, that is to say, some other classes may need recompiling. JDT uses some algorithms to figure out those delta *.java and compile it, and compiling continues until there is no affected files that need to be compiled.
As compiling has its entry, Java2Script just install an extra compiler at the entry so that a *.java file is compiled into *.class, it also be compiled into *.js. This is? the whole magic of Java2Script builder.
But to inject a Java2Script compiler into existed JDT plugin requires some works. First JDT’s compiler is not designed to be injected. Modified the JDT sources and recompiling the plugin do works. But it’s not quite suitable for public, as it need to overwrite original JDT plugin jars. There is another factor that make a little difficult in implementing Java2Script compiler based JDT. A lot of classes in JDT are package accessible or their methods are not public. It need a lot of works to do so that those restricts can be avoided. And besides, Java2Script compiler codes must be maintainable, or when a new Eclipse version is released, all those hard works need to re-do.
In current Java2Script compiler, it reuses codes in package org.eclipse.jdt.internal.core.builder. All it need is to move all the sources into a new package named net.sf.j2s.core.builder. And some new proxy classes or new inherited classes are added so it is possible to access inner data structure. And Java2ScriptImageCompiler is injected into those JDT normal compiling process. And there are some tricks here. To convert some instances between two different classes without trigger ClassClastError, one instance (e.g. net.sf.j2s.core.builder.State instance) is serialized into DataInputStream first, and then it will be de-serialized into another instance (org.eclipse.jdt.internal.core.builder.State.). In all, in implementing Java2Script compiler, it use all kinds of tricks to expose JDT’s inner data structures to outside compilers.
For more details, please compare the Java2Script sources (net.sf.j2s.core.builder, net.sf.j2s.core.compiler) with sources in JDT (org.eclipse.jdt.internal.core.builder, org.eclipse.jdt.core.compiler)