Using Eclipse’s source code formatter from the command line

One of the many wonderful capabilities built into the side of Eclipse is a powerful code formatter. Adjusting source code to match one’s particular preferences is nothing terribly new; what makes Eclipse’s so excellent is the degree of configurability and the preview of the effect each setting will have.

An Eclipse project has several metadata files:

.project
.classpath
.settings/org.eclipse.cdt.core.prefs
.settings/org.eclipse.jdt.core.prefs
.settings/org.eclipse.jdt.ui.prefs

Which seems a bit of a mess, but whatever. The .settings/ stuff gets written down when you decide to tell a Project to have settings custom that override the user’s defaults. It goes without saying that for a collaboratively developed project like the Java bindings we have the Eclipse project metadata for compiler warnings tuned, the code formatter settings, how to invoke the build system etc all stored in Bazaar along side the real sources.

Anyway, this’s all fine and nice for people working on my software in Eclipse, but what about people wishing to use a different editor?

For a few versions now, Eclipse has exposed the the ability to run its code formatter from the command line; the work was done by Ben Konrath, someone I met a few years ago at a java-gnome hackfest. Since I use Eclipse I hadn’t needed to bother to figure out how to use whatever it was that he’d done. Since becoming maintainer of java-gnome, though, I’ve noticed a bit of unnecessary formatting churn in the contributions we receive. We do have a style guide, but it is secondary to the fact that Eclipse just normalizes the code every time I save something (nice). But for people not using Eclipse I thought I might have a look.

A bit of searching around turned up this blog post by one Peter Friese. It included two important points that are non-trivial. Firstly, that configuration the code formatter from command line will use can be controlled by the pointing it at the .settings/org.eclipse.jdt.ui.prefs file which in turn can be created by the “Enable project specific settings” described above (we’d already done that, so no problem, but how on earth would anyone have guessed this?). Secondly, the command line that one has to incant to make it go is pretty voodoo, so I’m pretty thankful that he described what he’d done.

In our environment, this works out to:

$ /opt/local/eclipse/eclipse -nosplash
    -application org.eclipse.jdt.core.JavaCodeFormatter
    -verbose
    -config .settings/org.eclipse.jdt.core.prefs
    src/ tests/ doc/examples/

Gah!

For a brief moment I wondered if it would be easier just to run the Java class in question. So I interrupted the process and had a look in the process table.

/usr/lib/jvm/sun-jdk-1.6/bin/java
    -Dosgi.requiredJavaVersion=1.5
    -client
    -Xms40m
    -Xmx256m
    -jar /opt/local/eclipse/plugins org.eclipse.equinox.launcher_1.0.1.R33x_v20070828.jar
    -os linux
    -ws gtk
    -arch x86
    -launcher /opt/local/eclipse/eclipse
    -name Eclipse
    --launcher.library /opt/local/eclipse/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_1.0.2.R331_v20071019/eclipse_1021.so
    -startup /opt/local/eclipse/plugins/org.eclipse.equinox.launcher_1.0.1.R33x_v20070828.jar
    -exitdata 84001b
    -application org.eclipse.jdt.core.JavaCodeFormatter
    -verbose
    -config .settings/org.eclipse.jdt.core.prefs
    src/ tests/ doc/examples/
    -vm /usr/bin/java
    -vmargs
    -Dosgi.requiredJavaVersion=1.5
    -client
    -Xms40m
    -Xmx256m
    -jar /opt/local/eclipse/plugins/org.eclipse.equinox.launcher_1.0.1.R33x_v20070828.jar

Good Lord. What the hell is all that? I mean, I know Java environments tend to get a bit unwieldy because there is still no link-to-binary facility, and I know Eclipse is an OSGi framework and what not, but that is pathetic. I guess running the command as described at the top isn’t such a bad idea after all.

I’ve got an even better idea: how about a convenience target in our Makefile front end. Yup. So I’ve added a format target:

$ make format

(or

$ ECLIPSE=/opt/local/eclipse/eclipse make format

in my case). Running that before committing will do the trick quite nicely.

I agree with the bug mentioned by one Nicholas Irving in his post on the topic: it is somewhat asinine that this bit of Eclipse bumps the modification time of every file it formats; it would be nice if it only changed files in which it actually found something it needed to alter. Fortunately our internal build system is actually md5 hash (not Make) based, so it doesn’t hurt us.

AfC