November 14, 2018

Gradle Goodness: Generate Javadoc In HTML5

Since Java 9 we can specify that the Javadoc output must be generated in HTML 5 instead of the default HTML 4. We need to pass the option -html5 to the javadoc tool. To do this in Gradle we must add the option to the javadoc task configuration. We use the addBooleanOption method of the options property that is part of the javadoc task. We set the argument to html5 and the value to true.

In the following example we reconfigure the javadoc task to make sure the generated Javadoc output is in HTML 5:

// File: build.gradle
apply plugin: 'java'

javadoc {
    options.addBooleanOption('html5', true)
}

The boolean option we added to the options property is not part of the Gradle check to see if a task is up to date. So if we would change the key html5 to html4, because we want to get documentation in HTML 4, the task would be seen as up to date, because Gradle doesn't keep track of the change. We can change this by adding a property to the task inputs property, that contains the output format. Let's also add a new extension to Javadoc tasks to define our own DSL to set the output format.

We need to create an extension class and plugin to apply the extension to the Javadoc tasks. In the plugin we can also add support to help Gradle check to see if the task is up to date, based on the output format. In the following example we define an extension and plugin in our build file, but we could also place the classes in the buildSrc directory of our project.

// File: build.gradle
apply plugin: 'java'
apply plugin: JavadocPlugin

javadoc {
    // New DSL to configure the task
    // added by the JavadocPlugin.
    output {
        html5 = true
    }
}

/**
 * Plugin to add the {@link JavadocOutputOptions} extension
 * to the Javadoc tasks. 
 * <p>
 * Also make sure Gradle can check if the task needs
 * to rerun when the output format changes.
 */
class JavadocPlugin implements Plugin<Project&g;t {

    void apply(Project project) {
        project.tasks.withType(Javadoc) { Javadoc task ->
            // Create new extension for Javadoc task with the name "output".
            // Users can set output format to HTML 5 as:
            // javadoc {
            //     output {
            //         html5 = true 
            //     }
            // }
            // or as HTML4:
            // javadoc {
            //     output {
            //         html4 = true 
            //     }
            // }
            JavadocOutputOptions outputOptions = 
                    task.extensions.create("output", JavadocOutputOptions)

            // After project evaluation we know what the
            // user has defined as output format using the 
            // "output" configuration block.
            project.afterEvaluate {
                // We need to make sure the up-to-date check
                // is triggered when the output option changes.
                // If the value is not changed the task is up-to-date.
                task.inputs.property("output.html5", outputOptions.html5)

                // We add the boolean option html4 and html5 
                // based on the user's value set via the
                // JavadocOutputOptions.
                task.options.addBooleanOption("html4", outputOptions.html4)
                task.options.addBooleanOption("html5", outputOptions.html5)
            }

        }
    }

}

/**
 * Extension for Javadoc tasks to define
 * if the output format must be HTML 4 or HTML 5.
 */
class JavadocOutputOptions {
    Boolean html4 = true
    Boolean html5 = !html4

    void setHtml4(boolean useHtml4) {
        html4 = useHtml4
        html5 = !html4
    }

    void setHtml5(boolean useHtml5) {
        html5 = useHtml5
        html4 = !html5
    }
}

Written with Gradle 4.10.2.