ScaladocPlugin.groovy
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2018-2019 Andres Almiray.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package org.kordamp.gradle.plugin.scaladoc
019 
020 import groovy.transform.CompileStatic
021 import org.gradle.BuildAdapter
022 import org.gradle.api.Project
023 import org.gradle.api.Task
024 import org.gradle.api.invocation.Gradle
025 import org.gradle.api.plugins.JavaBasePlugin
026 import org.gradle.api.plugins.scala.ScalaBasePlugin
027 import org.gradle.api.publish.maven.MavenPublication
028 import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
029 import org.gradle.api.tasks.bundling.Jar
030 import org.gradle.api.tasks.scala.ScalaDoc
031 import org.kordamp.gradle.plugin.AbstractKordampPlugin
032 import org.kordamp.gradle.plugin.base.BasePlugin
033 import org.kordamp.gradle.plugin.base.ProjectConfigurationExtension
034 
035 import static org.kordamp.gradle.PluginUtils.resolveEffectiveConfig
036 import static org.kordamp.gradle.plugin.base.BasePlugin.isRootProject
037 
038 /**
039  * Configures {@code scaladoc} and {@code scaladocJar} tasks.
040  *
041  @author Andres Almiray
042  @since 0.15.0
043  */
044 class ScaladocPlugin extends AbstractKordampPlugin {
045     static final String SCALADOC_TASK_NAME = 'scaladoc'
046     static final String SCALADOC_JAR_TASK_NAME = 'scaladocJar'
047     static final String AGGREGATE_SCALADOCS_TASK_NAME = 'aggregateScaladocs'
048     static final String AGGREGATE_SCALADOCS_JAR_TASK_NAME = 'aggregateScaladocsJar'
049 
050     Project project
051 
052     @CompileStatic
053     void apply(Project project) {
054         this.project = project
055 
056         if (isRootProject(project)) {
057             if (project.childProjects.size()) {
058                 project.childProjects.values().each {
059                     configureProject(it)
060                 }
061                 configureRootProject(project, true)
062             else {
063                 configureProject(project)
064                 configureRootProject(project, false)
065             }
066         else {
067             configureProject(project)
068         }
069     }
070 
071     @CompileStatic
072     static void applyIfMissing(Project project) {
073         if (!project.plugins.findPlugin(ScaladocPlugin)) {
074             project.plugins.apply(ScaladocPlugin)
075         }
076     }
077 
078     @CompileStatic
079     private void configureRootProject(Project project, boolean checkIfApplied) {
080         if (checkIfApplied && hasBeenVisited(project)) {
081             return
082         }
083         setVisited(project, true)
084 
085         BasePlugin.applyIfMissing(project)
086 
087         if (isRootProject(project&& !project.childProjects.isEmpty()) {
088             createAggregateScaladocsTask(project)
089 
090             project.gradle.addBuildListener(new BuildAdapter() {
091                 @Override
092                 void projectsEvaluated(Gradle gradle) {
093                     doConfigureRootProject(project)
094                 }
095             })
096         }
097     }
098 
099     private void doConfigureRootProject(Project project) {
100         ProjectConfigurationExtension effectiveConfig = resolveEffectiveConfig(project)
101         setEnabled(effectiveConfig.scaladoc.enabled)
102 
103         if (!enabled) {
104             return
105         }
106 
107         if (!project.childProjects.isEmpty()) {
108             List<ScalaDoc> scaladocs = []
109             project.tasks.withType(ScalaDoc) { ScalaDoc scaladoc -> if (scaladoc.name != AGGREGATE_SCALADOCS_TASK_NAME && scaladoc.enabledscaladocs << scaladoc }
110             project.childProjects.values().each Project p ->
111                 if (p in effectiveConfig.scaladoc.excludedProjects()) return
112                 p.tasks.withType(ScalaDoc) { ScalaDoc scaladoc -> if (scaladoc.enabledscaladocs << scaladoc }
113             }
114             scaladocs = scaladocs.unique()
115 
116             ScalaDoc aggregateScaladocs = project.tasks.findByName(AGGREGATE_SCALADOCS_TASK_NAME)
117             Jar aggregateScaladocsJar = project.tasks.findByName(AGGREGATE_SCALADOCS_JAR_TASK_NAME)
118 
119             if (scaladocs) {
120                 aggregateScaladocs.configure task ->
121                     task.enabled true
122                     task.dependsOn scaladocs
123                     task.source scaladocs.source
124                     task.classpath = project.files(scaladocs.classpath)
125 
126                     effectiveConfig.scaladoc.applyTo(task)
127                     // task.options.footer = "Copyright &copy; ${effectiveConfig.info.copyrightYear} ${effectiveConfig.info.authors.join(', ')}. All rights reserved."
128                 }
129                 aggregateScaladocsJar.configure {
130                     enabled true
131                     from aggregateScaladocs.destinationDir
132                 }
133             }
134         }
135     }
136 
137     private void configureProject(Project project) {
138         if (hasBeenVisited(project)) {
139             return
140         }
141         setVisited(project, true)
142 
143         BasePlugin.applyIfMissing(project)
144 
145         project.afterEvaluate {
146             ProjectConfigurationExtension effectiveConfig = resolveEffectiveConfig(project)
147             setEnabled(effectiveConfig.scaladoc.enabled)
148 
149             if (!enabled) {
150                 return
151             }
152 
153             project.plugins.withType(ScalaBasePlugin) {
154                 Task scaladoc = configureScaladocTask(project)
155                 effectiveConfig.scaladoc.scaladocTasks() << scaladoc
156 
157                 Task scaladocJar = createScaladocJarTask(project, scaladoc)
158                 project.tasks.findByName(org.gradle.api.plugins.BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(scaladocJar)
159                 effectiveConfig.scaladoc.scaladocJarTasks() << scaladocJar
160 
161                 effectiveConfig.scaladoc.projects() << project
162 
163                 project.tasks.withType(ScalaDoc) { task ->
164                     effectiveConfig.scaladoc.applyTo(task)
165                     // task.scalaDocOptions.footer = "Copyright &copy; ${effectiveConfig.info.copyrightYear} ${effectiveConfig.info.getAuthors().join(', ')}. All rights reserved."
166                 }
167             }
168         }
169     }
170 
171     private Task configureScaladocTask(Project project) {
172         String taskName = SCALADOC_TASK_NAME
173 
174         ScalaDoc scaladocTask = project.tasks.findByName(taskName)
175         Task classesTask = project.tasks.findByName('classes')
176 
177         if (classesTask && !scaladocTask) {
178             scaladocTask = project.tasks.create(taskName, ScalaDoc) {
179                 dependsOn classesTask
180                 group JavaBasePlugin.DOCUMENTATION_GROUP
181                 description 'Generates Scaladoc API documentation'
182                 source project.sourceSets.main.allSource
183                 destinationDir project.file("${project.buildDir}/docs/scaladoc")
184             }
185         }
186 
187         ProjectConfigurationExtension effectiveConfig = resolveEffectiveConfig(project)
188         scaladocTask.configure {
189             include(effectiveConfig.scaladoc.includes)
190             exclude(effectiveConfig.scaladoc.excludes)
191         }
192 
193         scaladocTask
194     }
195 
196     private Task createScaladocJarTask(Project project, Task scaladoc) {
197         String taskName = SCALADOC_JAR_TASK_NAME
198 
199         Task scaladocJarTask = project.tasks.findByName(taskName)
200 
201         if (!scaladocJarTask) {
202             scaladocJarTask = project.tasks.create(taskName, Jar) {
203                 dependsOn scaladoc
204                 group JavaBasePlugin.DOCUMENTATION_GROUP
205                 description 'An archive of the Scaladoc API docs'
206                 classifier 'scaladoc'
207                 from scaladoc.destinationDir
208             }
209         }
210 
211         if (project.plugins.findPlugin(MavenPublishPlugin)) {
212             project.publishing {
213                 publications {
214                     main(MavenPublication) {
215                         artifact scaladocJarTask
216                     }
217                 }
218             }
219         }
220 
221         scaladocJarTask
222     }
223 
224     private List<Task> createAggregateScaladocsTask(Project project) {
225         ScalaDoc aggregateScaladocs = project.tasks.create(AGGREGATE_SCALADOCS_TASK_NAME, ScalaDoc) {
226             enabled false
227             group JavaBasePlugin.DOCUMENTATION_GROUP
228             description 'Aggregates ScalaDoc API docs for all projects.'
229             destinationDir project.file("${project.buildDir}/docs/scaladoc")
230         }
231 
232         Jar aggregateScaladocsJar = project.tasks.create(AGGREGATE_SCALADOCS_JAR_TASK_NAME, Jar) {
233             enabled false
234             dependsOn aggregateScaladocs
235             group JavaBasePlugin.DOCUMENTATION_GROUP
236             description 'An archive of the aggregate ScalaDoc API docs'
237             classifier 'scaladoc'
238         }
239 
240         [aggregateScaladocs, aggregateScaladocsJar]
241     }
242 }