Adopt AntBuilder groovydoc with javaVersion support#15420
Adopt AntBuilder groovydoc with javaVersion support#15420jamesfredley wants to merge 2 commits into7.0.xfrom
Conversation
Replace Gradle's built-in Groovydoc task execution with AntBuilder to support the javaVersion parameter introduced in Groovy 4.0.27 (GROOVY-11668). This is needed because Gradle's Groovydoc task does not expose javaVersion (gradle/gradle#33659 is not merged), causing Java 17+ source parsing failures. Changes across all groovydoc configurations: - gradle/docs-dependencies.gradle: central config for ~90 modules and both aggregate tasks (aggregateGroovydoc, aggregateDataMappingGroovydoc) - gradle/docs-config.gradle: per-module source directory setup - grails-doc/build.gradle: aggregate task source directories - grails-data-docs/stage/build.gradle: data mapping aggregate source dirs - grails-gradle/gradle/docs-config.gradle: independent AntBuilder setup - grails-data-hibernate5/docs/build.gradle: added groovy-ant dependency and AntBuilder execution - grails-data-mongodb/docs/build.gradle: added groovy-ant dependency and AntBuilder execution - grails-forge/gradle/doc-config.gradle: AntBuilder without javaVersion (forge uses Groovy 3.0.25 which predates the feature) Closes #15385 Assisted-by: Claude Code <Claude@Claude.ai>
…ion plugin Move duplicated AntBuilder groovydoc execution, Matomo footer, documentation configuration registration, and task defaults into a shared convention plugin in build-logic. This eliminates ~490 lines of duplicated configuration across 8 build scripts while maintaining identical behavior. The plugin provides: - Documentation configuration registration with standard attributes - Common Groovydoc task defaults (author, timestamps, scripts) - AntBuilder-based execution with javaVersion support (Groovy 4.0.27+) - Matomo analytics footer - Source directory resolution from ext.groovydocSourceDirs or source sets - External documentation link support via ext.groovydocLinks - GrailsGroovydocExtension for per-project javaVersion control Build scripts retain project-specific configuration: dependencies, titles, source directories for aggregate tasks, and dynamic link resolution. Assisted-by: Claude Code <Claude@Claude.ai>
There was a problem hiding this comment.
Pull request overview
This PR centralizes Groovydoc configuration and execution by introducing a build-logic convention plugin that runs Groovydoc via AntBuilder (to support Groovy’s javaVersion option), and updates multiple modules to use the new plugin while removing duplicated Groovydoc setup.
Changes:
- Added
org.apache.grails.buildsrc.groovydocconvention plugin (GrailsGroovydocPlugin+GrailsGroovydocExtension) to run Groovydoc throughorg.codehaus.groovy.ant.Groovydoc, with optionaljavaVersionsupport. - Updated shared/per-module docs Gradle scripts to apply the plugin and centralize common defaults (e.g., Matomo footer, shared dependency setup).
- Updated aggregate Groovydoc tasks to pass source directories via
ext.groovydocSourceDirsfor the new Ant-driven execution.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
build-logic/plugins/build.gradle |
Registers the new org.apache.grails.buildsrc.groovydoc convention plugin. |
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy |
Implements AntBuilder-based Groovydoc execution and shared defaults (footer, configuration). |
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocExtension.groovy |
Adds extension properties to control javaVersion and the javaVersion-passing toggle. |
gradle/docs-dependencies.gradle |
Applies the convention plugin and reworks Groovydoc link population via ext.groovydocLinks. |
grails-gradle/gradle/docs-config.gradle |
Applies the convention plugin and removes duplicated Groovydoc task configuration. |
grails-forge/gradle/doc-config.gradle |
Applies the convention plugin; disables javaVersion passing for Groovy 3.x and adds Ant Groovydoc deps. |
grails-doc/build.gradle |
Simplifies aggregate Groovydoc setup and provides ext.groovydocSourceDirs for Ant execution. |
grails-data-docs/stage/build.gradle |
Updates aggregate Groovydoc source handling and provides ext.groovydocSourceDirs. |
grails-data-hibernate5/docs/build.gradle |
Applies the convention plugin, adds required Ant Groovydoc deps, and supplies ext.groovydocSourceDirs. |
grails-data-mongodb/docs/build.gradle |
Applies the convention plugin, adds required Ant Groovydoc deps, and supplies ext.groovydocSourceDirs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Map<String, Object> antArgs = [ | ||
| destdir: destDir.absolutePath, | ||
| sourcepath: sourcepath, | ||
| packagenames: '**.*', | ||
| windowtitle: gdoc.windowTitle ?: '', |
There was a problem hiding this comment.
The Ant groovydoc call doesn't pass gdoc.classpath/gdoc.groovyClasspath (the documentation configuration is only used for taskdef). As a result, any Groovydoc classpath configured in build scripts is ignored during generation and can break type resolution. Pass the configured task classpath into the Ant task (e.g., classpath attribute or nested classpath).
| List<File> sourceDirs = resolveSourceDirectories(gdoc, project) | ||
| if (sourceDirs.isEmpty()) { | ||
| project.logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found") | ||
| return | ||
| } |
There was a problem hiding this comment.
Groovydoc source filtering from the Gradle task (e.g., gdoc.source, gdoc.includes/gdoc.excludes) isn’t honored here because the Ant task is driven only by sourcepath + packagenames. This makes existing exclusions in build scripts ineffective and can change which classes end up in the published API docs. Consider deriving the Ant inputs from gdoc.source (or translating excludes/includes into Ant filesets/excludepackagenames) so task configuration still applies.
| def gebVersion = resolveProjectVersion('geb-spock') | ||
| if(gebVersion) { | ||
| gdoc.link("https://groovy.apache.org/geb/manual/${gebVersion}/api/", 'geb.') | ||
| if (gebVersion) { | ||
| links << [packages: 'geb.', href: "https://groovy.apache.org/geb/manual/${gebVersion}/api/"] | ||
| } |
There was a problem hiding this comment.
resolveProjectVersion() (defined above) never returns the resolved version when it is present, so gebVersion/testContainersVersion/etc will always be null here and no external groovydoc links will be added. Ensure resolveProjectVersion() returns the resolved version value.
| import org.gradle.api.tasks.javadoc.Groovydoc | ||
|
|
||
| @CompileStatic | ||
| class GrailsGroovydocPlugin implements Plugin<Project> { |
There was a problem hiding this comment.
What are your thoughts about keeping this plugin generic? i.e. do not put specific grails-core configuration in it and instead configure it like we configured groovydoc before? That way if gradle merges the upstream change, we don't have to separate out all of the configuration.
Summary
Replaces Gradle built-in Groovydoc task execution with direct AntBuilder invocation of the Groovy
org.codehaus.groovy.ant.GroovydocAnt task, enabling thejavaVersionparameter introduced in Groovy 4.0.27 (GROOVY-11668). The duplicated AntBuilder configuration is then centralized into aGrailsGroovydocPluginconvention plugin inbuild-logic/.Problem
Gradle
Groovydoctask does not expose thejavaVersionproperty (gradle/gradle#33659 is not merged). Without it, groovydoc defaults toJAVA_11language level when parsing Java source files, causing failures when processing Java 17+ features like sealed classes, records, and pattern matching.Solution
1. AntBuilder groovydoc with javaVersion
For each Groovydoc task:
@TaskActionexecutiondoLastthat uses AntBuilder to callorg.codehaus.groovy.ant.GroovydocdirectlyjavaVersion: JAVA_17(derived fromgradle.properties) to enable correct Java 17+ source parsing2. Centralized convention plugin
Created
GrailsGroovydocPlugin(org.apache.grails.buildsrc.groovydoc) inbuild-logic/that:javaVersionsupportmainsource setext.groovydocLinksGroovydocAccessenum viaClass.forName(not on build-logic compile classpath)Property<T>/ plain-value API viaresolveGroovydocProperty()GrailsGroovydocExtensionprovides:javaVersion(default:JAVA_17) - target Java version for Groovydoc outputjavaVersionEnabled(default:true) - allows disabling for Groovy 3.x (Forge uses 3.0.25 which lacksjavaVersionsupport)Files changed
build-logic/plugins/build.gradlegrailsGroovydocplugin IDbuild-logic/.../GrailsGroovydocPlugin.groovybuild-logic/.../GrailsGroovydocExtension.groovyjavaVersionandjavaVersionEnabledpropertiesgradle/docs-dependencies.gradlegradle/docs-config.gradleincludeInApiDocsgrails-gradle/gradle/docs-config.gradlegrails-forge/gradle/doc-config.gradlejavaVersionEnabled = false) + depsgrails-data-hibernate5/docs/build.gradlegrails-data-mongodb/docs/build.gradlegrails-doc/build.gradlegrails-data-docs/stage/build.gradleTechnical details
resolveGroovydocProperty()helper handles the mix of plain values andProperty<T>wrappers in GradleGroovydoctask APIext.groovydocSourceDirsfor aggregate tasks, or derived from source sets for per-module tasksdocumentationconfiguration already includesgroovy-antin the central config; hibernate5 and mongodb docs needed it addedenabledbefore running any actionsgrails-data-neo4jandgrails-data-graphqlmodules are not in the build and were not changeddoFirstto populateext.groovydocLinks, plugin reads them indoLastTesting
:grails-core:groovydoc,:grails-bootstrap:groovydoc:grails-gradle-plugins:groovydoc:grails-doc:aggregateGroovydoc(3,929 HTML files generated):grails-data-docs-stage:aggregateDataMappingGroovydoc./gradlew codeStylepassesjavaVersionEnabled = false)Closes #15385