package org.jetbrains.compose.resources import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.jetbrains.compose.ComposePlugin import org.jetbrains.compose.desktop.application.internal.ComposeProperties import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import java.io.File internal const val COMPOSE_RESOURCES_DIR = "composeResources" private const val RES_GEN_DIR = "generated/compose/resourceGenerator" private val androidPluginIds = listOf( "com.android.application", "com.android.library" ) internal fun Project.configureComposeResources() { plugins.withId(KOTLIN_MPP_PLUGIN_ID) { configureComposeResources(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) } plugins.withId(KOTLIN_JVM_PLUGIN_ID) { configureComposeResources(SourceSet.MAIN_SOURCE_SET_NAME) } } private fun Project.configureComposeResources(commonSourceSetName: String) { val kotlinExtension = project.extensions.getByType(KotlinProjectExtension::class.java) kotlinExtension.sourceSets.all { sourceSet -> val sourceSetName = sourceSet.name val composeResourcesPath = project.projectDir.resolve("src/$sourceSetName/$COMPOSE_RESOURCES_DIR") sourceSet.resources.srcDirs(composeResourcesPath) if (sourceSetName == commonSourceSetName) { configureResourceGenerator(composeResourcesPath, sourceSet) } } } private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, commonSourceSet: KotlinSourceSet) { val commonComposeResources = provider { commonComposeResourcesDir } val packageName = provider { buildString { val group = project.group.toString().lowercase().asUnderscoredIdentifier() append(group) if (group.isNotEmpty()) append(".") append(project.name.lowercase()) append(".generated.resources") } } fun buildDir(path: String) = layout.dir(layout.buildDirectory.map { File(it.asFile, path) }) //lazy check a dependency on the Resources library val shouldGenerateResClass: Provider = provider { if (ComposeProperties.alwaysGenerateResourceAccessors(project).get()) { true } else { configurations .getByName(commonSourceSet.implementationConfigurationName) .allDependencies.any { dep -> val depStringNotation = dep.let { "${it.group}:${it.name}:${it.version}" } depStringNotation == ComposePlugin.CommonComponentsDependencies.resources } } } val genTask = tasks.register( "generateComposeResClass", GenerateResClassTask::class.java ) { it.packageName.set(packageName) it.shouldGenerateResClass.set(shouldGenerateResClass) it.resDir.set(commonComposeResources) it.codeDir.set(buildDir("$RES_GEN_DIR/kotlin")) } //register generated source set commonSourceSet.kotlin.srcDir(genTask.map { it.codeDir }) //setup task execution during IDE import tasks.configureEach { if (it.name == "prepareKotlinIdeaImport") { it.dependsOn(genTask) } } //when applied AGP then configure android resources androidPluginIds.forEach { pluginId -> plugins.withId(pluginId) { configureAndroidResources( commonComposeResources, buildDir("$RES_GEN_DIR/androidFonts").map { it.asFile }, shouldGenerateResClass ) } } }