Javadoc task does not support some Javadoc features

456 views
Skip to first unread message

Ross Wang

unread,
Feb 19, 2016, 9:20:44 PM2/19/16
to gradle-dev
It seems that because the Gradle Javadoc task operates on individual files rather than whole packages, a few Javadoc features don't seem to work:
  • doc-files directories are recursively processed by SourceTask, so Javadoc tries to process files within them for Javadoc (erroring with "illegal package name") rather than copying them. Excluding these files prevents copy, making it difficult to include images in Javadoc unless externally linked or copied via another Gradle task.
  • overview.html also errors with "illegal package name", seemingly for the same reason.
  • @see links to package docs (package-info.java) do not work in the generated Javadoc.
I have hacked out a subclass of the Javadoc task that works around these issues by:

...

private Set<File> sourceDirs

@Override
public void setSource(Object sourceDirs) {
this.sourceDirs = sourceDirs
super.setSource(sourceDirs)
}

@Override
protected void generate() {
    ...
    Set<String> roots = new HashSet<>();
for (File sourceDir : sourceDirs) {
roots += sourceDir.absolutePath
}
/*Set<String> packages = new HashSet<>();
for (File sourceFile : getSource()) {
TODO
}*/
options.setSourceNames(Arrays.asList('<library package name>'));
options.addStringOption('subpackages', '<library package name>')
options.addStringsOption('sourcepath').value = new ArrayList<>(roots)

executeExternalJavadoc();
}

...

However, a more general solution (ex. one that doesn't hard-code the library package name) may require more effort. In general, it seems like processing entire packages instead of file sets is the way to go, but that presents complications with include/exclude filters. Perhaps modeling it as a SourceTask isn't quite correct, though it does make for easy integration for those who don't need the features that break like this.

Possibly related issue:
https://discuss.gradle.org/t/javadoc-task-doesnt-generate-package-links/10621

Loosely related issue:
https://discuss.gradle.org/t/javadoc-exclusion-question/11875

Also please let me know if there's a simpler workaround that I've missed.

Ross Wang

unread,
Mar 10, 2016, 8:02:12 PM3/10/16
to gradle-dev
Updated snippets:

private Set<File> sourceDirs

@Override
public void setSource(Object sourceDirs) {
this.sourceDirs = project.files(sourceDirs).files
super.setSource(sourceDirs)
}

@Override
protected void generate() {
    ...
    Set<JPath> roots = sourceDirs.collect { it.toPath() } as Set
Collection<JPath> sourcePaths = source.collect{ it.toPath() }

Set<String> packages = new HashSet<>()

    sourcePaths.each { sourcePath ->
JPath curRoot = roots.find { sourcePath.startsWith(it) }
JPath rel = curRoot.relativize(sourcePath)

if (rel.parent != null) {
packages += rel.parent.toString().replaceAll("/", ".")
}
}
options.setSourceNames(packages as List);
options.addStringsOption('sourcepath').value =
roots.collect { it.toAbsolutePath() as String }

executeExternalJavadoc();
}

...

Ross Wang

unread,
Mar 10, 2016, 9:25:53 PM3/10/16
to gradle-dev
Oh, where import java.nio.file.Path as JPath

In addition to rel.parent != null, it looks like we'd also need to && sourcePath.parent.fileName as String != "doc-files". It would be nice to further be able to tweak the functionality here without having to copy code in the future, perhaps putting this whole each closure/accumulation into its own method. For example, we're using the Pegdown doclet, which seems to ignore doc-files, so we have to copy those files and this is a convenient place to do it.
Reply all
Reply to author
Forward
0 new messages