Up-to-date checking broken for JacocoReport task?

We had a JacocoReport task which is gathering coverage reports from multiple subprojects into one place. Its configuration looks like this:

def codeCoverageReport = tasks.register('codeCoverageReport', JacocoReport) {
    subprojects.each {
        sourceSets it.sourceSets.main

    reports {
        xml.enabled true
        html.enabled true

    // Gather execution data from all subprojects (no need to call jacocoMerge)

If we do this:

  • Run ./gradlew codeCoverageReport
  • Delete the report
  • Run ./gradlew codeCoverageReport again

We find that the task doesn’t notice that it’s out of date.

Investigating the task classes:

  • On JacocoReport, getReports() is annotated @Nested, returning JacocoReportsContainer
  • On JacocoReportsContainer, getHtml() is annotated @Internal, returning DirectoryReport
  • On DirectoryReport, getOutputLocation() is annotated @OutputDirectory

So it seems that getHtml() was mis-annotated as @Internal when it should have been @Nested - a straight-forward bug?


The getHtml() and getXml() methods are marked as @Internal since they are their to be used from the DSL as convenience. What is annotated with @Nested is the ReportContainer.getEnabledReports() method, which contains all the enabled reports.

It is still very strange that the task in the root project doesn’t notice it has been deleted. I suppose you delete the report in the root project manually and not by using something like :clean? Can you share a reproducible example?