diff -r 3ccb29f83309 -r 91a3ad3b1b9c buildSrc/src/main/kotlin/SourceLicenseChecker.kt --- a/buildSrc/src/main/kotlin/SourceLicenseChecker.kt Wed Oct 06 16:05:47 2021 -0400 +++ b/buildSrc/src/main/kotlin/SourceLicenseChecker.kt Tue Nov 29 14:05:44 2022 -0400 @@ -21,48 +21,145 @@ */ package com.geekorum.build +import com.android.build.api.dsl.AndroidSourceSet +import com.android.build.gradle.BaseExtension +import com.android.build.gradle.DynamicFeaturePlugin import com.hierynomus.gradle.license.LicenseBasePlugin import com.hierynomus.gradle.license.tasks.LicenseCheck import com.hierynomus.gradle.license.tasks.LicenseFormat +import nl.javadude.gradle.plugins.license.License import nl.javadude.gradle.plugins.license.LicenseExtension import nl.javadude.gradle.plugins.license.LicensePlugin +import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.invoke -import org.gradle.kotlin.dsl.named +import org.gradle.api.file.FileTree +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.* +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper +import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper +import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper +import java.util.* -internal fun Project.configureSourceLicenseChecker(): Unit { +internal fun Project.configureSourceLicenseChecker() { apply() configure { header = file("$rootDir/config/license/header.txt") - // ignore failures for now until we set the final license - ignoreFailures = true + mapping("java", "SLASHSTAR_STYLE") + mapping("kt", "SLASHSTAR_STYLE") excludes(listOf("**/*.webp", "**/*.png")) } - tasks { - val checkKotlinFilesLicenseTask = register("checkKotlinFilesLicense", LicenseCheck::class.java) { - source = fileTree("src").apply { - include("**/*.kt") - } - } + // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin + // Copied the code to configure it + plugins.withType(DynamicFeaturePlugin::class.java) { + configureAndroid() + } + // make the license tasks looks for kotlin files in an Android project + plugins.withType(KotlinAndroidPluginWrapper::class.java) { + configureKotlinAndroid() + } + + // make the license tasks for kotlin js project + plugins.withType(KotlinJsPluginWrapper::class.java) { + configureKotlin() + } + + plugins.withType(KotlinMultiplatformPluginWrapper::class.java) { + configureKotlin() + } +} - val formatKotlinFilesLicenseTask = register("formatKotlinFilesLicense", LicenseFormat::class.java) { - source = fileTree("src").apply { - include("**/*.kt") - } +@OptIn(ExperimentalStdlibApi::class) +private fun Project.configureKotlin() { + val kotlin = the() + val taskInfix = "" + kotlin.sourceSets.configureEach { + val kotlinSource = this + val sourceSetTaskName = + "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}" + logger.info("Adding $sourceSetTaskName task for sourceSet ${kotlinSource.name}") + if (sourceSetTaskName in tasks.names) { + // tasks may have already been added by configuration for the Android plugin + logger.info("Tasks $sourceSetTaskName already exists. Skip") + return@configureEach } - - named(LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()) { - dependsOn(checkKotlinFilesLicenseTask) + tasks.register(sourceSetTaskName, LicenseCheck::class.java) { + source(kotlinSource.kotlin) } - - named(LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()) { - dependsOn(formatKotlinFilesLicenseTask) + val sourceSetFormatTaskName = + "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}" + tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java) { + source(kotlinSource.kotlin) } } } + +@OptIn(ExperimentalStdlibApi::class) +private fun Project.configureKotlinAndroid() { + val kotlin = the() + val android = the() + val taskInfix = "Android" + android.sourceSets.configureEach { + val kotlinSource = kotlin.sourceSets[name] + logger.info("Adding kotlin sources from sourceSet $name to License plugin tasks") + val sourceSetTaskName = + "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}" + tasks.named(sourceSetTaskName, LicenseCheck::class.java) { + source(kotlinSource.kotlin, manifest.srcFile) + } + val sourceSetFormatTaskName = + "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize(Locale.ROOT)}" + tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java) { + source(kotlinSource.kotlin, manifest.srcFile) + } + } +} + + +private fun Project.configureAndroid() { + val android = the() + configureSourceSetRule(android.sourceSets, "Android") { ss -> + @Suppress("DEPRECATION") + when (ss) { + // the dsl.AndroidSourceSet don't expose any getter, so we still need to cast it + is com.android.build.gradle.api.AndroidSourceSet -> { + ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) + } + else -> fileTree() + } + } +} + +/** + * Dynamically create a task for each sourceSet, and register with check + */ +@Suppress("DefaultLocale") +private fun Project.configureSourceSetRule(androidSourceSetContainer: NamedDomainObjectContainer, + taskInfix: String, sourceSetSources: (AndroidSourceSet) -> FileTree) { + // This follows the other check task pattern + androidSourceSetContainer.configureEach { + val sourceSetTaskName = "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" + logger.info("Adding $sourceSetTaskName task for sourceSet $name") + + val checkTask = tasks.register(sourceSetTaskName, LicenseCheck::class.java) + configureForSourceSet(this, checkTask, sourceSetSources) + + // Add independent license task, which will perform format + val sourceSetFormatTaskName = "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}" + val formatTask = tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java) + configureForSourceSet(this, formatTask, sourceSetSources) + } +} + +private fun configureForSourceSet(sourceSet: AndroidSourceSet, task: TaskProvider, sourceSetSources: (AndroidSourceSet) -> FileTree) { + task.configure { + // Explicitly set description + description = "Scanning license on ${sourceSet.name} files" + + // Default to all source files from SourceSet + source = sourceSetSources(sourceSet) + } +}