This is an automated email from the ASF dual-hosted git repository. jamesfredley pushed a commit to branch refactor/centralize-groovydoc-plugin in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 3c50821ea7aa98b15561e8e6672a45c91411e8f9 Author: James Fredley <[email protected]> AuthorDate: Thu Feb 19 20:32:21 2026 -0500 Centralize groovydoc configuration into GrailsGroovydocPlugin convention 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 <[email protected]> --- build-logic/plugins/build.gradle | 4 + .../buildsrc/GrailsGroovydocExtension.groovy | 67 ++++++++ .../grails/buildsrc/GrailsGroovydocPlugin.groovy | 186 +++++++++++++++++++++ gradle/docs-config.gradle | 9 - gradle/docs-dependencies.gradle | 121 +------------- grails-data-docs/stage/build.gradle | 17 -- grails-data-hibernate5/docs/build.gradle | 81 +-------- grails-data-mongodb/docs/build.gradle | 82 +-------- grails-doc/build.gradle | 17 -- grails-forge/gradle/doc-config.gradle | 93 +---------- grails-gradle/gradle/docs-config.gradle | 89 +--------- 11 files changed, 275 insertions(+), 491 deletions(-) diff --git a/build-logic/plugins/build.gradle b/build-logic/plugins/build.gradle index e85254e152..f750808908 100644 --- a/build-logic/plugins/build.gradle +++ b/build-logic/plugins/build.gradle @@ -62,6 +62,10 @@ gradlePlugin { id = 'org.apache.grails.gradle.grails-code-style' implementationClass = 'org.apache.grails.buildsrc.GrailsCodeStylePlugin' } + register('grailsGroovydoc') { + id = 'org.apache.grails.buildsrc.groovydoc' + implementationClass = 'org.apache.grails.buildsrc.GrailsGroovydocPlugin' + } register('grailsRepoSettings') { id = 'org.apache.grails.buildsrc.repo' implementationClass = 'org.apache.grails.buildsrc.GrailsRepoSettingsPlugin' diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocExtension.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocExtension.groovy new file mode 100644 index 0000000000..98cefd434c --- /dev/null +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocExtension.groovy @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.grails.buildsrc + +import javax.inject.Inject + +import groovy.transform.CompileStatic + +import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property + +/** + * Extension for configuring the Grails Groovydoc convention plugin. + * + * <p>Allows per-project control over the {@code javaVersion} parameter + * passed to the Groovy Ant groovydoc task. The {@code javaVersion} + * parameter was added in Groovy 4.0.27 (GROOVY-11668) and controls + * the JavaParser language level used when parsing Java sources.</p> + * + * @since 7.0.8 + */ +@CompileStatic +class GrailsGroovydocExtension { + + /** + * The Java language level string passed to the groovydoc Ant task's + * {@code javaVersion} parameter (e.g. {@code "JAVA_17"}, {@code "JAVA_21"}). + * + * <p>Defaults to {@code "JAVA_${javaVersion}"} where {@code javaVersion} + * is read from the project property, falling back to {@code "JAVA_17"}.</p> + */ + final Property<String> javaVersion + + /** + * Whether to pass the {@code javaVersion} parameter to the groovydoc + * Ant task. Set to {@code false} for projects using Groovy versions + * older than 4.0.27 (which do not support the parameter). + * + * <p>Defaults to {@code true}.</p> + */ + final Property<Boolean> javaVersionEnabled + + @Inject + GrailsGroovydocExtension(ObjectFactory objects, Project project) { + javaVersion = objects.property(String).convention( + "JAVA_${GradleUtils.findProperty(project, 'javaVersion') ?: '17'}" as String + ) + javaVersionEnabled = objects.property(Boolean).convention(true) + } +} diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy new file mode 100644 index 0000000000..d5e5875af2 --- /dev/null +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.grails.buildsrc + +import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Bundling +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.Usage +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.javadoc.Groovydoc + +@CompileStatic +class GrailsGroovydocPlugin implements Plugin<Project> { + + static final String MATOMO_FOOTER = '''\ +<!-- Matomo --> +<script> + var _paq = window._paq = window._paq || []; + /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ + _paq.push(["setDoNotTrack", true]); + _paq.push(["disableCookies"]); + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + (function() { + var u="https://analytics.apache.org/"; + _paq.push(['setTrackerUrl', u+'matomo.php']); + _paq.push(['setSiteId', '79']); + var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; + g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); + })(); +</script> +<!-- End Matomo Code -->''' + + @Override + void apply(Project project) { + GrailsGroovydocExtension extension = project.extensions.create( + 'grailsGroovydoc', GrailsGroovydocExtension, project + ) + registerDocumentationConfiguration(project) + configureGroovydocDefaults(project) + configureAntBuilderExecution(project, extension) + } + + private static void registerDocumentationConfiguration(Project project) { + if (project.configurations.names.contains('documentation')) { + return + } + project.configurations.register('documentation') { Configuration config -> + config.canBeConsumed = false + config.canBeResolved = true + config.attributes { container -> + container.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category, Category.LIBRARY)) + container.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling, Bundling.EXTERNAL)) + container.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage, Usage.JAVA_RUNTIME)) + } + } + } + + @CompileDynamic + private static void configureGroovydocDefaults(Project project) { + project.tasks.withType(Groovydoc).configureEach { Groovydoc gdoc -> + gdoc.includeAuthor = false + gdoc.includeMainForScripts = false + gdoc.processScripts = false + gdoc.noTimestamp = true + gdoc.noVersionStamp = false + gdoc.footer = MATOMO_FOOTER + if (project.configurations.names.contains('documentation')) { + gdoc.groovyClasspath = project.configurations.getByName('documentation') + } + } + } + + @CompileDynamic + private static void configureAntBuilderExecution(Project project, GrailsGroovydocExtension extension) { + project.tasks.withType(Groovydoc).configureEach { Groovydoc gdoc -> + gdoc.actions.clear() + gdoc.doLast { + File destDir = gdoc.destinationDir + destDir.mkdirs() + + List<File> sourceDirs = resolveSourceDirectories(gdoc, project) + if (sourceDirs.isEmpty()) { + project.logger.lifecycle("Skipping groovydoc for ${gdoc.name}: no source directories found") + return + } + + Configuration docConfig = project.configurations.findByName('documentation') + if (!docConfig) { + project.logger.warn("Skipping groovydoc for ${gdoc.name}: 'documentation' configuration not found") + return + } + + project.ant.taskdef( + name: 'groovydoc', + classname: 'org.codehaus.groovy.ant.Groovydoc', + classpath: docConfig.asPath + ) + + List<Map<String, String>> links = resolveLinks(gdoc) + String sourcepath = sourceDirs.collect { it.absolutePath }.join(File.pathSeparator) + + Map<String, Object> antArgs = [ + 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 + ] + + if (extension.javaVersionEnabled.get()) { + antArgs.put('javaVersion', extension.javaVersion.get()) + } + + project.ant.groovydoc(antArgs) { + for (Map<String, String> l in links) { + link(packages: l.packages, href: l.href) + } + } + } + } + } + + @CompileDynamic + private static List<File> resolveSourceDirectories(Groovydoc gdoc, Project project) { + if (gdoc.ext.has('groovydocSourceDirs') && gdoc.ext.groovydocSourceDirs) { + return (gdoc.ext.groovydocSourceDirs as List<File>).findAll { it.exists() }.unique() as List<File> + } + + List<File> sourceDirs = [] + SourceSetContainer sourceSets = project.extensions.findByType(SourceSetContainer) + if (sourceSets) { + SourceSet mainSS = sourceSets.findByName('main') + if (mainSS) { + sourceDirs.addAll(mainSS.groovy.srcDirs.findAll { it.exists() }) + sourceDirs.addAll(mainSS.java.srcDirs.findAll { it.exists() }) + } + } + sourceDirs.unique() as List<File> + } + + @CompileDynamic + private static List<Map<String, String>> resolveLinks(Groovydoc gdoc) { + if (gdoc.ext.has('groovydocLinks')) { + return gdoc.ext.groovydocLinks as List<Map<String, String>> + } + [] + } + + static Object resolveGroovydocProperty(Object value) { + if (value instanceof Provider) { + return ((Provider) value).getOrNull() + } + value + } +} diff --git a/gradle/docs-config.gradle b/gradle/docs-config.gradle index 76a14b619b..5b5c7d1794 100644 --- a/gradle/docs-config.gradle +++ b/gradle/docs-config.gradle @@ -21,13 +21,4 @@ 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 23b75693b9..afb56aec4a 100644 --- a/gradle/docs-dependencies.gradle +++ b/gradle/docs-dependencies.gradle @@ -16,15 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -configurations.register('documentation') { - canBeConsumed = false - canBeResolved = true - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) - } -} +apply plugin: 'org.apache.grails.buildsrc.groovydoc' dependencies { add('documentation', platform(project(':grails-bom'))) @@ -50,127 +42,32 @@ 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 gdoc.windowTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion" gdoc.docTitle = "${project.findProperty('pomArtifactId') ?: project.name} - $projectVersion" - gdoc.access = GroovydocAccess.PROTECTED - gdoc.includeAuthor = false - gdoc.includeMainForScripts = false - gdoc.processScripts = false - gdoc.noTimestamp = true - gdoc.noVersionStamp = false - gdoc.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' - // 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() - - 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 = [] + gdoc.doFirst { + List<Map<String, String>> links = [] def gebVersion = resolveProjectVersion('geb-spock') if (gebVersion) { - groovydocLinks << [packages: 'geb.', href: "https://groovy.apache.org/geb/manual/${gebVersion}/api/"] + links << [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}/"] + links << [packages: 'org.testcontainers.', href: "https://javadoc.io/doc/org.testcontainers/testcontainers/${testContainersVersion}/"] } def springVersion = resolveProjectVersion('spring-core') if (springVersion) { - groovydocLinks << [packages: 'org.springframework.core.', href: "https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/"] + links << [packages: 'org.springframework.core.', href: "https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/"] } def springBootVersion = resolveProjectVersion('spring-boot') if (springBootVersion) { - groovydocLinks << [packages: 'org.springframework.boot.', href: "https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/"] + links << [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) - } + links.addAll(gdoc.ext.groovydocLinks as List<Map<String, String>>) } + gdoc.ext.groovydocLinks = links } } \ No newline at end of file diff --git a/grails-data-docs/stage/build.gradle b/grails-data-docs/stage/build.gradle index 4d13bb6b01..5af7d88544 100644 --- a/grails-data-docs/stage/build.gradle +++ b/grails-data-docs/stage/build.gradle @@ -25,23 +25,6 @@ apply from: rootProject.layout.projectDirectory.file('gradle/docs-dependencies.g combinedGroovydoc.configure { Groovydoc task -> task.windowTitle = "Grails Data Mapping API - ${projectVersion}" task.docTitle = "Grails Data Mapping API - ${projectVersion}" - task.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' Set<Project> docProjects = rootProject.subprojects.findAll { it.name in [ diff --git a/grails-data-hibernate5/docs/build.gradle b/grails-data-hibernate5/docs/build.gradle index 565da447cb..be9c04f90d 100644 --- a/grails-data-hibernate5/docs/build.gradle +++ b/grails-data-hibernate5/docs/build.gradle @@ -31,13 +31,7 @@ ext { coreProjects = ['grails-datastore-core', 'grails-datamapping-core'] } -configurations { - documentation { - attributes { - attribute(Bundling.BUNDLING_ATTRIBUTE, (Bundling) (objects.named(Bundling, 'external'))) - } - } -} +apply plugin: 'org.apache.grails.buildsrc.groovydoc' dependencies { documentation platform(project(':grails-bom')) @@ -94,41 +88,12 @@ 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') } .collect { ":${it.name}:groovydoc" }) it.docTitle = "GORM for Hibernate 5 - $project.version" - it.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' def sourceFiles = coreProjects.collect { rootProject.layout.projectDirectory.files("$it/src/main/groovy") @@ -140,15 +105,8 @@ tasks.withType(Groovydoc).configureEach { it.source = sourceFiles it.destinationDir = layout.buildDirectory.dir('combined-api/api').get().asFile - it.access = GroovydocAccess.PROTECTED - it.processScripts = false - it.includeMainForScripts = false - it.includeAuthor = false 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 } @@ -156,43 +114,6 @@ tasks.withType(Groovydoc).configureEach { .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 81a0fca998..02de80eb95 100644 --- a/grails-data-mongodb/docs/build.gradle +++ b/grails-data-mongodb/docs/build.gradle @@ -31,13 +31,7 @@ ext { coreProjects = ['grails-datastore-core', 'grails-datamapping-core'] } -configurations { - documentation { - attributes { - attribute(Bundling.BUNDLING_ATTRIBUTE, (Bundling) (objects.named(Bundling, 'external'))) - } - } -} +apply plugin: 'org.apache.grails.buildsrc.groovydoc' tasks.register('resolveMongodbVersion').configure { Task docTask -> docTask.group = 'documentation' @@ -103,40 +97,12 @@ 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') } .collect { ":${it.name}:groovydoc" }) groovydoc.docTitle = "GORM for MongoDB - $project.version" - groovydoc.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' + groovydoc.includeAuthor = true def sourceFiles = coreProjects.collect { layout.projectDirectory.files("$it/src/main/groovy") @@ -148,15 +114,8 @@ tasks.withType(Groovydoc).configureEach { Groovydoc groovydoc -> groovydoc.source = sourceFiles groovydoc.destinationDir = layout.buildDirectory.dir('combined-api/api').get().asFile - groovydoc.access = GroovydocAccess.PROTECTED - groovydoc.processScripts = false - groovydoc.includeMainForScripts = false - groovydoc.includeAuthor = true 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 } @@ -164,43 +123,6 @@ tasks.withType(Groovydoc).configureEach { Groovydoc groovydoc -> .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 63382c712e..4f7c1d9d87 100644 --- a/grails-doc/build.gradle +++ b/grails-doc/build.gradle @@ -63,23 +63,6 @@ apply from: rootProject.layout.projectDirectory.file('gradle/docs-dependencies.g combinedGroovydoc.configure { Groovydoc gdoc -> gdoc.windowTitle = "Grails $projectVersion" gdoc.docTitle = "Grails $projectVersion" - gdoc.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' def docProjects = rootProject.subprojects .findAll { it.findProperty('includeInApiDocs') } diff --git a/grails-forge/gradle/doc-config.gradle b/grails-forge/gradle/doc-config.gradle index 38b8e2a60d..4d22d4fba6 100644 --- a/grails-forge/gradle/doc-config.gradle +++ b/grails-forge/gradle/doc-config.gradle @@ -17,14 +17,10 @@ * under the License. */ -configurations.register('documentation') { - canBeConsumed = false - canBeResolved = true - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) - } +apply plugin: 'org.apache.grails.buildsrc.groovydoc' + +grailsGroovydoc { + javaVersionEnabled = false } dependencies { @@ -38,85 +34,4 @@ 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" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</script> -<!-- End Matomo Code -->''' - 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 e3459998b6..8426b70a63 100644 --- a/grails-gradle/gradle/docs-config.gradle +++ b/grails-gradle/gradle/docs-config.gradle @@ -17,15 +17,8 @@ * under the License. */ -configurations.register('documentation') { - canBeConsumed = false - canBeResolved = true - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) - } -} +apply plugin: 'org.apache.grails.buildsrc.groovydoc' + dependencies { add('documentation', platform(project(':grails-gradle-bom'))) add('documentation', 'org.fusesource.jansi:jansi') @@ -42,88 +35,10 @@ 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 - it.groovyClasspath = configurations.documentation - it.access = GroovydocAccess.PROTECTED - it.includeAuthor = false - it.includeMainForScripts = false - it.processScripts = false - it.noTimestamp = true - it.noVersionStamp = false - it.footer = '''<!-- Matomo --> -<script> - var _paq = window._paq = window._paq || []; - /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ - _paq.push(["setDoNotTrack", true]); - _paq.push(["disableCookies"]); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u="https://analytics.apache.org/"; - _paq.push(['setTrackerUrl', u+'matomo.php']); - _paq.push(['setSiteId', '79']); - var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); - })(); -</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 {
