Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Friday, May 20, 2011

Extending JavaDoc

I don't think I've seen a piece of code more poorly designed for extension, and more in need of it, than JavaDoc. I'm in the process of removing Tapestry's Maven-based component report (as part of an overall move from Maven to Gradle). My goal is to merge what currently comes from the component report directly into the JavaDocs.

My first approach was to extend the built-in HtmlDoclet , the one that generates the every-day HTML report. Good luck with that ... it's like a field guide to anti-patterns for preventing extensibility. Here's an example:

public class HtmlDoclet extends AbstractDoclet {
    
    /**
     * The global configuration information for this run.
     */
    public ConfigurationImpl configuration = 
        (ConfigurationImpl) configuration();
    

    /**
     * Create the configuration instance.
     * Override this method to use a different
     * configuration.
     */
    public Configuration configuration() {
        return ConfigurationImpl.getInstance();
    }

    ...
}

public class ConfigurationImpl extends Configuration {

    /**
     * Constructor. Initialises resource for the
     * {@link com.sun.tools.doclets.MessageRetriever}.
     */
    private ConfigurationImpl() {
        standardmessage = new MessageRetriever(this,
            "com.sun.tools.doclets.formats.html.resources.standard");
    }
    
    public static ConfigurationImpl getInstance() {
        return instance;
    }

   ...
}

So, HtmlDoclet commits the cardinal sin of down-casting from the interface to the implementation class, and ConfigurationImpl is effectively final, as its only constructor is private. But you are encouraged to override the configuration anyway (recommended only if your goal is to throw a ClassCastException).

JavaDoc is old. The HtmlDoclet is just ... tired. Someone failed to tell these folks about XML and XSL, for example ... or about HTML and CSS, for that matter. JavaDoc is screaming out to be a tool that generates an XML representation of Java source content that can then be transformed into an HTML document tree via XSLT. I've seen an abandoned project along those lines. Perhaps in my spare time ... it would be a fun little side project to create that, and create a really world-class JavaDoc.

In any case ... I've been forced to impose the use of a @tapestrydoc tag on component classes that wish to be documented. Not the end of the world, but not backwards compatible either (though the Tapestry 5.2 Maven component report will continue to work with Tapestry 5.3, so that's not a deal-breaker).

5 comments:

Howard said...

Oops. Forgot to mention ... the reason you want to override the Configuration is to replace the AbstractBuilder used to generate class documentation, which is stored in a protected (but at least not final) variable. So, I may work on this again, to remove the need for the @tapestrydoc tag, using some ugly hacks ... but I'm still not sure it can be done, and it certainly can't be done cleanly.

Jesse Kuhnert said...

Antlr has a java grammar in their grammar repo I'm pretty sure. Don't know if it captures javadoc stuff in current form but could be a good starting point.

swankjesse said...

Doclava has potential:
http://code.google.com/p/doclava/

Leonel said...

JavaFX is a marketing failure, but its API is shown in a great format. It uses Javascript effects to provide easy navigation and is pleasant to the eye.

http://download.oracle.com/docs/cd/E17802_01/javafx/javafx/1.3/docs/api/

Frank Grimes said...

It looks like JavaDoc is getting a little attention: http://blogs.oracle.com/jjg/entry/what_s_up_javadoc