BasePlugin.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.base
019 
020 import groovy.transform.CompileStatic
021 import org.gradle.BuildAdapter
022 import org.gradle.api.Action
023 import org.gradle.api.GradleException
024 import org.gradle.api.Project
025 import org.gradle.api.Rule
026 import org.gradle.api.invocation.Gradle
027 import org.kordamp.gradle.PluginUtils
028 import org.kordamp.gradle.plugin.AbstractKordampPlugin
029 import org.kordamp.gradle.plugin.base.tasks.EffectiveSettingsTask
030 import org.kordamp.gradle.plugin.base.tasks.ExtensionsTask
031 import org.kordamp.gradle.plugin.base.tasks.GroovyCompilerSettingsTask
032 import org.kordamp.gradle.plugin.base.tasks.JavaCompilerSettingsTask
033 import org.kordamp.gradle.plugin.base.tasks.ListIncludedBuildsTask
034 import org.kordamp.gradle.plugin.base.tasks.ListProjectsTask
035 import org.kordamp.gradle.plugin.base.tasks.PluginsTask
036 import org.kordamp.gradle.plugin.base.tasks.ProjectPropertiesTask
037 import org.kordamp.gradle.plugin.base.tasks.RepositoriesTask
038 import org.kordamp.gradle.plugin.base.tasks.TestSettingsTask
039 
040 /**
041  *
042  @author Andres Almiray
043  @since 0.1.0
044  */
045 @CompileStatic
046 class BasePlugin extends AbstractKordampPlugin {
047     static final String ORG_KORDAMP_GRADLE_BASE_VALIDATE = 'org.kordamp.gradle.base.validate'
048 
049     Project project
050 
051     void apply(Project project) {
052         this.project = project
053 
054         if (hasBeenVisited(project)) {
055             return
056         }
057         setVisited(project, true)
058 
059         if (!project.plugins.findPlugin(org.gradle.api.plugins.BasePlugin)) {
060             project.plugins.apply(org.gradle.api.plugins.BasePlugin)
061         }
062 
063         if (!project.extensions.findByType(ProjectConfigurationExtension)) {
064             project.extensions.create(ProjectConfigurationExtension.CONFIG_NAME, ProjectConfigurationExtension, project)
065         }
066 
067         project.tasks.register('effectiveSettings', EffectiveSettingsTask,
068             new Action<EffectiveSettingsTask>() {
069                 @Override
070                 void execute(EffectiveSettingsTask t) {
071                     t.group = 'Insight'
072                     t.description = "Displays resolved settings for project '$project.name'."
073                 }
074             })
075 
076         project.tasks.register('repositories', RepositoriesTask,
077             new Action<RepositoriesTask>() {
078                 @Override
079                 void execute(RepositoriesTask t) {
080                     t.group = 'Insight'
081                     t.description = "Displays all repositories for project '$project.name'."
082                 }
083             })
084 
085         project.tasks.register('plugins', PluginsTask,
086             new Action<PluginsTask>() {
087                 @Override
088                 void execute(PluginsTask t) {
089                     t.group = 'Insight'
090                     t.description = "Displays all plugins applied to project '$project.name'."
091                 }
092             })
093 
094         project.tasks.register('extensions', ExtensionsTask,
095             new Action<ExtensionsTask>() {
096                 @Override
097                 void execute(ExtensionsTask t) {
098                     t.group = 'Insight'
099                     t.description = "Displays all extensions applied to project '$project.name'."
100                 }
101             })
102 
103         project.tasks.register('projectProperties', ProjectPropertiesTask,
104             new Action<ProjectPropertiesTask>() {
105                 @Override
106                 void execute(ProjectPropertiesTask t) {
107                     t.group = 'Insight'
108                     t.description = "Displays all properties found in project '$project.name'."
109                 }
110             })
111 
112         project.tasks.register('javaCompilerSettings', JavaCompilerSettingsTask,
113             new Action<JavaCompilerSettingsTask>() {
114                 @Override
115                 void execute(JavaCompilerSettingsTask t) {
116                     t.group = 'Insight'
117                     t.description = 'Display Java compiler configuration.'
118                 }
119             })
120 
121         project.tasks.addRule('Pattern: compile<ID>JavaSettings: Displays compiler configuration of a JavaCompile task.', new Action<String>() {
122             @Override
123             void execute(String taskName) {
124                 if (taskName.startsWith('compile') && taskName.endsWith('JavaSettings')) {
125                     String resolvedTaskName = taskName - 'Settings'
126                     project.tasks.register(taskName, JavaCompilerSettingsTask,
127                         new Action<JavaCompilerSettingsTask>() {
128                             @Override
129                             void execute(JavaCompilerSettingsTask t) {
130                                 t.group = 'Insight'
131                                 t.task = resolvedTaskName
132                                 t.description = "Display Java compiler configuration for the ${resolvedTaskName} task."
133                             }
134                         })
135                 }
136             }
137         })
138 
139         project.tasks.register('testSettings', TestSettingsTask,
140             new Action<TestSettingsTask>() {
141                 @Override
142                 void execute(TestSettingsTask t) {
143                     t.group = 'Insight'
144                     t.description = 'Display test task configuration.'
145                 }
146             })
147 
148         project.tasks.addRule('Pattern: <ID>TestSettings: Displays configuration of a Test task.', new Action<String>() {
149             @Override
150             void execute(String taskName) {
151                 if (taskName.endsWith('TestSettings')) {
152                     String resolvedTaskName = taskName - 'Settings'
153                     project.tasks.register(taskName, TestSettingsTask,
154                         new Action<TestSettingsTask>() {
155                             @Override
156                             void execute(TestSettingsTask t) {
157                                 t.group = 'Insight'
158                                 t.task = resolvedTaskName
159                                 t.description = "Display configuration for the ${resolvedTaskName} task."
160                             }
161                         })
162                 }
163             }
164         })
165 
166         if (isRootProject(project)) {
167             project.tasks.register('listProjects', ListProjectsTask,
168                 new Action<ListProjectsTask>() {
169                     @Override
170                     void execute(ListProjectsTask t) {
171                         t.group = 'Insight'
172                         t.description = 'List all projects.'
173                     }
174                 })
175 
176             project.tasks.register('listIncludedBuilds', ListIncludedBuildsTask,
177                 new Action<ListIncludedBuildsTask>() {
178                     @Override
179                     void execute(ListIncludedBuildsTask t) {
180                         t.group = 'Insight'
181                         t.description = 'List all included builds.'
182                     }
183                 })
184 
185             project.gradle.addBuildListener(new BuildAdapter() {
186                 @Override
187                 void projectsEvaluated(Gradle gradle) {
188                     project.subprojects.each Project subproject ->
189                         PluginUtils.resolveEffectiveConfig(subproject).rootReady()
190                     }
191                     PluginUtils.resolveEffectiveConfig(project).rootReady()
192                 }
193             })
194         }
195 
196         project.afterEvaluate {
197             if (project.plugins.findPlugin('groovy')) {
198                 project.tasks.register('groovyCompilerSettings', GroovyCompilerSettingsTask,
199                     new Action<GroovyCompilerSettingsTask>() {
200                         @Override
201                         void execute(GroovyCompilerSettingsTask t) {
202                             t.group = 'Insight'
203                             t.description = 'Display Groovy compiler configuration.'
204                         }
205                     })
206 
207                 project.tasks.addRule('Pattern: compile<ID>GroovySettings: Displays compiler configuration of a GroovyCompile task.', new Action<String>() {
208                     @Override
209                     void execute(String taskName) {
210                         if (taskName.startsWith('compile') && taskName.endsWith('GroovySettings')) {
211                             String resolvedTaskName = taskName - 'Settings'
212                             project.tasks.register(taskName, GroovyCompilerSettingsTask,
213                                 new Action<GroovyCompilerSettingsTask>() {
214                                     @Override
215                                     void execute(GroovyCompilerSettingsTask t) {
216                                         t.group = 'Insight'
217                                         t.task = resolvedTaskName
218                                         t.description = "Display Groovy compiler configuration for the ${resolvedTaskName} task."
219                                     }
220                                 })
221                         }
222                     }
223                 })
224             }
225 
226             ProjectConfigurationExtension rootExtension = project.rootProject.extensions.findByType(ProjectConfigurationExtension)
227             ProjectConfigurationExtension extension = project.extensions.findByType(ProjectConfigurationExtension)
228             extension.normalize()
229 
230             boolean validate = PluginUtils.checkFlag(ORG_KORDAMP_GRADLE_BASE_VALIDATE, true)
231 
232             List<String> errors = []
233             if (isRootProject(project)) {
234                 ProjectConfigurationExtension merged = extension.merge(rootExtension)
235                 if (validateerrors.addAll(merged.validate())
236                 project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, merged).ready()
237             else {
238                 if (rootExtension) {
239                     ProjectConfigurationExtension merged = extension.merge(rootExtension)
240                     if (validateerrors.addAll(merged.validate())
241                     project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, merged).ready()
242                 else {
243                     if (validateerrors.addAll(extension.validate())
244                     extension.postMerge()
245                     project.extensions.create(ProjectConfigurationExtension.EFFECTIVE_CONFIG_NAME, ProjectConfigurationExtension, extension).ready()
246                 }
247             }
248 
249             if (validate && errors) {
250                 errors.each project.logger.error(it) }
251                 throw new GradleException("Project ${project.name} has not been properly configured")
252             }
253         }
254     }
255 
256     static void applyIfMissing(Project project) {
257         if (!project.plugins.findPlugin(BasePlugin)) {
258             project.plugins.apply(BasePlugin)
259         }
260     }
261 
262     static boolean isRootProject(Project project) {
263         project == project.rootProject
264     }
265 }