Porting
It is an important step to first prepare the Java source. And it should be done always in the exact same and documented way. This makes it possible to merge later version of the Java sources. For the already prepared sources see below.
Prepare the source
In Eclipse
- Take the whole source tree and create an eclipse Java project.
- use "organize imports" to expand star (*) imports.
- use package renaming
After that use GVim
- load all files into gvim
- remove tabs with ":bufdo retab" (having tabstop=4)
- convert all files to unix format ":bufdo set ff=unix"
- do global search-replaces
- ":set noignorecase"
- ":bufdo %s:\<boolean\>:bool:g"
- ":bufdo %s:\>==: ==:g" insert space if needed
- ":bufdo %s:==\<:== :g" insert space if needed
- ":bufdo %s:==:is:g"
- ":bufdo %s:\>!=: !=:g" insert space if needed
- ":bufdo %s:!=\<:!= :g" insert space if needed
- ":bufdo %s:!=:!is:g"
- create a keyboard macro that does correct the package statement and insert the utils import
- "qq" start recording keyboard macro 'q'
- "gg/package<ENTER>cemodule<ESC>" search for package and replace with module
- "o<C-r>%<BS><BS>;<ESC>bv0d" in a new line insert the current file name, remove the '.d', append ';', remove the path
- "kJxxi.<ESC>" Join lines, delete spaces, connect with dot
- "o<ENTER>import dwt.dwthelper.utils;<ENTER><ESC>" insert the import
- "q" end the key macro recording
- undo all by pressing several times 'u'
- ":bufdo! normal @q" apply the keyboard macro to all loaded buffers
- save all ":wall"
Rename all .java files to .d
Save the prepared sources for later merges
Use the prepared source archives
This archives contain the sources already renamed and prepared.
3.4M7:
3.4:
The addons package now contains the sources for jface, jface.text (Editor support), ui.* (forms and workbench), equinox (OSGi), draw2d (from GEF). More than 3000 files.
Quick Look-over
- Fix constructors
Operators
Change hashCode to toHash and equals to opEquals
Search for \<equals\> and replace by opEquals
final
final member vars
Change them to const if possible. In Java the initializer can be runtime method call, in D that is only possible with a static constructor. Because of the "circular dependencies" problem the use of static constructors is not always possible. Try to eliminate them.
- use version statements
- use ctfe
- use the normal constructor to initialize static members. Have them not const.
final local vars or parameters
In general the final keyword can be removed here. But keep them until you have checked, the variable is not used in a anonymous class. An exampls:
void func( final Display display ){ addListener( new Listener(){ void handle( Event e ){ display.doSomething(); } }); }
In Java the anonymous class can access local vars if they are final. In D1.x this will result in stack corruption if the handler is executed after func-execution was completed. The local var needs to become a member var of the anonymous class:
void func( Display display ){ addListener( new class( display ) Listener { Display d; this( Display d ){ this.d = d; } void handle( Event e ){ d.doSomething(); } }); }
Now this is save.
The whole thing is very sensible to errors. The compile does not help you. Because of that use the find function to find all references to a final variable. After rewrite again use the find function and make sure you did not miss a reference.
Evaluation order
Evaluation order is not defined in D, but in Java it is. So there are in seldom cases situation, where runtime errors occur because of that.
Java:
array1[index] = array2[index++];
ported to D:
array1[index] = array2[index]; index++;
Java:
result = ( popNextByte() << 8 ) | popNextByte();
ported to D:
result = popNextByte() << 8; result |= popNextByte();
