buildSrc/src/main/kotlin/SourceLicenseChecker.kt
changeset 19 91a3ad3b1b9c
parent 10 9aad34f43f71
child 20 5d8a0555733d
equal deleted inserted replaced
18:3ccb29f83309 19:91a3ad3b1b9c
    19  * You should have received a copy of the GNU General Public License
    19  * You should have received a copy of the GNU General Public License
    20  * along with Geekdroid.  If not, see <http://www.gnu.org/licenses/>.
    20  * along with Geekdroid.  If not, see <http://www.gnu.org/licenses/>.
    21  */
    21  */
    22 package com.geekorum.build
    22 package com.geekorum.build
    23 
    23 
       
    24 import com.android.build.api.dsl.AndroidSourceSet
       
    25 import com.android.build.gradle.BaseExtension
       
    26 import com.android.build.gradle.DynamicFeaturePlugin
    24 import com.hierynomus.gradle.license.LicenseBasePlugin
    27 import com.hierynomus.gradle.license.LicenseBasePlugin
    25 import com.hierynomus.gradle.license.tasks.LicenseCheck
    28 import com.hierynomus.gradle.license.tasks.LicenseCheck
    26 import com.hierynomus.gradle.license.tasks.LicenseFormat
    29 import com.hierynomus.gradle.license.tasks.LicenseFormat
       
    30 import nl.javadude.gradle.plugins.license.License
    27 import nl.javadude.gradle.plugins.license.LicenseExtension
    31 import nl.javadude.gradle.plugins.license.LicenseExtension
    28 import nl.javadude.gradle.plugins.license.LicensePlugin
    32 import nl.javadude.gradle.plugins.license.LicensePlugin
       
    33 import org.gradle.api.NamedDomainObjectContainer
    29 import org.gradle.api.Project
    34 import org.gradle.api.Project
    30 import org.gradle.api.Task
    35 import org.gradle.api.file.FileTree
    31 import org.gradle.kotlin.dsl.apply
    36 import org.gradle.api.tasks.TaskProvider
    32 import org.gradle.kotlin.dsl.configure
    37 import org.gradle.kotlin.dsl.*
    33 import org.gradle.kotlin.dsl.invoke
    38 import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
    34 import org.gradle.kotlin.dsl.named
    39 import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
       
    40 import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper
       
    41 import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
       
    42 import java.util.*
    35 
    43 
    36 internal fun Project.configureSourceLicenseChecker(): Unit {
    44 internal fun Project.configureSourceLicenseChecker() {
    37     apply<LicensePlugin>()
    45     apply<LicensePlugin>()
    38 
    46 
    39     configure<LicenseExtension> {
    47     configure<LicenseExtension> {
    40         header = file("$rootDir/config/license/header.txt")
    48         header = file("$rootDir/config/license/header.txt")
    41         // ignore failures for now until we set the final license
    49         mapping("java", "SLASHSTAR_STYLE")
    42         ignoreFailures = true
    50         mapping("kt", "SLASHSTAR_STYLE")
    43 
    51 
    44         excludes(listOf("**/*.webp", "**/*.png"))
    52         excludes(listOf("**/*.webp", "**/*.png"))
    45     }
    53     }
    46 
    54 
    47     tasks {
    55     // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin
    48         val checkKotlinFilesLicenseTask = register("checkKotlinFilesLicense", LicenseCheck::class.java) {
    56     // Copied the code to configure it
    49             source = fileTree("src").apply {
    57     plugins.withType(DynamicFeaturePlugin::class.java) {
    50                 include("**/*.kt")
    58         configureAndroid()
    51             }
    59     }
       
    60     // make the license tasks looks for kotlin files in an Android project
       
    61     plugins.withType(KotlinAndroidPluginWrapper::class.java) {
       
    62         configureKotlinAndroid()
       
    63     }
       
    64 
       
    65     // make the license tasks for kotlin js project
       
    66     plugins.withType(KotlinJsPluginWrapper::class.java) {
       
    67         configureKotlin()
       
    68     }
       
    69 
       
    70     plugins.withType(KotlinMultiplatformPluginWrapper::class.java) {
       
    71         configureKotlin()
       
    72     }
       
    73 }
       
    74 
       
    75 @OptIn(ExperimentalStdlibApi::class)
       
    76 private fun Project.configureKotlin() {
       
    77     val kotlin = the<KotlinProjectExtension>()
       
    78     val taskInfix = ""
       
    79     kotlin.sourceSets.configureEach {
       
    80         val kotlinSource = this
       
    81         val sourceSetTaskName =
       
    82             "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
    83         logger.info("Adding $sourceSetTaskName task for sourceSet ${kotlinSource.name}")
       
    84         if (sourceSetTaskName in tasks.names) {
       
    85             // tasks may have already been added by configuration for the Android plugin
       
    86             logger.info("Tasks $sourceSetTaskName already exists. Skip")
       
    87             return@configureEach
    52         }
    88         }
    53 
    89         tasks.register(sourceSetTaskName, LicenseCheck::class.java) {
    54         val formatKotlinFilesLicenseTask = register("formatKotlinFilesLicense", LicenseFormat::class.java) {
    90             source(kotlinSource.kotlin)
    55             source = fileTree("src").apply {
       
    56                 include("**/*.kt")
       
    57             }
       
    58         }
    91         }
    59 
    92         val sourceSetFormatTaskName =
    60         named<Task>(LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()) {
    93             "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
    61             dependsOn(checkKotlinFilesLicenseTask)
    94         tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java) {
    62         }
    95             source(kotlinSource.kotlin)
    63 
       
    64         named<Task>(LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()) {
       
    65             dependsOn(formatKotlinFilesLicenseTask)
       
    66         }
    96         }
    67     }
    97     }
    68 }
    98 }
       
    99 
       
   100 @OptIn(ExperimentalStdlibApi::class)
       
   101 private fun Project.configureKotlinAndroid() {
       
   102     val kotlin = the<KotlinProjectExtension>()
       
   103     val android = the<BaseExtension>()
       
   104     val taskInfix = "Android"
       
   105     android.sourceSets.configureEach {
       
   106         val kotlinSource = kotlin.sourceSets[name]
       
   107         logger.info("Adding kotlin sources from sourceSet $name to License plugin tasks")
       
   108         val sourceSetTaskName =
       
   109             "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
   110         tasks.named(sourceSetTaskName, LicenseCheck::class.java) {
       
   111             source(kotlinSource.kotlin, manifest.srcFile)
       
   112         }
       
   113         val sourceSetFormatTaskName =
       
   114             "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}"
       
   115         tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java) {
       
   116             source(kotlinSource.kotlin, manifest.srcFile)
       
   117         }
       
   118     }
       
   119 }
       
   120 
       
   121 
       
   122 private fun Project.configureAndroid() {
       
   123     val android = the<BaseExtension>()
       
   124     configureSourceSetRule(android.sourceSets, "Android") { ss ->
       
   125         @Suppress("DEPRECATION")
       
   126         when (ss) {
       
   127             // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it
       
   128             is com.android.build.gradle.api.AndroidSourceSet -> {
       
   129         ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile)
       
   130             }
       
   131             else -> fileTree()
       
   132         }
       
   133     }
       
   134 }
       
   135 
       
   136 /**
       
   137  * Dynamically create a task for each sourceSet, and register with check
       
   138  */
       
   139 @Suppress("DefaultLocale")
       
   140 private fun Project.configureSourceSetRule(androidSourceSetContainer: NamedDomainObjectContainer<out AndroidSourceSet>,
       
   141                                            taskInfix: String, sourceSetSources: (AndroidSourceSet) -> FileTree) {
       
   142     // This follows the other check task pattern
       
   143     androidSourceSetContainer.configureEach {
       
   144         val sourceSetTaskName = "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
       
   145         logger.info("Adding $sourceSetTaskName task for sourceSet $name")
       
   146 
       
   147         val checkTask = tasks.register(sourceSetTaskName, LicenseCheck::class.java)
       
   148         configureForSourceSet(this, checkTask, sourceSetSources)
       
   149 
       
   150         // Add independent license task, which will perform format
       
   151         val sourceSetFormatTaskName = "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
       
   152         val formatTask = tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java)
       
   153         configureForSourceSet(this, formatTask, sourceSetSources)
       
   154     }
       
   155 }
       
   156 
       
   157 private fun configureForSourceSet(sourceSet: AndroidSourceSet, task: TaskProvider<out License>, sourceSetSources: (AndroidSourceSet) -> FileTree) {
       
   158     task.configure {
       
   159         // Explicitly set description
       
   160         description = "Scanning license on ${sourceSet.name} files"
       
   161 
       
   162         // Default to all source files from SourceSet
       
   163         source = sourceSetSources(sourceSet)
       
   164     }
       
   165 }