Stuart Kent
(Android Developer)

Adventures With Javadocs (Part 3)

This is the follow-up to Adventures with Javadocs parts 1 and 2. If you haven’t already, please go read those - this post continues to build on the sample project constructed there, and explores the extra configuration needed to properly handle classes supplied by third party dependencies.

Introducing Classes From Third Party Dependencies

Let’s add Google’s Gson as a third party dependency of our library:

dependencies {
    compile 'com.google.code.gson:gson:2.6.2'
}

We also introduce a fourth test class to our project, again in a separate package, that depends only on Gson classes:

package com.github.stkent.javadoctests.package4;

import com.google.gson.Gson;

/**
 * This class depends on a third party type only!
 */
public class TestClassFour {

    private final Gson gson;

    public TestClassFour(final Gson gson) { this.gson = gson; }

    public Gson getGson() { return gson; }

}

Our docs task is still configured as follows:

task docs(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath = files(((Object) android.bootClasspath.join(File.pathSeparator)))
}

and running it produces all output from before plus the expected additions for our new package/class:

However, similarly to when we first included Android classes in our library project, the command-line output of the docs task includes new warnings associated with our new class:

/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package4/TestClassFour.java:3: error: package com.google.gson does not exist
import com.google.gson.Gson;
                      ^
/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package4/TestClassFour.java:10: error: cannot find symbol
    private final Gson gson;
                  ^
  symbol:   class Gson
  location: class TestClassFour
/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package4/TestClassFour.java:12: error: cannot find symbol
    public TestClassFour(final Gson gson) {
                               ^
  symbol:   class Gson
  location: class TestClassFour
/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package4/TestClassFour.java:16: error: cannot find symbol
    public Gson getGson() {
           ^
  symbol:   class Gson
  location: class TestClassFour
4 warnings

BUILD SUCCESSFUL

This should not be at all surprising. Based on our investigations in the last post, we know that com.google.gson.Gson is a newly-added referenced class whose definition is currently not included in the classpath we are supplying to the javadoc tool. Let’s fix that.

The code for this portion of the post is available here.

Adding Third Party Classes To The Classpath

Since third party dependencies are, by definition, not bundled with our Android SDK install, we will need to do a little bit more work to locate their compiled class files. The simplest way to achieve this is to leverage the libraryVariants method exposed by the Android library project plugin. This allows us to redefine our docs task as follows:

android.libraryVariants.all { variant ->
    if (variant.name == 'release') {
        task docs(type: Javadoc) {
            source = variant.javaCompiler.source
            classpath = files(((Object) android.bootClasspath.join(File.pathSeparator)))
            classpath += variant.javaCompiler.classpath
        }
    }
}

There are a few new things going on here, so let’s break this code down a bit.

To confirm I’m not lying about that last point, here’s the content of the javadoc.options file generated by executing this redefined docs task:

-classpath '/Users/stkent/Library/Android/sdk/platforms/android-23/android.jar:/Users/stkent/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.6.2/f1bc476cc167b18e66c297df599b2377131a8947/gson-2.6.2.jar'
-d '/Users/stkent/dev/personal/libraries/javadoc-tests/library/build/docs/javadoc'
-doctitle 'library API'
-quiet 
-windowtitle 'library API'
'/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package1/TestClassOne.java'
'/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package2/TestClassTwo.java'
'/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package3/TestClassThree.java'
'/Users/stkent/dev/personal/libraries/javadoc-tests/library/src/main/java/com/github/stkent/javadoctests/package4/TestClassFour.java'

That long first line confirms that the javadoc tool will search for referenced classes within the Android platform and Gson JARs!

Results

Let’s check our actual Javadoc output and verify that it includes the full package names for classes in third-party dependencies:

Perfect :-)

The code for this portion of the post is available here.

Generalizing

I mentioned in a couple places that the docs task we defined would not necessarily be suitable for a library that utilizes product flavors. For completeness, here’s how we could declare a separate Javadoc-generating task for each library variant:

android.libraryVariants.all { variant ->
    task("${variant.name}Docs", type: Javadoc) {
        source = variant.javaCompiler.source
        classpath = files(((Object) android.bootClasspath.join(File.pathSeparator)))
        classpath += variant.javaCompiler.classpath
    }
}