build: update SourceLicenseChecker for AGP 9.x default tip main
authorDa Risk <da_risk@geekorum.com>
Tue, 05 May 2026 14:55:56 -0400
changeset 119 684356cd6a7d
parent 118 ceee12802fbc
build: update SourceLicenseChecker for AGP 9.x
buildSrc/src/main/kotlin/SourceLicenseChecker.kt
--- a/buildSrc/src/main/kotlin/SourceLicenseChecker.kt	Mon May 04 23:53:58 2026 -0400
+++ b/buildSrc/src/main/kotlin/SourceLicenseChecker.kt	Tue May 05 14:55:56 2026 -0400
@@ -22,6 +22,7 @@
 package com.geekorum.build
 
 import com.android.build.api.dsl.AndroidSourceSet
+import com.android.build.api.dsl.CommonExtension
 import com.android.build.gradle.BaseExtension
 import com.android.build.gradle.DynamicFeaturePlugin
 import com.android.build.gradle.TestPlugin
@@ -40,6 +41,7 @@
 import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
 import org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper
 import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
+import java.io.File
 import java.util.Locale
 
 internal fun Project.configureSourceLicenseChecker() {
@@ -48,39 +50,44 @@
     configure<LicenseExtension> {
         header = file("$rootDir/config/license/header.txt")
         mapping("java", "SLASHSTAR_STYLE")
+        mapping("json", "SLASHSTAR_STYLE")
         mapping("kt", "SLASHSTAR_STYLE")
 
-        excludes(listOf("**/*.webp", "**/*.png"))
+        excludes(listOf("**/*.webp", "**/*.png", "**/*.jpeg", "**/*.jpg"))
     }
 
     // the LicensePlugin doesn't configure itself properly on DynamicFeaturePlugin
     // Copied the code to configure it
-    plugins.withType(DynamicFeaturePlugin::class.java) {
+    plugins.withType<DynamicFeaturePlugin> {
         configureAndroid()
     }
 
     // the LicensePlugin doesn't configure itself properly on Android Test plugin
     // Copied the code to configure it
-    plugins.withType(TestPlugin::class.java) {
+    plugins.withType<TestPlugin> {
         configureAndroid()
     }
 
     // make the license tasks looks for kotlin files in an Android project
-    plugins.withType(KotlinAndroidPluginWrapper::class.java) {
+    plugins.withType<KotlinAndroidPluginWrapper> {
         configureKotlinAndroid()
     }
 
     // make the license tasks for kotlin js project
-    plugins.withType(KotlinJsPluginWrapper::class.java) {
+    plugins.withType<KotlinJsPluginWrapper> {
         configureKotlin()
     }
 
-    plugins.withType(KotlinMultiplatformPluginWrapper::class.java) {
+    plugins.withType<KotlinMultiplatformPluginWrapper> {
         configureKotlin()
+        configureComposeResources()
+    }
+
+    tasks.withType<License>().configureEach {
+        notCompatibleWithConfigurationCache("License tasks calls getProject() at execution time")
     }
 }
 
-@OptIn(ExperimentalStdlibApi::class)
 private fun Project.configureKotlin() {
     val kotlin = the<KotlinProjectExtension>()
     val taskInfix = ""
@@ -128,6 +135,48 @@
     }
 }
 
+private fun Project.configureComposeResources() {
+    val kotlin = the<KotlinProjectExtension>()
+    val taskInfix = "ComposeResources"
+    kotlin.sourceSets.configureEach {
+        val kotlinSource = this
+        val sourceSetTaskName =
+            "${LicenseBasePlugin.getLICENSE_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
+        if (name.startsWith("generated")) {
+            logger.info("Skip sourceSet $name because it's generated code")
+            return@configureEach
+        }
+        val resourceDir = kotlinSource.resources.sourceDirectories.files.first()
+        val composeResourceDir = File(resourceDir, "../composeResources")
+
+        val configureLicenseCheckTaskLambda: LicenseCheck.() -> Unit = {
+            source(composeResourceDir)
+        }
+        if (sourceSetTaskName in tasks.names) {
+            // tasks may have already been added by configuration for the Android plugin
+            logger.info("Tasks $sourceSetTaskName already exists. configure it")
+            tasks.named(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda)
+        } else {
+            logger.info("Adding ${project.name}:$sourceSetTaskName task for sourceSet ${kotlinSource.name}")
+            tasks.register(sourceSetTaskName, LicenseCheck::class.java, configureLicenseCheckTaskLambda)
+        }
+
+        val configureLicenseFormatTaskLambda: LicenseFormat.() -> Unit = {
+            source(composeResourceDir)
+        }
+        val sourceSetFormatTaskName =
+            "${LicenseBasePlugin.getFORMAT_TASK_BASE_NAME()}${taskInfix}${name.capitalize()}"
+        if (sourceSetFormatTaskName in tasks.names) {
+            // tasks may have already been added by configuration for the Android plugin
+            logger.info("Tasks $sourceSetFormatTaskName already exists. configure it")
+            tasks.named(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda)
+        } else {
+            logger.info("Adding ${project.name}:$sourceSetFormatTaskName task for sourceSet ${kotlinSource.name}")
+            tasks.register(sourceSetFormatTaskName, LicenseFormat::class.java, configureLicenseFormatTaskLambda)
+        }
+    }
+}
+
 @OptIn(ExperimentalStdlibApi::class)
 private fun Project.configureKotlinAndroid() {
     val kotlin = the<KotlinProjectExtension>()
@@ -159,13 +208,20 @@
 
 
 private fun Project.configureAndroid() {
-    val android = the<BaseExtension>()
+    val android = the<CommonExtension>()
     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)
+                val kotlinFileTrees  = ss.kotlin.directories.foldIndexed(fileTree() as FileTree) { index, acc, n ->
+                    if (index == 0) { // skip first as it's an empty tree created for typing
+                        fileTree(n)
+                    } else {
+                        acc + fileTree(n)
+                    }
+                }
+                ss.java.getSourceFiles() + ss.res.getSourceFiles() + fileTree(ss.manifest.srcFile) + kotlinFileTrees
             }
             else -> fileTree()
         }