Saturday, September 25, 2021

JDK 18: Code Snippets in Java API Documentation

OpenJDK 18 Early-Access Build 16 (2021/9/23) is now available and includes the implementation for JEP 413 ("Code Snippets in Java API Documentation"), which is targeted for JDK 18. The objective of JEP 413 is to "introduce an @snippet tag for JavaDoc's Standard Doclet, to simplify the inclusion of example source code in API documentation" and the JEP itself covers the syntax of and features supported by the Javadoc {@snippet} tag.

JEP 413 introduces the new {@snippet } Javadoc tag:

We introduce a new inline tag, {@snippet ...}, to declare code fragments to appear in the generated documentation. It can be used to declare both inline snippets, where the code fragment is included within the tag itself, and external snippets, where the code fragment is read from a separate source file.

The JEP has far more details on what is supported by {@snippet } and what its syntax is. This post provides a small taste of what {@snippet } brings to Javadoc-based documentation and the code listings included in this post are available on GitHub.

This first contrived code listing makes use of {@snippet }:

package dustin.examples.jdk18.javadoc;

/**
 * Demonstrates {@code @snippet} Javadoc tag targeted for JDK
 * as part of JEP 413 (AKA Bug JDK-8201533):
 * <ul>
 *     <li>https://openjdk.java.net/jeps/413</li>
 *     <li>https://bugs.openjdk.java.net/browse/JDK-8201533</li>
 * </ul>
 *
 * An instance of this class is obtained via my {@link #newInstance()} method
 * rather than via a constructor.
 *
 * {@snippet :
 *    final SnippetExample instance = SnippetExample.newInstance(); // @highlight substring="newInstance"
 *    instance.processIt();
 * }
 */
public class SnippetExample
{
    /**
     * No-arguments constructor not intended for public use.
     * Use {@link #newInstance()} instead to get an instance of me:
     * {@snippet :
     *    final SnippetExample instance = SnippetExample.newInstance();   // @highlight substring="newInstance"
     * }
     */
    private SnippetExample()
    {
    }

    /**
     * Preferred approach for obtaining an instance of me.
     *
     * @return Instance of me.
     */
    public SnippetExample newInstance()
    {
        return new SnippetExample();
    }

    /**
     * Performs valuable processing.
     */
    public void processIt()
    {
    }
}

When the above code is run through the javadoc tool with the -private option, code snippets are generated in the HTML for the class and no-arguments constructor. Note also that the "highlighted" sections have bold emphasis in the generated HTML.

Generated class-level documentation with snippet:

Generated method-level documentation with snippet:

One area where I think the {@snippet } may be particularly useful is in package documentation. A code example of use for a package description is shown in the next code listing for package-info.java.

/**
 * Examples and demonstrations of Javadoc-related capabilities.
 *
 * The main entrypoint for the snippets example is the {@link SnippetExample} class:
 * {@snippet :
 *    final SnippetExample instance = SnippetExample.newInstance();  // @highlight substring="SnippetExample" @link substring="SnippetExample.newInstance()" target="SnippetExample#newInstance()"
 * }
 */
package dustin.examples.jdk18.javadoc;

The generated HTML output for this package-level documentation is shown in the next screenshot.

One of the challenges in including code snippets in Javadoc-based documentation has been that the tags used to present the code (such as <pre>, <code>, and {@code}) can make the Javadoc comment less readable when viewed in source directly instead of via the generated HTML. The {@snippet } Javadoc tag can make the code presentation better for the generated HTML while being less distracting in the source code itself. JEP 413 addresses the shortcomings of current approaches for including code snippets in Javadoc and summarizes how {@snippet } addresses those shortcomings:

A better way to address all these concerns is to provide a new tag with metadata that allows the author to implicitly or explicitly specify the kind of the content so that it can be validated and presented in an appropriate manner. It would also be useful to allow fragments to be placed in separate files that can be directly manipulated by the author's preferred editor.

JEP 413 contains far more details on application of {@snippet }, including the ability to reference code contained in external files.

No comments: