You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ja...@apache.org on 2026/02/20 01:01:00 UTC
(grails-core) 01/01: Adopt AntBuilder groovydoc with javaVersion support
This is an automated email from the ASF dual-hosted git repository.
jamesfredley pushed a commit to branch fix/groovydoc-java-version
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 3467bad8dbaa0da1e973e6a4cdb1bc1f07f1fc43
Author: James Fredley <ja...@users.noreply.github.com>
AuthorDate: Thu Feb 19 20:00:48 2026 -0500
Adopt AntBuilder groovydoc with javaVersion support
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 <Cl...@Claude.ai>
---
gradle/docs-config.gradle | 9 +++
gradle/docs-dependencies.gradle | 97 ++++++++++++++++++++++++++++----
grails-data-docs/stage/build.gradle | 10 ++--
grails-data-hibernate5/docs/build.gradle | 62 ++++++++++++++++++++
grails-data-mongodb/docs/build.gradle | 61 ++++++++++++++++++++
grails-doc/build.gradle | 4 +-
grails-forge/gradle/doc-config.gradle | 82 +++++++++++++++++++++++----
grails-gradle/gradle/docs-config.gradle | 54 ++++++++++++++++++
8 files changed, 351 insertions(+), 28 deletions(-)
diff --git a/gradle/docs-config.gradle b/gradle/docs-config.gradle
index 5b5c7d1794..76a14b619b 100644
--- a/gradle/docs-config.gradle
+++ b/gradle/docs-config.gradle
@@ -21,4 +21,13 @@ apply from: rootProject.layout.projectDirectory.file('gradle/docs-dependencies.g
ext {
includeInApiDocs = true
+}
+
+// Set source directories for AntBuilder groovydoc execution (per-module tasks)
+tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
+ SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer)
+ SourceSet mainSS = sourceSets.findByName('main')
+ if (mainSS) {
+ gdoc.ext.groovydocSourceDirs = (mainSS.groovy.srcDirs + mainSS.java.srcDirs).findAll { it.exists() }
+ }
}
\ No newline at end of file
diff --git a/gradle/docs-dependencies.gradle b/gradle/docs-dependencies.gradle
index df4244f39c..23b75693b9 100644
--- a/gradle/docs-dependencies.gradle
+++ b/gradle/docs-dependencies.gradle
@@ -50,6 +50,21 @@ String resolveProjectVersion(String artifact) {
}
}
+// Resolve a Groovydoc task property that may be either a Gradle Property<T> or a plain value.
+// Gradle 8.x Groovydoc uses a mix of both types depending on the property.
+Object resolveGroovydocProperty(Object value) {
+ if (value instanceof org.gradle.api.provider.Provider) {
+ return value.getOrNull()
+ }
+ return value
+}
+
+// Compute the javaVersion string for groovydoc's JavaParser language level.
+// Requires Groovy 4.0.27+ (GROOVY-11668). Gradle's built-in Groovydoc task does not
+// expose this parameter (https://github.com/gradle/gradle/issues/33659), so we replace
+// the task execution with AntBuilder to pass it directly to the Groovy Ant task.
+String groovydocJavaVersion = "JAVA_${project.findProperty('javaVersion') ?: '17'}"
+
tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
gdoc.exclude('META-INF/**', '*yml', '*properties', '*xml', '**/Application.groovy', '**/Bootstrap.groovy', '**/resources.groovy')
gdoc.groovyClasspath = configurations.documentation
@@ -79,25 +94,83 @@ tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
</script>
<!-- End Matomo Code -->'''
- doFirst {
- def gebVersion = resolveProjectVersion('geb-spock')
- if(gebVersion) {
- gdoc.link("https://groovy.apache.org/geb/manual/${gebVersion}/api/", 'geb.')
+ // Replace Gradle's built-in Groovydoc execution with AntBuilder to support javaVersion.
+ // See: https://github.com/apache/grails-core/issues/15385
+ gdoc.actions.clear()
+ gdoc.doLast {
+ def destDir = gdoc.destinationDir
+ destDir.mkdirs()
+
+ // Source directories: set by modules via ext.groovydocSourceDirs, or derived from source sets
+ List<File> sourceDirs
+ if (gdoc.ext.has('groovydocSourceDirs') && gdoc.ext.groovydocSourceDirs) {
+ sourceDirs = (gdoc.ext.groovydocSourceDirs as List<File>).findAll { it.exists() }
+ } else {
+ sourceDirs = []
+ def sourceSetsExt = project.extensions.findByType(SourceSetContainer)
+ if (sourceSetsExt) {
+ def mainSS = sourceSetsExt.findByName('main')
+ if (mainSS) {
+ sourceDirs.addAll(mainSS.groovy.srcDirs.findAll { it.exists() })
+ sourceDirs.addAll(mainSS.java.srcDirs.findAll { it.exists() })
+ }
+ }
}
+ sourceDirs = sourceDirs.unique()
- def testContainersVersion = resolveProjectVersion('testcontainers')
- if(testContainersVersion) {
- gdoc.link("https://javadoc.io/doc/org.testcontainers/testcontainers/${testContainersVersion}/", 'org.testcontainers.')
+ if (sourceDirs.isEmpty()) {
+ logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found")
+ return
}
+ ant.taskdef(
+ name: 'groovydoc',
+ classname: 'org.codehaus.groovy.ant.Groovydoc',
+ classpath: configurations.documentation.asPath
+ )
+
+ // Resolve dynamic links from project dependencies
+ List<Map<String, String>> groovydocLinks = []
+ def gebVersion = resolveProjectVersion('geb-spock')
+ if (gebVersion) {
+ groovydocLinks << [packages: 'geb.', href: "https://groovy.apache.org/geb/manual/${gebVersion}/api/"]
+ }
+ def testContainersVersion = resolveProjectVersion('testcontainers')
+ if (testContainersVersion) {
+ groovydocLinks << [packages: 'org.testcontainers.', href: "https://javadoc.io/doc/org.testcontainers/testcontainers/${testContainersVersion}/"]
+ }
def springVersion = resolveProjectVersion('spring-core')
- if(springVersion) {
- gdoc.link("https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/", 'org.springframework.core.')
+ if (springVersion) {
+ groovydocLinks << [packages: 'org.springframework.core.', href: "https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/"]
}
-
def springBootVersion = resolveProjectVersion('spring-boot')
- if(springBootVersion) {
- gdoc.link("https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/", 'org.springframework.boot.')
+ if (springBootVersion) {
+ groovydocLinks << [packages: 'org.springframework.boot.', href: "https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/"]
+ }
+ if (gdoc.ext.has('groovydocLinks')) {
+ groovydocLinks.addAll(gdoc.ext.groovydocLinks as List<Map<String, String>>)
+ }
+
+ def sourcepath = sourceDirs.collect { it.absolutePath }.join(File.pathSeparator)
+
+ ant.groovydoc(
+ destdir: destDir.absolutePath,
+ sourcepath: sourcepath,
+ packagenames: '**.*',
+ windowtitle: gdoc.windowTitle ?: '',
+ doctitle: gdoc.docTitle ?: '',
+ footer: gdoc.footer ?: '',
+ access: resolveGroovydocProperty(gdoc.access)?.name()?.toLowerCase() ?: 'protected',
+ author: resolveGroovydocProperty(gdoc.includeAuthor) as String,
+ noTimestamp: resolveGroovydocProperty(gdoc.noTimestamp) as String,
+ noVersionStamp: resolveGroovydocProperty(gdoc.noVersionStamp) as String,
+ processScripts: resolveGroovydocProperty(gdoc.processScripts) as String,
+ includeMainForScripts: resolveGroovydocProperty(gdoc.includeMainForScripts) as String,
+ javaVersion: groovydocJavaVersion
+ ) {
+ for (Map<String, String> l in groovydocLinks) {
+ link(packages: l.packages, href: l.href)
+ }
}
}
}
\ No newline at end of file
diff --git a/grails-data-docs/stage/build.gradle b/grails-data-docs/stage/build.gradle
index b5d71cc03a..4d13bb6b01 100644
--- a/grails-data-docs/stage/build.gradle
+++ b/grails-data-docs/stage/build.gradle
@@ -77,14 +77,16 @@ combinedGroovydoc.configure { Groovydoc task ->
}
.flatten()
- task.source(sources.collect{ SourceSet it -> [it.allSource.srcDirs, it.allSource.srcDirs] }.flatten().findAll { File srcDir ->
- if(!(srcDir.name in ['java', 'groovy'])) {
+ def allSourceDirs = sources.collect { SourceSet it -> [it.allSource.srcDirs, it.allSource.srcDirs] }.flatten().findAll { File srcDir ->
+ if (!(srcDir.name in ['java', 'groovy'])) {
return false
}
srcDir.exists()
- }.unique())
- task.classpath = files(sources.collect{ SourceSet it -> it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
+ }.unique()
+ task.source(allSourceDirs)
+ task.ext.groovydocSourceDirs = allSourceDirs
+ task.classpath = files(sources.collect { SourceSet it -> it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
task.destinationDir = project.layout.buildDirectory.dir('data-api/api').get().asFile
task.inputs.files(task.source).withPropertyName("groovyDocSrc").withPathSensitivity(PathSensitivity.RELATIVE)
diff --git a/grails-data-hibernate5/docs/build.gradle b/grails-data-hibernate5/docs/build.gradle
index aed5772187..565da447cb 100644
--- a/grails-data-hibernate5/docs/build.gradle
+++ b/grails-data-hibernate5/docs/build.gradle
@@ -44,7 +44,11 @@ dependencies {
documentation 'com.github.javaparser:javaparser-core'
documentation "info.picocli:picocli:$picocliVersion"
documentation 'org.apache.groovy:groovy-dateutil'
+ documentation 'org.apache.groovy:groovy-ant'
+ documentation 'org.apache.groovy:groovy-groovydoc'
+ documentation 'org.apache.groovy:groovy-templates'
documentation 'org.fusesource.jansi:jansi'
+ documentation 'jline:jline'
documentation project(':grails-bootstrap')
documentation project(':grails-core')
documentation project(':grails-spring')
@@ -90,6 +94,18 @@ tasks.named('asciidoctor', AsciidoctorTask) { AsciidoctorTask it ->
]
}
+// Resolve a Groovydoc task property that may be either a Gradle Property<T> or a plain value.
+Object resolveGroovydocProperty(Object value) {
+ if (value instanceof org.gradle.api.provider.Provider) {
+ return value.getOrNull()
+ }
+ return value
+}
+
+// Compute the javaVersion string for groovydoc's JavaParser language level.
+// Requires Groovy 4.0.27+ (GROOVY-11668).
+String groovydocJavaVersion = "JAVA_${project.findProperty('javaVersion') ?: '17'}"
+
tasks.withType(Groovydoc).configureEach {
it.dependsOn(rootProject.subprojects
.findAll { it.findProperty('gormApiDocs') }
@@ -131,6 +147,52 @@ tasks.withType(Groovydoc).configureEach {
it.classpath = configurations.documentation
it.groovyClasspath += configurations.documentation
it.noVersionStamp = false
+
+ // Collect source directories for AntBuilder groovydoc
+ List<File> groovydocSrcDirs = coreProjects.collect {
+ rootProject.layout.projectDirectory.dir("$it/src/main/groovy").asFile
+ }
+ rootProject.subprojects
+ .findAll { sp -> sp.findProperty('gormApiDocs') }
+ .each { sp -> groovydocSrcDirs << new File(sp.projectDir, 'src/main/groovy') }
+ it.ext.groovydocSourceDirs = groovydocSrcDirs
+
+ // Replace Gradle's built-in Groovydoc execution with AntBuilder to support javaVersion.
+ // See: https://github.com/apache/grails-core/issues/15385
+ it.actions.clear()
+ it.doLast { Groovydoc gdoc ->
+ def destDir = gdoc.destinationDir
+ destDir.mkdirs()
+
+ List<File> sourceDirs = (gdoc.ext.groovydocSourceDirs as List<File>).findAll { File f -> f.exists() }.unique()
+ if (sourceDirs.isEmpty()) {
+ logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found")
+ return
+ }
+
+ ant.taskdef(
+ name: 'groovydoc',
+ classname: 'org.codehaus.groovy.ant.Groovydoc',
+ classpath: configurations.documentation.asPath
+ )
+
+ def sourcepath = sourceDirs.collect { File f -> f.absolutePath }.join(File.pathSeparator)
+
+ ant.groovydoc(
+ destdir: destDir.absolutePath,
+ sourcepath: sourcepath,
+ packagenames: '**.*',
+ doctitle: gdoc.docTitle ?: '',
+ footer: gdoc.footer ?: '',
+ access: resolveGroovydocProperty(gdoc.access)?.name()?.toLowerCase() ?: 'protected',
+ author: resolveGroovydocProperty(gdoc.includeAuthor) as String,
+ noTimestamp: 'true',
+ noVersionStamp: resolveGroovydocProperty(gdoc.noVersionStamp) as String,
+ processScripts: resolveGroovydocProperty(gdoc.processScripts) as String,
+ includeMainForScripts: resolveGroovydocProperty(gdoc.includeMainForScripts) as String,
+ javaVersion: groovydocJavaVersion
+ )
+ }
}
tasks.register('docs', Sync).configure { Sync docTask ->
diff --git a/grails-data-mongodb/docs/build.gradle b/grails-data-mongodb/docs/build.gradle
index 89cfce4530..81a0fca998 100644
--- a/grails-data-mongodb/docs/build.gradle
+++ b/grails-data-mongodb/docs/build.gradle
@@ -56,7 +56,10 @@ tasks.register('resolveMongodbVersion').configure { Task docTask ->
dependencies {
documentation platform(project(':grails-bom'))
documentation 'org.fusesource.jansi:jansi'
+ documentation 'jline:jline'
documentation 'org.apache.groovy:groovy'
+ documentation 'org.apache.groovy:groovy-ant'
+ documentation 'org.apache.groovy:groovy-groovydoc'
documentation 'org.apache.groovy:groovy-templates'
documentation 'org.apache.groovy:groovy-dateutil'
documentation 'com.github.javaparser:javaparser-core'
@@ -100,6 +103,18 @@ tasks.named('asciidoctor', AsciidoctorTask) { AsciidoctorTask it ->
]
}
+// Compute the javaVersion string for groovydoc's JavaParser language level.
+// Requires Groovy 4.0.27+ (GROOVY-11668).
+String groovydocJavaVersion = "JAVA_${project.findProperty('javaVersion') ?: '17'}"
+
+// Resolve a Groovydoc task property that may be either a Gradle Property<T> or a plain value.
+Object resolveGroovydocProperty(Object value) {
+ if (value instanceof org.gradle.api.provider.Provider) {
+ return value.getOrNull()
+ }
+ return value
+}
+
tasks.withType(Groovydoc).configureEach { Groovydoc groovydoc ->
groovydoc.dependsOn(rootProject.subprojects
.findAll { it.findProperty('gormApiDocs') }
@@ -140,6 +155,52 @@ tasks.withType(Groovydoc).configureEach { Groovydoc groovydoc ->
groovydoc.classpath = configurations.documentation
groovydoc.groovyClasspath += configurations.documentation
groovydoc.noVersionStamp = false
+
+ // Collect source directories for AntBuilder groovydoc
+ List<File> groovydocSrcDirs = coreProjects.collect {
+ layout.projectDirectory.dir("$it/src/main/groovy").asFile
+ }
+ rootProject.subprojects
+ .findAll { sp -> sp.findProperty('gormApiDocs') }
+ .each { sp -> groovydocSrcDirs << new File(sp.projectDir, 'src/main/groovy') }
+ groovydoc.ext.groovydocSourceDirs = groovydocSrcDirs
+
+ // Replace Gradle's built-in Groovydoc execution with AntBuilder to support javaVersion.
+ // See: https://github.com/apache/grails-core/issues/15385
+ groovydoc.actions.clear()
+ groovydoc.doLast { Groovydoc gdoc ->
+ def destDir = gdoc.destinationDir
+ destDir.mkdirs()
+
+ List<File> sourceDirs = (gdoc.ext.groovydocSourceDirs as List<File>).findAll { File f -> f.exists() }.unique()
+ if (sourceDirs.isEmpty()) {
+ logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found")
+ return
+ }
+
+ ant.taskdef(
+ name: 'groovydoc',
+ classname: 'org.codehaus.groovy.ant.Groovydoc',
+ classpath: configurations.documentation.asPath
+ )
+
+ def sourcepath = sourceDirs.collect { File f -> f.absolutePath }.join(File.pathSeparator)
+
+ ant.groovydoc(
+ destdir: destDir.absolutePath,
+ sourcepath: sourcepath,
+ packagenames: '**.*',
+ doctitle: gdoc.docTitle ?: '',
+ footer: gdoc.footer ?: '',
+ access: resolveGroovydocProperty(gdoc.access)?.name()?.toLowerCase() ?: 'protected',
+ author: resolveGroovydocProperty(gdoc.includeAuthor) as String,
+ noTimestamp: 'true',
+ noVersionStamp: resolveGroovydocProperty(gdoc.noVersionStamp) as String,
+ processScripts: resolveGroovydocProperty(gdoc.processScripts) as String,
+ includeMainForScripts: resolveGroovydocProperty(gdoc.includeMainForScripts) as String,
+ javaVersion: groovydocJavaVersion
+ )
+ }
}
tasks.register('docs', Sync).configure { Sync docTask ->
diff --git a/grails-doc/build.gradle b/grails-doc/build.gradle
index 1802c28395..63382c712e 100644
--- a/grails-doc/build.gradle
+++ b/grails-doc/build.gradle
@@ -127,7 +127,9 @@ combinedGroovydoc.configure { Groovydoc gdoc ->
sourceDirs
}
- gdoc.source(project.files((baseSourceDirs + includedBuildSourceDirs).unique()))
+ def allSourceDirs = (baseSourceDirs + includedBuildSourceDirs).unique()
+ gdoc.source(project.files(allSourceDirs))
+ gdoc.ext.groovydocSourceDirs = allSourceDirs
gdoc.classpath = files(sources.collect { SourceSet it -> it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
gdoc.destinationDir = project.layout.buildDirectory.dir('combined-api/api').get().asFile
diff --git a/grails-forge/gradle/doc-config.gradle b/grails-forge/gradle/doc-config.gradle
index d7b0eaf7fb..38b8e2a60d 100644
--- a/grails-forge/gradle/doc-config.gradle
+++ b/grails-forge/gradle/doc-config.gradle
@@ -30,13 +30,15 @@ configurations.register('documentation') {
dependencies {
documentation "org.codehaus.groovy:groovy-templates:$groovyVersion"
documentation "org.codehaus.groovy:groovy-dateutil:$groovyVersion"
+ documentation "org.codehaus.groovy:groovy-ant:$groovyVersion"
+ documentation "org.codehaus.groovy:groovy-groovydoc:$groovyVersion"
}
-tasks.withType(Groovydoc).configureEach {
- classpath += project.configurations.documentation
- windowTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion"
- docTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion"
- footer = '''<!-- Matomo -->
+tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
+ gdoc.classpath += project.configurations.documentation
+ gdoc.windowTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion"
+ gdoc.docTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion"
+ gdoc.footer = '''<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
@@ -53,10 +55,68 @@ tasks.withType(Groovydoc).configureEach {
})();
</script>
<!-- End Matomo Code -->'''
- access = GroovydocAccess.PROTECTED
- includeAuthor = false
- includeMainForScripts = false
- processScripts = false
- noTimestamp = true
- noVersionStamp = false
+ gdoc.access = GroovydocAccess.PROTECTED
+ gdoc.includeAuthor = false
+ gdoc.includeMainForScripts = false
+ gdoc.processScripts = false
+ gdoc.noTimestamp = true
+ gdoc.noVersionStamp = false
+
+ // Resolve a Groovydoc task property that may be either a Gradle Property<T> or a plain value.
+ Closure resolveGroovydocProperty = { Object value ->
+ if (value instanceof org.gradle.api.provider.Provider) {
+ return value.getOrNull()
+ }
+ return value
+ }
+
+ // Replace Gradle's built-in Groovydoc execution with AntBuilder for consistency
+ // with the main build. The javaVersion parameter is not available in Groovy 3.x
+ // (requires Groovy 4.0.27+, GROOVY-11668) - it will be added when forge upgrades.
+ // See: https://github.com/apache/grails-core/issues/15385
+ gdoc.actions.clear()
+ gdoc.doLast {
+ def destDir = gdoc.destinationDir
+ destDir.mkdirs()
+
+ List<File> sourceDirs = []
+ def sourceSetsExt = project.extensions.findByType(SourceSetContainer)
+ if (sourceSetsExt) {
+ def mainSS = sourceSetsExt.findByName('main')
+ if (mainSS) {
+ sourceDirs.addAll(mainSS.groovy.srcDirs.findAll { it.exists() })
+ sourceDirs.addAll(mainSS.java.srcDirs.findAll { it.exists() })
+ }
+ }
+ sourceDirs = sourceDirs.unique()
+
+ if (sourceDirs.isEmpty()) {
+ logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found")
+ return
+ }
+
+ ant.taskdef(
+ name: 'groovydoc',
+ classname: 'org.codehaus.groovy.ant.Groovydoc',
+ classpath: configurations.documentation.asPath
+ )
+
+ def sourcepath = sourceDirs.collect { File f -> f.absolutePath }.join(File.pathSeparator)
+
+ // Note: javaVersion omitted - not supported in Groovy 3.x (forge uses Groovy $groovyVersion)
+ ant.groovydoc(
+ destdir: destDir.absolutePath,
+ sourcepath: sourcepath,
+ packagenames: '**.*',
+ windowtitle: gdoc.windowTitle ?: '',
+ doctitle: gdoc.docTitle ?: '',
+ footer: gdoc.footer ?: '',
+ access: resolveGroovydocProperty(gdoc.access)?.name()?.toLowerCase() ?: 'protected',
+ author: resolveGroovydocProperty(gdoc.includeAuthor) as String,
+ noTimestamp: resolveGroovydocProperty(gdoc.noTimestamp) as String,
+ noVersionStamp: resolveGroovydocProperty(gdoc.noVersionStamp) as String,
+ processScripts: resolveGroovydocProperty(gdoc.processScripts) as String,
+ includeMainForScripts: resolveGroovydocProperty(gdoc.includeMainForScripts) as String
+ )
+ }
}
diff --git a/grails-gradle/gradle/docs-config.gradle b/grails-gradle/gradle/docs-config.gradle
index be2aaf4f1c..e3459998b6 100644
--- a/grails-gradle/gradle/docs-config.gradle
+++ b/grails-gradle/gradle/docs-config.gradle
@@ -42,6 +42,18 @@ ext {
includeInApiDocs = true
}
+// Resolve a Groovydoc task property that may be either a Gradle Property<T> or a plain value.
+Object resolveGroovydocProperty(Object value) {
+ if (value instanceof org.gradle.api.provider.Provider) {
+ return value.getOrNull()
+ }
+ return value
+}
+
+// Compute the javaVersion string for groovydoc's JavaParser language level.
+// Requires Groovy 4.0.27+ (GROOVY-11668).
+String groovydocJavaVersion = "JAVA_${project.findProperty('javaVersion') ?: '17'}"
+
TaskProvider<Groovydoc> groovydocTask = tasks.named('groovydoc', Groovydoc)
groovydocTask.configure { Groovydoc it ->
it.classpath = configurations.documentation
@@ -70,6 +82,48 @@ groovydocTask.configure { Groovydoc it ->
</script>
<!-- End Matomo Code -->'''
it.destinationDir = project.file('build/docs/api')
+
+ // Replace Gradle's built-in Groovydoc execution with AntBuilder to support javaVersion.
+ // See: https://github.com/apache/grails-core/issues/15385
+ it.actions.clear()
+ it.doLast {
+ def destDir = it.destinationDir
+ destDir.mkdirs()
+
+ SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer)
+ List<File> sourceDirs = ([] + sourceSets.main.groovy.srcDirs + sourceSets.main.java.srcDirs)
+ .findAll { File f -> f.exists() }
+ .unique()
+
+ if (sourceDirs.isEmpty()) {
+ logger.lifecycle("Skipping groovydoc for ${it.name}: no source directories found")
+ return
+ }
+
+ ant.taskdef(
+ name: 'groovydoc',
+ classname: 'org.codehaus.groovy.ant.Groovydoc',
+ classpath: configurations.documentation.asPath
+ )
+
+ def sourcepath = sourceDirs.collect { File f -> f.absolutePath }.join(File.pathSeparator)
+
+ ant.groovydoc(
+ destdir: destDir.absolutePath,
+ sourcepath: sourcepath,
+ packagenames: '**.*',
+ windowtitle: it.windowTitle ?: '',
+ doctitle: it.docTitle ?: '',
+ footer: it.footer ?: '',
+ access: resolveGroovydocProperty(it.access)?.name()?.toLowerCase() ?: 'protected',
+ author: resolveGroovydocProperty(it.includeAuthor) as String,
+ noTimestamp: resolveGroovydocProperty(it.noTimestamp) as String,
+ noVersionStamp: resolveGroovydocProperty(it.noVersionStamp) as String,
+ processScripts: resolveGroovydocProperty(it.processScripts) as String,
+ includeMainForScripts: resolveGroovydocProperty(it.includeMainForScripts) as String,
+ javaVersion: groovydocJavaVersion
+ )
+ }
}
tasks.named('javadoc').configure {