Skip to content

Commit

Permalink
Introduce top level composeResources dir (#4127)
Browse files Browse the repository at this point in the history
  • Loading branch information
terrakok authored Jan 19, 2024
1 parent ae1dca8 commit 747aab0
Show file tree
Hide file tree
Showing 26 changed files with 107 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import components.resources.demo.generated.resources.Res
import components.resources.demo.shared.generated.resources.Res

@Composable
fun FileRes(paddingValues: PaddingValues) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import components.resources.demo.generated.resources.Res
import components.resources.demo.shared.generated.resources.Res
import org.jetbrains.compose.resources.Font

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import components.resources.demo.generated.resources.Res
import components.resources.demo.shared.generated.resources.Res
import org.jetbrains.compose.resources.imageResource
import org.jetbrains.compose.resources.vectorResource
import org.jetbrains.compose.resources.painterResource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import components.resources.demo.generated.resources.Res
import components.resources.demo.shared.generated.resources.Res
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.resources.stringArrayResource
import org.jetbrains.compose.resources.readResourceBytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import org.jetbrains.compose.internal.mppExtOrNull
import org.jetbrains.compose.internal.service.ConfigurationProblemReporterService
import org.jetbrains.compose.internal.service.GradlePropertySnapshotService
import org.jetbrains.compose.internal.utils.currentTarget
import org.jetbrains.compose.resources.configureResourceGenerator
import org.jetbrains.compose.resources.configureComposeResources
import org.jetbrains.compose.resources.ios.configureSyncTask
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
Expand Down Expand Up @@ -65,7 +65,7 @@ abstract class ComposePlugin : Plugin<Project> {
project.plugins.apply(ComposeCompilerKotlinSupportPlugin::class.java)
project.configureNativeCompilerCaching()

project.configureResourceGenerator()
project.configureComposeResources()

project.afterEvaluate {
configureDesktop(project, desktopExtension)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,86 @@ package org.jetbrains.compose.resources

import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.ComposePlugin
import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.compose.desktop.application.internal.ComposeProperties
import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
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"

internal fun Project.configureResourceGenerator() {
internal fun Project.configureComposeResources() {
pluginManager.withPlugin(KOTLIN_MPP_PLUGIN_ID) {
val kotlinExtension = project.extensions.getByType(KotlinProjectExtension::class.java)
val commonSourceSet = kotlinExtension.sourceSets.findByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) ?: return@withPlugin
val commonResourcesDir = provider { commonSourceSet.resources.sourceDirectories.first() }

val packageName = provider {
buildString {
val group = project.group.toString().asUnderscoredIdentifier()
append(group)
if (group.isNotEmpty()) append(".")
append("generated.resources")
val kotlinExtension = project.extensions.getByType(KotlinMultiplatformExtension::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 == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) {
configureResourceGenerator(composeResourcesPath, sourceSet)
}
}
}
}

fun buildDir(path: String) = layout.dir(layout.buildDirectory.map { File(it.asFile, path) })
private fun Project.configureResourceGenerator(commonComposeResourcesDir: File, commonSourceSet: KotlinSourceSet) {
val commonComposeResources = provider { commonComposeResourcesDir }
val packageName = provider {
buildString {
val group = project.group.toString().asUnderscoredIdentifier()
append(group)
if (group.isNotEmpty()) append(".")
append(project.name.lowercase())
append(".generated.resources")
}
}

val resDir = layout.dir(commonResourcesDir.map { it.resolve(COMPOSE_RESOURCES_DIR) })
fun buildDir(path: String) = layout.dir(layout.buildDirectory.map { File(it.asFile, path) })

//lazy check a dependency on the Resources library
val shouldGenerateResourceAccessors: Provider<Boolean> = provider {
if (ComposeProperties.alwaysGenerateResourceAccessors(providers).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 resDir = layout.dir(commonComposeResources)

val genTask = tasks.register(
"generateComposeResClass",
GenerateResClassTask::class.java
) {
it.packageName.set(packageName)
it.resDir.set(resDir)
it.codeDir.set(buildDir("$RES_GEN_DIR/kotlin"))
it.onlyIf { shouldGenerateResourceAccessors.get() }
//lazy check a dependency on the Resources library
val shouldGenerateResourceAccessors: Provider<Boolean> = provider {
if (ComposeProperties.alwaysGenerateResourceAccessors(providers).get()) {
true
} else {
configurations
.getByName(commonSourceSet.implementationConfigurationName)
.allDependencies.any { dep ->
val depStringNotation = dep.let { "${it.group}:${it.name}:${it.version}" }
depStringNotation == ComposePlugin.CommonComponentsDependencies.resources
}
}
}

//register generated source set
commonSourceSet.kotlin.srcDir(genTask.map { it.codeDir })
val genTask = tasks.register(
"generateComposeResClass",
GenerateResClassTask::class.java
) {
it.packageName.set(packageName)
it.resDir.set(resDir)
it.codeDir.set(buildDir("$RES_GEN_DIR/kotlin"))
it.onlyIf { shouldGenerateResourceAccessors.get() }
}

//setup task execution during IDE import
tasks.configureEach {
if (it.name == "prepareKotlinIdeaImport") {
it.dependsOn(genTask)
}
}
//register generated source set
commonSourceSet.kotlin.srcDir(genTask.map { it.codeDir })

val androidExtension = project.extensions.findByName("android")
if (androidExtension != null) {
configureAndroidResources(
commonResourcesDir,
buildDir("$RES_GEN_DIR/androidFonts").map { it.asFile },
shouldGenerateResourceAccessors
)
//setup task execution during IDE import
tasks.configureEach {
if (it.name == "prepareKotlinIdeaImport") {
it.dependsOn(genTask)
}
}
}

val androidExtension = project.extensions.findByName("android")
if (androidExtension != null) {
configureAndroidResources(
commonComposeResources,
buildDir("$RES_GEN_DIR/androidFonts").map { it.asFile },
shouldGenerateResourceAccessors
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ internal fun getResFileSpec(
.addParameter("path", String::class)
.addModifiers(KModifier.SUSPEND)
.returns(ByteArray::class)
.addStatement("return %M(\"$COMPOSE_RESOURCES_DIR/\" + path)", readResourceBytes) //todo: add module ID here
.addStatement("return %M(path)", readResourceBytes) //todo: add module ID here
.build()
)

Expand Down Expand Up @@ -163,7 +163,7 @@ private fun TypeSpec.Builder.addResourceProperty(name: String, items: List<Resou
add("%T(\n", resourceItemClass).withIndent {
add("setOf(").addQualifiers(item).add("),\n")
//file separator should be '/' on all platforms
add("\"$COMPOSE_RESOURCES_DIR/${item.path.invariantSeparatorsPathString}\"\n") //todo: add module ID here
add("\"${item.path.invariantSeparatorsPathString}\"\n") //todo: add module ID here
}
add("),\n")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,87 +13,87 @@ class ResourcesTest : GradlePluginTestBase() {
//check generated resource's accessors
gradle("generateComposeResClass").checks {
assertEqualTextFiles(
file("build/generated/compose/resourceGenerator/kotlin/app/group/generated/resources/Res.kt"),
file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt"),
file("expected/Res.kt")
)
}

//check resource's accessors were regenerated
file("src/commonMain/resources/composeResources/drawable/vector_2.xml").renameTo(
file("src/commonMain/resources/composeResources/drawable/vector_3.xml")
file("src/commonMain/composeResources/drawable/vector_2.xml").renameTo(
file("src/commonMain/composeResources/drawable/vector_3.xml")
)
gradle("generateComposeResClass").checks {
assertNotEqualTextFiles(
file("build/generated/compose/resourceGenerator/kotlin/app/group/generated/resources/Res.kt"),
file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt"),
file("expected/Res.kt")
)
}

file("src/commonMain/resources/composeResources/drawable-en").renameTo(
file("src/commonMain/resources/composeResources/drawable-ren")
file("src/commonMain/composeResources/drawable-en").renameTo(
file("src/commonMain/composeResources/drawable-ren")
)
gradle("generateComposeResClass").checks {
check.logContains("""
contains unknown qualifier: 'ren'.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/drawable-ren").renameTo(
file("src/commonMain/resources/composeResources/drawable-rUS-en")
file("src/commonMain/composeResources/drawable-ren").renameTo(
file("src/commonMain/composeResources/drawable-rUS-en")
)
gradle("generateComposeResClass").checks {
check.logContains("""
Region qualifier must be declared after language: 'en-rUS'.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/drawable-rUS-en").renameTo(
file("src/commonMain/resources/composeResources/drawable-rUS")
file("src/commonMain/composeResources/drawable-rUS-en").renameTo(
file("src/commonMain/composeResources/drawable-rUS")
)
gradle("generateComposeResClass").checks {
check.logContains("""
Region qualifier must be used only with language.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/drawable-rUS").renameTo(
file("src/commonMain/resources/composeResources/drawable-en-fr")
file("src/commonMain/composeResources/drawable-rUS").renameTo(
file("src/commonMain/composeResources/drawable-en-fr")
)
gradle("generateComposeResClass").checks {
check.logContains("""
contains repetitive qualifiers: 'en' and 'fr'.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/drawable-en-fr").renameTo(
file("src/commonMain/resources/composeResources/image")
file("src/commonMain/composeResources/drawable-en-fr").renameTo(
file("src/commonMain/composeResources/image")
)
gradle("generateComposeResClass").checks {
check.logContains("""
Unknown resource type: 'image'
""".trimIndent())
}

file("src/commonMain/resources/composeResources/image").renameTo(
file("src/commonMain/resources/composeResources/files-de")
file("src/commonMain/composeResources/image").renameTo(
file("src/commonMain/composeResources/files-de")
)
gradle("generateComposeResClass").checks {
check.logContains("""
The 'files' directory doesn't support qualifiers: 'files-de'.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/files-de").renameTo(
file("src/commonMain/resources/composeResources/strings")
file("src/commonMain/composeResources/files-de").renameTo(
file("src/commonMain/composeResources/strings")
)
gradle("generateComposeResClass").checks {
check.logContains("""
Unknown resource type: 'strings'.
""".trimIndent())
}

file("src/commonMain/resources/composeResources/strings").renameTo(
file("src/commonMain/resources/composeResources/string-us")
file("src/commonMain/composeResources/strings").renameTo(
file("src/commonMain/composeResources/string-us")
)
gradle("generateComposeResClass").checks {
check.logContains("""
Expand All @@ -102,11 +102,11 @@ class ResourcesTest : GradlePluginTestBase() {
}

//restore defaults
file("src/commonMain/resources/composeResources/string-us").renameTo(
file("src/commonMain/resources/composeResources/drawable-en")
file("src/commonMain/composeResources/string-us").renameTo(
file("src/commonMain/composeResources/drawable-en")
)
file("src/commonMain/resources/composeResources/drawable/vector_3.xml").renameTo(
file("src/commonMain/resources/composeResources/drawable/vector_2.xml")
file("src/commonMain/composeResources/drawable/vector_3.xml").renameTo(
file("src/commonMain/composeResources/drawable/vector_2.xml")
)

//TODO: check a real build after a release a new version of the resources library
Expand Down
Loading

0 comments on commit 747aab0

Please sign in to comment.