diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt index b3d19ef68f..c30cb2583d 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt @@ -12,10 +12,13 @@ import kotlin.io.path.relativeTo /** * This task should be FAST and SAFE! Because it is being run during IDE import. */ -abstract class GenerateResClassTask : DefaultTask() { +internal abstract class GenerateResClassTask : DefaultTask() { @get:Input abstract val packageName: Property + @get:Input + abstract val shouldGenerateResClass: Property + @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) abstract val resDir: Property @@ -26,32 +29,37 @@ abstract class GenerateResClassTask : DefaultTask() { @TaskAction fun generate() { try { - val rootResDir = resDir.get() - logger.info("Generate resources for $rootResDir") + val kotlinDir = codeDir.get().asFile + logger.info("Clean directory $kotlinDir") + kotlinDir.deleteRecursively() + kotlinDir.mkdirs() - //get first level dirs - val dirs = rootResDir.listNotHiddenFiles() + if (shouldGenerateResClass.get()) { + val rootResDir = resDir.get() + logger.info("Generate resources for $rootResDir") - dirs.forEach { f -> - if (!f.isDirectory) { - error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") - } - } + //get first level dirs + val dirs = rootResDir.listNotHiddenFiles() - //type -> id -> resource item - val resources: Map>> = dirs - .flatMap { dir -> - dir.listNotHiddenFiles() - .mapNotNull { it.fileToResourceItems(rootResDir.toPath()) } - .flatten() + dirs.forEach { f -> + if (!f.isDirectory) { + error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") + } } - .groupBy { it.type } - .mapValues { (_, items) -> items.groupBy { it.name } } - val kotlinDir = codeDir.get().asFile - kotlinDir.deleteRecursively() - kotlinDir.mkdirs() - getResFileSpec(resources, packageName.get()).writeTo(kotlinDir) + //type -> id -> resource item + val resources: Map>> = dirs + .flatMap { dir -> + dir.listNotHiddenFiles() + .mapNotNull { it.fileToResourceItems(rootResDir.toPath()) } + .flatten() + } + .groupBy { it.type } + .mapValues { (_, items) -> items.groupBy { it.name } } + getResFileSpec(resources, packageName.get()).writeTo(kotlinDir) + } else { + logger.info("Generation Res class is disabled") + } } catch (e: Exception) { //message must contain two ':' symbols to be parsed by IDE UI! logger.error("e: GenerateResClassTask was failed:", e) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt index b0cb6ae8a8..9378ac67f9 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesGenerator.kt @@ -54,7 +54,7 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, fun buildDir(path: String) = layout.dir(layout.buildDirectory.map { File(it.asFile, path) }) //lazy check a dependency on the Resources library - val shouldGenerateResourceAccessors: Provider = provider { + val shouldGenerateResClass: Provider = provider { if (ComposeProperties.alwaysGenerateResourceAccessors(project).get()) { true } else { @@ -72,9 +72,9 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, GenerateResClassTask::class.java ) { it.packageName.set(packageName) + it.shouldGenerateResClass.set(shouldGenerateResClass) it.resDir.set(commonComposeResources) it.codeDir.set(buildDir("$RES_GEN_DIR/kotlin")) - it.onlyIf { shouldGenerateResourceAccessors.get() } } //register generated source set @@ -93,7 +93,7 @@ private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, configureAndroidResources( commonComposeResources, buildDir("$RES_GEN_DIR/androidFonts").map { it.asFile }, - shouldGenerateResourceAccessors + shouldGenerateResClass ) } } diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt index 73851f43ab..aef995819d 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt @@ -117,6 +117,56 @@ class ResourcesTest : GradlePluginTestBase() { } } + @Test + fun testUpToDateChecks(): Unit = with(testProject("misc/commonResources")) { + gradle("prepareKotlinIdeaImport").checks { + check.taskSuccessful(":generateComposeResClass") + assert(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + } + gradle("prepareKotlinIdeaImport").checks { + check.taskUpToDate(":generateComposeResClass") + } + + modifyText("build.gradle.kts") { str -> + str.replace( + "implementation(compose.components.resources)", + "//implementation(compose.components.resources)" + ) + } + gradle("prepareKotlinIdeaImport").checks { + check.taskSuccessful(":generateComposeResClass") + assert(!file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + } + + gradle("prepareKotlinIdeaImport", "-Pcompose.resources.always.generate.accessors=true").checks { + check.taskSuccessful(":generateComposeResClass") + assert(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + } + + modifyText("build.gradle.kts") { str -> + str.replace( + "//implementation(compose.components.resources)", + "implementation(compose.components.resources)" + ) + } + gradle("prepareKotlinIdeaImport").checks { + check.taskUpToDate(":generateComposeResClass") + assert(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + } + + modifyText("build.gradle.kts") { str -> + str.replace( + "group = \"app.group\"", + "group = \"io.company\"" + ) + } + gradle("prepareKotlinIdeaImport").checks { + check.taskSuccessful(":generateComposeResClass") + assert(!file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + assert(file("build/generated/compose/resourceGenerator/kotlin/io/company/resources_test/generated/resources/Res.kt").exists()) + } + } + @Test fun testEmptyResClass(): Unit = with(testProject("misc/emptyResources")) { gradle("generateComposeResClass").checks { diff --git a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/assertUtils.kt b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/assertUtils.kt index 6be9978bb0..1503c8f083 100644 --- a/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/assertUtils.kt +++ b/gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/utils/assertUtils.kt @@ -57,6 +57,10 @@ internal class BuildResultChecks(private val result: BuildResult) { taskOutcome(task, TaskOutcome.FAILED) } + fun taskUpToDate(task: String) { + taskOutcome(task, TaskOutcome.UP_TO_DATE) + } + fun taskFromCache(task: String) { taskOutcome(task, TaskOutcome.FROM_CACHE) } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts index a72fb6423f..392b9a9efc 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/build.gradle.kts @@ -21,7 +21,6 @@ kotlin { dependencies { implementation(compose.runtime) implementation(compose.material) - @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) } }