diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt index 7f6f0b4f619..c4c7d79e69d 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/AndroidResources.kt @@ -5,9 +5,9 @@ import com.android.build.gradle.BaseExtension import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemOperations import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.jetbrains.compose.internal.utils.registerTask import org.jetbrains.compose.internal.utils.uppercaseFirstChar @@ -18,40 +18,31 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull import org.jetbrains.kotlin.gradle.utils.ObservableSet -import java.io.File import javax.inject.Inject @OptIn(ExperimentalKotlinGradlePluginApi::class) internal fun Project.configureAndroidComposeResources( kotlinExtension: KotlinMultiplatformExtension, - androidExtension: BaseExtension, - preparedCommonResources: Provider + androidExtension: BaseExtension ) { - val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME - val commonResourcesDir = projectDir.resolve("src/$commonMain/$COMPOSE_RESOURCES_DIR") - // 1) get the Kotlin Android Target Compilation -> [A] // 2) get default source set name for the 'A' // 3) find the associated Android SourceSet in the AndroidExtension -> [B] // 4) get all source sets in the 'A' and add its resources to the 'B' kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).all { androidTarget -> androidTarget.compilations.all { compilation: KotlinJvmAndroidCompilation -> - - //fix for AGP < 8.0 - //usually 'androidSourceSet.resources.srcDir(preparedCommonResources)' should be enough - compilation.androidVariant.processJavaResourcesProvider.configure { it.dependsOn(preparedCommonResources) } - compilation.defaultSourceSet.androidSourceSetInfoOrNull?.let { kotlinAndroidSourceSet -> androidExtension.sourceSets .matching { it.name == kotlinAndroidSourceSet.androidSourceSetName } .all { androidSourceSet -> (compilation.allKotlinSourceSets as? ObservableSet)?.forAll { kotlinSourceSet -> - if (kotlinSourceSet.name == commonMain) { - androidSourceSet.resources.srcDir(preparedCommonResources) - } else { - androidSourceSet.resources.srcDir( - projectDir.resolve("src/${kotlinSourceSet.name}/$COMPOSE_RESOURCES_DIR") - ) + val preparedComposeResources = getPreparedComposeResourcesDir(kotlinSourceSet) + androidSourceSet.resources.srcDirs(preparedComposeResources) + + //fix for AGP < 8.0 + //usually 'androidSourceSet.resources.srcDir(preparedCommonResources)' should be enough + compilation.androidVariant.processJavaResourcesProvider.configure { + it.dependsOn(preparedComposeResources) } } } @@ -62,10 +53,24 @@ internal fun Project.configureAndroidComposeResources( //copy fonts from the compose resources dir to android assets val androidComponents = project.extensions.findByType(AndroidComponentsExtension::class.java) ?: return androidComponents.onVariants { variant -> + val variantResources = project.files() + + kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).all { androidTarget -> + androidTarget.compilations.all { compilation: KotlinJvmAndroidCompilation -> + if (compilation.androidVariant.name == variant.name) { + project.logger.info("Configure fonts for variant ${variant.name}") + (compilation.allKotlinSourceSets as? ObservableSet)?.forAll { kotlinSourceSet -> + val preparedComposeResources = getPreparedComposeResourcesDir(kotlinSourceSet) + variantResources.from(preparedComposeResources) + } + } + } + } + val copyFonts = registerTask( "copy${variant.name.uppercaseFirstChar()}FontsToAndroidAssets" ) { - from.set(commonResourcesDir) + from.set(variantResources) } variant.sources?.assets?.addGeneratedSourceDirectory( taskProvider = copyFonts, @@ -83,7 +88,7 @@ internal abstract class CopyAndroidFontsToAssetsTask : DefaultTask() { @get:InputFiles @get:IgnoreEmptyDirectories - abstract val from: Property + abstract val from: Property @get:OutputDirectory abstract val outputDirectory: DirectoryProperty diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt index e9a1a717188..08dae761b74 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResources.kt @@ -1,11 +1,14 @@ package org.jetbrains.compose.resources import com.android.build.gradle.BaseExtension +import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask +import com.android.build.gradle.internal.lint.LintModelWriterTask import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskProvider import org.gradle.util.GradleVersion +import org.jetbrains.compose.ComposePlugin import org.jetbrains.compose.internal.KOTLIN_JVM_PLUGIN_ID import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension @@ -33,22 +36,18 @@ internal fun Project.configureComposeResources(extension: ResourcesExtension) { private fun Project.onKgpApplied(config: Provider) { val kotlinExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) - //common resources must be converted (XML -> CVR) - val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME - val preparedCommonResources = prepareCommonResources(commonMain) - val hasKmpResources = extraProperties.has(KMP_RES_EXT) val currentGradleVersion = GradleVersion.current() val minGradleVersion = GradleVersion.version(MIN_GRADLE_VERSION_FOR_KMP_RESOURCES) val kmpResourcesAreAvailable = hasKmpResources && currentGradleVersion >= minGradleVersion if (kmpResourcesAreAvailable) { - configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, preparedCommonResources, config) + configureKmpResources(kotlinExtension, extraProperties.get(KMP_RES_EXT)!!, config) } else { if (!hasKmpResources) logger.info( """ Compose resources publication requires Kotlin Gradle Plugin >= 2.0 - Current Kotlin Gradle Plugin is ${KotlinVersion.CURRENT} + Current Kotlin Gradle Plugin is ${kotlinExtension.coreLibrariesVersion} """.trimIndent() ) if (currentGradleVersion < minGradleVersion) logger.info( @@ -58,13 +57,31 @@ private fun Project.onKgpApplied(config: Provider) { """.trimIndent() ) - configureComposeResources(kotlinExtension, commonMain, preparedCommonResources, config) + val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME + configureComposeResources(kotlinExtension, commonMain, config) //when applied AGP then configure android resources androidPluginIds.forEach { pluginId -> plugins.withId(pluginId) { val androidExtension = project.extensions.getByType(BaseExtension::class.java) - configureAndroidComposeResources(kotlinExtension, androidExtension, preparedCommonResources) + configureAndroidComposeResources(kotlinExtension, androidExtension) + + + /* + There is a dirty fix for the problem: + + Reason: Task ':generateDemoDebugUnitTestLintModel' uses this output of task ':generateResourceAccessorsForAndroidUnitTest' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. + + Possible solutions: + 1. Declare task ':generateResourceAccessorsForAndroidUnitTest' as an input of ':generateDemoDebugUnitTestLintModel'. + 2. Declare an explicit dependency on ':generateResourceAccessorsForAndroidUnitTest' from ':generateDemoDebugUnitTestLintModel' using Task#dependsOn. + 3. Declare an explicit dependency on ':generateResourceAccessorsForAndroidUnitTest' from ':generateDemoDebugUnitTestLintModel' using Task#mustRunAfter. + */ + tasks.matching { + it is AndroidLintAnalysisTask || it is LintModelWriterTask + }.configureEach { + it.mustRunAfter(tasks.withType(GenerateResourceAccessorsTask::class.java)) + } } } } @@ -75,36 +92,20 @@ private fun Project.onKgpApplied(config: Provider) { private fun Project.onKotlinJvmApplied(config: Provider) { val kotlinExtension = project.extensions.getByType(KotlinProjectExtension::class.java) val main = SourceSet.MAIN_SOURCE_SET_NAME - val preparedCommonResources = prepareCommonResources(main) - configureComposeResources(kotlinExtension, main, preparedCommonResources, config) -} - -//common resources must be converted (XML -> CVR) -private fun Project.prepareCommonResources(commonSourceSetName: String): Provider { - val preparedResourcesTask = registerPrepareComposeResourcesTask( - project.projectDir.resolve("src/$commonSourceSetName/$COMPOSE_RESOURCES_DIR"), - layout.buildDirectory.dir("$RES_GEN_DIR/preparedResources/$commonSourceSetName/$COMPOSE_RESOURCES_DIR") - ) - return preparedResourcesTask.flatMap { it.outputDir } + configureComposeResources(kotlinExtension, main, config) } // sourceSet.resources.srcDirs doesn't work for Android targets. // Android resources should be configured separately private fun Project.configureComposeResources( kotlinExtension: KotlinProjectExtension, - commonSourceSetName: String, - preparedCommonResources: Provider, + resClassSourceSetName: String, config: Provider ) { logger.info("Configure compose resources") + configureComposeResourcesGeneration(kotlinExtension, resClassSourceSetName, config, false) + kotlinExtension.sourceSets.all { sourceSet -> - val sourceSetName = sourceSet.name - val resourcesDir = project.projectDir.resolve("src/$sourceSetName/$COMPOSE_RESOURCES_DIR") - if (sourceSetName == commonSourceSetName) { - sourceSet.resources.srcDirs(preparedCommonResources) - configureGenerationComposeResClass(preparedCommonResources, sourceSet, config, false) - } else { - sourceSet.resources.srcDirs(resourcesDir) - } + sourceSet.resources.srcDirs(getPreparedComposeResourcesDir(sourceSet)) } } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt new file mode 100644 index 00000000000..56b989ebdd5 --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt @@ -0,0 +1,133 @@ +package org.jetbrains.compose.resources + +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.jetbrains.compose.ComposePlugin +import org.jetbrains.compose.internal.utils.uppercaseFirstChar +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import java.io.File + +internal fun Project.configureComposeResourcesGeneration( + kotlinExtension: KotlinProjectExtension, + resClassSourceSetName: String, + config: Provider, + generateModulePath: Boolean +) { + logger.info("Configure compose resources generation") + + //lazy check a dependency on the Resources library + val shouldGenerateCode = config.map { + when (it.generateResClass) { + ResourcesExtension.ResourceClassGeneration.Auto -> { + configurations.run { + val commonSourceSet = kotlinExtension.sourceSets.getByName(resClassSourceSetName) + //because the implementation configuration doesn't extend the api in the KGP ¯\_(ツ)_/¯ + getByName(commonSourceSet.implementationConfigurationName).allDependencies + + getByName(commonSourceSet.apiConfigurationName).allDependencies + }.any { dep -> + val depStringNotation = dep.let { "${it.group}:${it.name}:${it.version}" } + depStringNotation == ComposePlugin.CommonComponentsDependencies.resources + } + } + + ResourcesExtension.ResourceClassGeneration.Always -> true + ResourcesExtension.ResourceClassGeneration.Never -> false + } + } + val packageName = config.getResourcePackage(project) + val makeAccessorsPublic = config.map { it.publicResClass } + val packagingDir = config.getModuleResourcesDir(project) + + kotlinExtension.sourceSets.all { sourceSet -> + if (sourceSet.name == resClassSourceSetName) { + configureResClassGeneration( + sourceSet, + shouldGenerateCode, + packageName, + makeAccessorsPublic, + packagingDir, + generateModulePath + ) + } + + //common resources must be converted (XML -> CVR) + val preparedResourcesTask = registerPrepareComposeResourcesTask(sourceSet) + val preparedResources = preparedResourcesTask.flatMap { it.outputDir.asFile } + configureResourceAccessorsGeneration( + sourceSet, + preparedResources, + shouldGenerateCode, + packageName, + makeAccessorsPublic, + packagingDir, + generateModulePath + ) + } + + //setup task execution during IDE import + tasks.configureEach { importTask -> + if (importTask.name == "prepareKotlinIdeaImport") { + importTask.dependsOn(tasks.withType(CodeGenerationTask::class.java)) + } + } +} + +private fun Project.configureResClassGeneration( + resClassSourceSet: KotlinSourceSet, + shouldGenerateCode: Provider, + packageName: Provider, + makeAccessorsPublic: Provider, + packagingDir: Provider, + generateModulePath: Boolean +) { + logger.info("Configure Res class generation for ${resClassSourceSet.name}") + + val genTask = tasks.register( + "generateComposeResClass", + GenerateResClassTask::class.java + ) { task -> + task.packageName.set(packageName) + task.shouldGenerateCode.set(shouldGenerateCode) + task.makeAccessorsPublic.set(makeAccessorsPublic) + task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/commonResClass")) + + if (generateModulePath) { + task.packagingDir.set(packagingDir) + } + } + + //register generated source set + resClassSourceSet.kotlin.srcDir(genTask.map { it.codeDir }) +} + +private fun Project.configureResourceAccessorsGeneration( + sourceSet: KotlinSourceSet, + resourcesDir: Provider, + shouldGenerateCode: Provider, + packageName: Provider, + makeAccessorsPublic: Provider, + packagingDir: Provider, + generateModulePath: Boolean +) { + logger.info("Configure resource accessors generation for ${sourceSet.name}") + + val genTask = tasks.register( + "generateResourceAccessorsFor${sourceSet.name.uppercaseFirstChar()}", + GenerateResourceAccessorsTask::class.java + ) { task -> + task.packageName.set(packageName) + task.sourceSetName.set(sourceSet.name) + task.shouldGenerateCode.set(shouldGenerateCode) + task.makeAccessorsPublic.set(makeAccessorsPublic) + task.resDir.set(resourcesDir) + task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/${sourceSet.name}ResourceAccessors")) + + if (generateModulePath) { + task.packagingDir.set(packagingDir) + } + } + + //register generated source set + sourceSet.kotlin.srcDir(genTask.map { it.codeDir }) +} \ No newline at end of file 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 3c7811d8380..e0202be20bf 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 @@ -1,147 +1,59 @@ package org.jetbrains.compose.resources import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFile import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import java.io.File -import java.io.RandomAccessFile -import java.nio.file.Path -import kotlin.io.path.relativeTo /** * This task should be FAST and SAFE! Because it is being run during IDE import. */ -internal abstract class GenerateResClassTask : DefaultTask() { +internal abstract class CodeGenerationTask : DefaultTask() + +internal abstract class GenerateResClassTask : CodeGenerationTask() { + companion object { + private const val RES_FILE_NAME = "Res" + } + @get:Input abstract val packageName: Property @get:Input @get:Optional - abstract val moduleDir: Property + abstract val packagingDir: Property @get:Input - abstract val shouldGenerateResClass: Property + abstract val shouldGenerateCode: Property @get:Input - abstract val makeResClassPublic: Property - - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val resDir: Property + abstract val makeAccessorsPublic: Property @get:OutputDirectory - abstract val codeDir: Property + abstract val codeDir: DirectoryProperty @TaskAction fun generate() { try { - val kotlinDir = codeDir.get() - logger.info("Clean directory $kotlinDir") - kotlinDir.deleteRecursively() - kotlinDir.mkdirs() + val dir = codeDir.get().asFile + dir.deleteRecursively() + dir.mkdirs() - if (shouldGenerateResClass.get()) { - val rootResDir = resDir.get() - logger.info("Generate resources for $rootResDir") + if (shouldGenerateCode.get()) { + logger.info("Generate $RES_FILE_NAME.kt") - //get first level dirs - val dirs = rootResDir.listNotHiddenFiles() - - dirs.forEach { f -> - if (!f.isDirectory) { - error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") - } - } - - //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 } } - getResFileSpecs( - resources, - packageName.get(), - moduleDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "", - makeResClassPublic.get() - ).forEach { it.writeTo(kotlinDir) } + val pkgName = packageName.get() + val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" + val isPublic = makeAccessorsPublic.get() + getResFileSpec(pkgName, RES_FILE_NAME, moduleDirectory, isPublic).writeTo(dir) } 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) + logger.error("e: $name task was failed:", e) } } - - private fun File.fileToResourceItems( - relativeTo: Path - ): List? { - val file = this - val dirName = file.parentFile.name ?: return null - val typeAndQualifiers = dirName.split("-") - if (typeAndQualifiers.isEmpty()) return null - - val typeString = typeAndQualifiers.first().lowercase() - val qualifiers = typeAndQualifiers.takeLast(typeAndQualifiers.size - 1) - val path = file.toPath().relativeTo(relativeTo) - - - if (typeString == "string") { - error("Forbidden directory name '$dirName'! String resources should be declared in 'values/strings.xml'.") - } - - if (typeString == "files") { - if (qualifiers.isNotEmpty()) error("The 'files' directory doesn't support qualifiers: '$dirName'.") - return null - } - - if (typeString == "values" && file.extension.equals(XmlValuesConverterTask.CONVERTED_RESOURCE_EXT, true)) { - return getValueResourceItems(file, qualifiers, path) - } - - val type = ResourceType.fromString(typeString) ?: error("Unknown resource type: '$typeString'.") - return listOf(ResourceItem(type, qualifiers, file.nameWithoutExtension.asUnderscoredIdentifier(), path)) - } - - private fun getValueResourceItems(dataFile: File, qualifiers: List, path: Path) : List { - val result = mutableListOf() - dataFile.bufferedReader().use { f -> - var offset = 0L - var line: String? = f.readLine() - while (line != null) { - val size = line.encodeToByteArray().size - - //first line is meta info - if (offset > 0) { - result.add(getValueResourceItem(line, offset, size.toLong(), qualifiers, path)) - } - - offset += size + 1 // "+1" for newline character - line = f.readLine() - } - } - return result - } - - private fun getValueResourceItem( - recordString: String, - offset: Long, - size: Long, - qualifiers: List, - path: Path - ) : ResourceItem { - val record = ValueResourceRecord.createFromString(recordString) - return ResourceItem(record.type, qualifiers, record.key.asUnderscoredIdentifier(), path, offset, size) - } } - -internal fun File.listNotHiddenFiles(): List = - listFiles()?.filter { !it.isHidden }.orEmpty() - -internal fun String.asUnderscoredIdentifier(): String = - replace('-', '_') - .let { if (it.isNotEmpty() && it.first().isDigit()) "_$it" else it } \ No newline at end of file diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt new file mode 100644 index 00000000000..fd997ed03b9 --- /dev/null +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt @@ -0,0 +1,157 @@ +package org.jetbrains.compose.resources + +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import java.io.File +import java.nio.file.Path +import kotlin.io.path.relativeTo + +internal abstract class GenerateResourceAccessorsTask : CodeGenerationTask() { + @get:Input + abstract val packageName: Property + + @get:Input + abstract val sourceSetName: Property + + @get:Input + @get:Optional + abstract val packagingDir: Property + + @get:Input + abstract val shouldGenerateCode: Property + + @get:Input + abstract val makeAccessorsPublic: Property + + @get:InputFiles + @get:SkipWhenEmpty + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val resDir: Property + + @get:OutputDirectory + abstract val codeDir: DirectoryProperty + + @TaskAction + fun generate() { + try { + val kotlinDir = codeDir.get().asFile + val rootResDir = resDir.get() + val sourceSet = sourceSetName.get() + + logger.info("Clean directory $kotlinDir") + kotlinDir.deleteRecursively() + kotlinDir.mkdirs() + + if (shouldGenerateCode.get()) { + logger.info("Generate accessors for $rootResDir") + + //get first level dirs + val dirs = rootResDir.listNotHiddenFiles() + + dirs.forEach { f -> + if (!f.isDirectory) { + error("${f.name} is not directory! Raw files should be placed in '${rootResDir.name}/files' directory.") + } + } + + //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 } } + + val pkgName = packageName.get() + val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: "" + val isPublic = makeAccessorsPublic.get() + getAccessorsSpecs( + resources, pkgName, sourceSet, moduleDirectory, isPublic + ).forEach { it.writeTo(kotlinDir) } + } else { + logger.info("Generation accessors for $rootResDir is disabled") + } + } catch (e: Exception) { + //message must contain two ':' symbols to be parsed by IDE UI! + logger.error("e: $name task was failed:", e) + } + } + + private fun File.fileToResourceItems( + relativeTo: Path + ): List? { + val file = this + val dirName = file.parentFile.name ?: return null + val typeAndQualifiers = dirName.split("-") + if (typeAndQualifiers.isEmpty()) return null + + val typeString = typeAndQualifiers.first().lowercase() + val qualifiers = typeAndQualifiers.takeLast(typeAndQualifiers.size - 1) + val path = file.toPath().relativeTo(relativeTo) + + + if (typeString == "string") { + error("Forbidden directory name '$dirName'! String resources should be declared in 'values/strings.xml'.") + } + + if (typeString == "files") { + if (qualifiers.isNotEmpty()) error("The 'files' directory doesn't support qualifiers: '$dirName'.") + return null + } + + if (typeString == "values" && file.extension.equals(XmlValuesConverterTask.CONVERTED_RESOURCE_EXT, true)) { + return getValueResourceItems(file, qualifiers, path) + } + + val type = ResourceType.fromString(typeString) ?: error("Unknown resource type: '$typeString'.") + return listOf(ResourceItem(type, qualifiers, file.nameWithoutExtension.asUnderscoredIdentifier(), path)) + } + + private fun getValueResourceItems(dataFile: File, qualifiers: List, path: Path): List { + val result = mutableListOf() + dataFile.bufferedReader().use { f -> + var offset = 0L + var line: String? = f.readLine() + while (line != null) { + val size = line.encodeToByteArray().size + + //first line is meta info + if (offset > 0) { + result.add(getValueResourceItem(line, offset, size.toLong(), qualifiers, path)) + } + + offset += size + 1 // "+1" for newline character + line = f.readLine() + } + } + return result + } + + private fun getValueResourceItem( + recordString: String, + offset: Long, + size: Long, + qualifiers: List, + path: Path + ): ResourceItem { + val record = ValueResourceRecord.createFromString(recordString) + return ResourceItem(record.type, qualifiers, record.key.asUnderscoredIdentifier(), path, offset, size) + } +} + +internal fun File.listNotHiddenFiles(): List = + listFiles()?.filter { !it.isHidden }.orEmpty() + +internal fun String.asUnderscoredIdentifier(): String = + replace('-', '_') + .let { if (it.isNotEmpty() && it.first().isDigit()) "_$it" else it } diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt index 8acb4e0c33a..bbe8a02be47 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt @@ -111,25 +111,14 @@ private fun CodeBlock.Builder.addQualifiers(resourceItem: ResourceItem): CodeBlo return this } -// We need to divide accessors by different files because -// -// if all accessors are generated in a single object -// then a build may fail with: org.jetbrains.org.objectweb.asm.MethodTooLargeException: Method too large: Res$drawable. ()V -// e.g. https://github.com/JetBrains/compose-multiplatform/issues/4285 -// -// if accessor initializers are extracted from the single object but located in the same file -// then a build may fail with: org.jetbrains.org.objectweb.asm.ClassTooLargeException: Class too large: Res$drawable -private const val ITEMS_PER_FILE_LIMIT = 500 -internal fun getResFileSpecs( - //type -> id -> items - resources: Map>>, +internal fun getResFileSpec( packageName: String, + fileName: String, moduleDir: String, isPublic: Boolean -): List { +): FileSpec { val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL - val files = mutableListOf() - val resClass = FileSpec.builder(packageName, "Res").also { file -> + return FileSpec.builder(packageName, fileName).also { file -> file.addAnnotation( AnnotationSpec.builder(ClassName("kotlin", "OptIn")) .addMember("org.jetbrains.compose.resources.InternalResourceApi::class") @@ -186,7 +175,27 @@ internal fun getResFileSpecs( } }.build()) }.build() - files.add(resClass) +} + +// We need to divide accessors by different files because +// +// if all accessors are generated in a single object +// then a build may fail with: org.jetbrains.org.objectweb.asm.MethodTooLargeException: Method too large: Res$drawable. ()V +// e.g. https://github.com/JetBrains/compose-multiplatform/issues/4285 +// +// if accessor initializers are extracted from the single object but located in the same file +// then a build may fail with: org.jetbrains.org.objectweb.asm.ClassTooLargeException: Class too large: Res$drawable +private const val ITEMS_PER_FILE_LIMIT = 500 +internal fun getAccessorsSpecs( + //type -> id -> items + resources: Map>>, + packageName: String, + sourceSetName: String, + moduleDir: String, + isPublic: Boolean +): List { + val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL + val files = mutableListOf() //we need to sort it to generate the same code on different platforms sortResources(resources).forEach { (type, idToResources) -> @@ -196,7 +205,8 @@ internal fun getResFileSpecs( files.add( getChunkFileSpec( type, - index, + "${type.accessorName.uppercaseFirstChar()}$index.$sourceSetName", + sourceSetName.uppercaseFirstChar() + type.accessorName.uppercaseFirstChar() + index, packageName, moduleDir, resModifier, @@ -211,14 +221,14 @@ internal fun getResFileSpecs( private fun getChunkFileSpec( type: ResourceType, - index: Int, + fileName: String, + chunkClassName: String, packageName: String, moduleDir: String, resModifier: KModifier, idToResources: Map> ): FileSpec { - val chunkClassName = type.accessorName.uppercaseFirstChar() + index - return FileSpec.builder(packageName, chunkClassName).also { chunkFile -> + return FileSpec.builder(packageName, fileName).also { chunkFile -> chunkFile.addAnnotation( AnnotationSpec.builder(ClassName("kotlin", "OptIn")) .addMember("org.jetbrains.compose.resources.InternalResourceApi::class") diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt index a2df7e50b18..3a945db5606 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/KmpResources.kt @@ -15,7 +15,6 @@ import java.io.File internal fun Project.configureKmpResources( kotlinExtension: KotlinProjectExtension, kmpResources: Any, - preparedCommonResources: Provider, config: Provider ) { kotlinExtension as KotlinMultiplatformExtension @@ -23,6 +22,9 @@ internal fun Project.configureKmpResources( logger.info("Configure KMP resources") + val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME + configureComposeResourcesGeneration(kotlinExtension, commonMain, config, true) + //configure KMP resources publishing for each supported target kotlinExtension.targets .matching { target -> kmpResources.canPublishResources(target) } @@ -33,16 +35,8 @@ internal fun Project.configureKmpResources( kmpResources.publishResourcesAsKotlinComponent( target, { sourceSet -> - val sourceSetName = sourceSet.name - val composeResDir: Provider - if (sourceSetName == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) { - composeResDir = preparedCommonResources - } else { - composeResDir = provider { project.file("src/$sourceSetName/$COMPOSE_RESOURCES_DIR") } - } - KotlinTargetResourcesPublication.ResourceRoot( - composeResDir, + getPreparedComposeResourcesDir(sourceSet), emptyList(), //for android target exclude fonts if (target is KotlinAndroidTarget) listOf("**/font*/*") else emptyList() @@ -57,15 +51,8 @@ internal fun Project.configureKmpResources( kmpResources.publishInAndroidAssets( target, { sourceSet -> - val sourceSetName = sourceSet.name - val composeResDir: Provider - if (sourceSetName == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) { - composeResDir = preparedCommonResources - } else { - composeResDir = provider { project.file("src/$sourceSetName/$COMPOSE_RESOURCES_DIR") } - } KotlinTargetResourcesPublication.ResourceRoot( - composeResDir, + getPreparedComposeResourcesDir(sourceSet), listOf("**/font*/*"), emptyList() ) @@ -75,19 +62,6 @@ internal fun Project.configureKmpResources( } } - //generate accessors for common resources - kotlinExtension.sourceSets.all { sourceSet -> - val sourceSetName = sourceSet.name - if (sourceSetName == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) { - configureGenerationComposeResClass( - preparedCommonResources, - sourceSet, - config, - true - ) - } - } - //add all resolved resources for browser and native compilations val platformsForSetupCompilation = listOf(KotlinPlatformType.native, KotlinPlatformType.js, KotlinPlatformType.wasm) kotlinExtension.targets diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt index b50bbdb22eb..e4327cd82e3 100644 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt +++ b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/PrepareComposeResources.kt @@ -6,6 +6,8 @@ import org.gradle.api.file.* import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* +import org.jetbrains.compose.internal.utils.uppercaseFirstChar +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.w3c.dom.Node import java.io.File import java.util.* @@ -13,19 +15,23 @@ import javax.inject.Inject import javax.xml.parsers.DocumentBuilderFactory internal fun Project.registerPrepareComposeResourcesTask( - userComposeResourcesDir: File, - preparedComposeResourcesDir: Provider + sourceSet: KotlinSourceSet ): TaskProvider { + val resDir = "${sourceSet.name}/$COMPOSE_RESOURCES_DIR" + val userComposeResourcesDir = project.projectDir.resolve("src/$resDir") + val preparedComposeResourcesDir = layout.buildDirectory.dir("$RES_GEN_DIR/preparedResources/$resDir") + val convertXmlValueResources = tasks.register( - "convertXmlValueResources", + "convertXmlValueResourcesFor${sourceSet.name.uppercaseFirstChar()}", XmlValuesConverterTask::class.java ) { task -> + task.fileSuffix.set(sourceSet.name) task.originalResourcesDir.set(userComposeResourcesDir) task.outputDir.set(preparedComposeResourcesDir) } val copyNonXmlValueResources = tasks.register( - "copyNonXmlValueResources", + "copyNonXmlValueResourcesFor${sourceSet.name.uppercaseFirstChar()}", CopyNonXmlValueResourcesTask::class.java ) { task -> task.originalResourcesDir.set(userComposeResourcesDir) @@ -33,17 +39,27 @@ internal fun Project.registerPrepareComposeResourcesTask( } val prepareComposeResourcesTask = tasks.register( - "prepareComposeResourcesTask", + getPrepareComposeResourcesTaskName(sourceSet), PrepareComposeResourcesTask::class.java ) { task -> task.convertedXmls.set(convertXmlValueResources.map { it.realOutputFiles.get() }) task.copiedNonXmls.set(copyNonXmlValueResources.map { it.realOutputFiles.get() }) - task.outputDir.set(preparedComposeResourcesDir.map { it.asFile }) + task.outputDir.set(preparedComposeResourcesDir) } return prepareComposeResourcesTask } +internal fun Project.getPreparedComposeResourcesDir(sourceSet: KotlinSourceSet): Provider = tasks + .named( + getPrepareComposeResourcesTaskName(sourceSet), + PrepareComposeResourcesTask::class.java + ) + .flatMap { it.outputDir.asFile } + +private fun getPrepareComposeResourcesTaskName(sourceSet: KotlinSourceSet) = + "prepareComposeResourcesTaskFor${sourceSet.name.uppercaseFirstChar()}" + internal abstract class CopyNonXmlValueResourcesTask : DefaultTask() { @get:Inject abstract val fileSystem: FileSystemOperations @@ -52,6 +68,7 @@ internal abstract class CopyNonXmlValueResourcesTask : DefaultTask() { abstract val originalResourcesDir: DirectoryProperty @get:InputFiles + @get:SkipWhenEmpty val realInputFiles = originalResourcesDir.map { dir -> dir.asFileTree.matching { it.exclude("values*/*.xml") } } @@ -67,7 +84,7 @@ internal abstract class CopyNonXmlValueResourcesTask : DefaultTask() { @TaskAction fun run() { realOutputFiles.get().forEach { f -> f.delete() } - fileSystem.copy { copy -> + fileSystem.copy { copy -> copy.includeEmptyDirs = false copy.from(originalResourcesDir) { it.exclude("values*/*.xml") @@ -79,16 +96,18 @@ internal abstract class CopyNonXmlValueResourcesTask : DefaultTask() { internal abstract class PrepareComposeResourcesTask : DefaultTask() { @get:InputFiles + @get:SkipWhenEmpty abstract val convertedXmls: Property @get:InputFiles + @get:SkipWhenEmpty abstract val copiedNonXmls: Property @get:OutputDirectory - abstract val outputDir: Property + abstract val outputDir: DirectoryProperty @TaskAction - fun run() {} + fun run() = Unit } internal data class ValueResourceRecord( @@ -119,10 +138,14 @@ internal abstract class XmlValuesConverterTask : DefaultTask() { private const val FORMAT_VERSION = 0 } + @get:Input + abstract val fileSuffix: Property + @get:Internal abstract val originalResourcesDir: DirectoryProperty @get:InputFiles + @get:SkipWhenEmpty val realInputFiles = originalResourcesDir.map { dir -> dir.asFileTree.matching { it.include("values*/*.xml") } } @@ -132,12 +155,14 @@ internal abstract class XmlValuesConverterTask : DefaultTask() { @get:OutputFiles val realOutputFiles = outputDir.map { dir -> - dir.asFileTree.matching { it.include("values*/*.$CONVERTED_RESOURCE_EXT") } + val suffix = fileSuffix.get() + dir.asFileTree.matching { it.include("values*/*.$suffix.$CONVERTED_RESOURCE_EXT") } } @TaskAction fun run() { val outDir = outputDir.get().asFile + val suffix = fileSuffix.get() realOutputFiles.get().forEach { f -> f.delete() } originalResourcesDir.get().asFile.listNotHiddenFiles().forEach { valuesDir -> if (valuesDir.isDirectory && valuesDir.name.startsWith("values")) { @@ -145,7 +170,7 @@ internal abstract class XmlValuesConverterTask : DefaultTask() { if (f.extension.equals("xml", true)) { val output = outDir .resolve(f.parentFile.name) - .resolve(f.nameWithoutExtension + ".$CONVERTED_RESOURCE_EXT") + .resolve(f.nameWithoutExtension + ".$suffix.$CONVERTED_RESOURCE_EXT") output.parentFile.mkdirs() convert(f, output) } @@ -195,6 +220,7 @@ internal abstract class XmlValuesConverterTask : DefaultTask() { quantity.uppercase() + ":" + content.asBase64() } } + else -> error("Unknown string resource type: '$type'") } return ValueResourceRecord(type, key, value) diff --git a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResClassGeneration.kt b/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResClassGeneration.kt deleted file mode 100644 index c8f213f58d0..00000000000 --- a/gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResClassGeneration.kt +++ /dev/null @@ -1,65 +0,0 @@ -package org.jetbrains.compose.resources - -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.jetbrains.compose.ComposePlugin -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import java.io.File - -internal fun Project.configureGenerationComposeResClass( - commonComposeResourcesDir: Provider, - commonSourceSet: KotlinSourceSet, - config: Provider, - generateModulePath: Boolean -) { - logger.info("Configure accessors for '${commonSourceSet.name}'") - - //lazy check a dependency on the Resources library - val shouldGenerateResClass = config.map { - when (it.generateResClass) { - ResourcesExtension.ResourceClassGeneration.Auto -> { - configurations.run { - //because the implementation configuration doesn't extend the api in the KGP ¯\_(ツ)_/¯ - getByName(commonSourceSet.implementationConfigurationName).allDependencies + - getByName(commonSourceSet.apiConfigurationName).allDependencies - }.any { dep -> - val depStringNotation = dep.let { "${it.group}:${it.name}:${it.version}" } - depStringNotation == ComposePlugin.CommonComponentsDependencies.resources - } - } - - ResourcesExtension.ResourceClassGeneration.Always -> { - true - } - - ResourcesExtension.ResourceClassGeneration.Never -> { - false - } - } - } - - val genTask = tasks.register( - "generateComposeResClass", - GenerateResClassTask::class.java - ) { task -> - task.packageName.set(config.getResourcePackage(project)) - task.shouldGenerateResClass.set(shouldGenerateResClass) - task.makeResClassPublic.set(config.map { it.publicResClass }) - task.resDir.set(commonComposeResourcesDir) - task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin").map { it.asFile }) - - if (generateModulePath) { - task.moduleDir.set(config.getModuleResourcesDir(project)) - } - } - - //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) - } - } -} \ No newline at end of file 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 68a5ebbfb6a..9253faca18f 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 @@ -14,9 +14,9 @@ class ResourcesTest : GradlePluginTestBase() { @Test fun testGeneratedAccessors(): Unit = with(testProject("misc/commonResources")) { //check generated resource's accessors - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { assertDirectoriesContentEquals( - file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources"), + file("build/generated/compose/resourceGenerator/kotlin"), file("expected") ) } @@ -25,17 +25,17 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/drawable/vector_2.xml").renameTo( file("src/commonMain/composeResources/drawable/vector_3.xml") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { assertNotEqualTextFiles( - file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Drawable0.kt"), - file("expected/Drawable0.kt") + file("build/generated/compose/resourceGenerator/kotlin/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt"), + file("expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt") ) } file("src/commonMain/composeResources/drawable-en").renameTo( file("src/commonMain/composeResources/drawable-rent") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ contains unknown qualifier: 'rent'. @@ -46,7 +46,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/drawable-rent").renameTo( file("src/commonMain/composeResources/drawable-rUS-en") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ Region qualifier must be declared after language: 'en-rUS'. @@ -57,7 +57,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/drawable-rUS-en").renameTo( file("src/commonMain/composeResources/drawable-rUS") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ Region qualifier must be used only with language. @@ -68,7 +68,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/drawable-rUS").renameTo( file("src/commonMain/composeResources/drawable-en-fr") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ contains repetitive qualifiers: 'en' and 'fr'. @@ -79,7 +79,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/drawable-en-fr").renameTo( file("src/commonMain/composeResources/image") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ Unknown resource type: 'image' @@ -90,7 +90,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/image").renameTo( file("src/commonMain/composeResources/files-de") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ The 'files' directory doesn't support qualifiers: 'files-de'. @@ -101,7 +101,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/files-de").renameTo( file("src/commonMain/composeResources/strings") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ Unknown resource type: 'strings'. @@ -112,7 +112,7 @@ class ResourcesTest : GradlePluginTestBase() { file("src/commonMain/composeResources/strings").renameTo( file("src/commonMain/composeResources/string-us") ) - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { check.logContains( """ Forbidden directory name 'string-us'! String resources should be declared in 'values/strings.xml'. @@ -137,9 +137,9 @@ class ResourcesTest : GradlePluginTestBase() { """.trimIndent() } - gradle("generateComposeResClass").checks { + gradle("prepareKotlinIdeaImport").checks { assertDirectoriesContentEquals( - file("build/generated/compose/resourceGenerator/kotlin/my/lib/res"), + file("build/generated/compose/resourceGenerator/kotlin"), file("expected-open-res") ) } @@ -382,7 +382,8 @@ class ResourcesTest : GradlePluginTestBase() { file.parentFile.name.startsWith("value") && file.extension.equals("xml", true) ) { - file.parentFile.resolve(file.nameWithoutExtension + "." + XmlValuesConverterTask.CONVERTED_RESOURCE_EXT) + val cvrSuffix = file.parentFile.parentFile.parentFile.name + file.parentFile.resolve("${file.nameWithoutExtension}.$cvrSuffix.${XmlValuesConverterTask.CONVERTED_RESOURCE_EXT}") } else { file } @@ -431,7 +432,7 @@ class ResourcesTest : GradlePluginTestBase() { fun testUpToDateChecks(): Unit = with(testProject("misc/commonResources")) { gradle("prepareKotlinIdeaImport").checks { check.taskSuccessful(":generateComposeResClass") - assertTrue(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + assertTrue(file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/resources_test/generated/resources/Res.kt").exists()) } gradle("prepareKotlinIdeaImport").checks { check.taskUpToDate(":generateComposeResClass") @@ -445,7 +446,7 @@ class ResourcesTest : GradlePluginTestBase() { } gradle("prepareKotlinIdeaImport").checks { check.taskSuccessful(":generateComposeResClass") - assertFalse(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) + assertFalse(file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/resources_test/generated/resources/Res.kt").exists()) } modifyText("build.gradle.kts") { str -> @@ -462,8 +463,8 @@ class ResourcesTest : GradlePluginTestBase() { } gradle("prepareKotlinIdeaImport").checks { check.taskSuccessful(":generateComposeResClass") - assertFalse(file("build/generated/compose/resourceGenerator/kotlin/app/group/resources_test/generated/resources/Res.kt").exists()) - assertTrue(file("build/generated/compose/resourceGenerator/kotlin/io/company/resources_test/generated/resources/Res.kt").exists()) + assertFalse(file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/resources_test/generated/resources/Res.kt").exists()) + assertTrue(file("build/generated/compose/resourceGenerator/kotlin/commonResClass/io/company/resources_test/generated/resources/Res.kt").exists()) } } @@ -471,7 +472,7 @@ class ResourcesTest : GradlePluginTestBase() { fun testEmptyResClass(): Unit = with(testProject("misc/emptyResources")) { gradle("generateComposeResClass").checks { assertDirectoriesContentEquals( - file("build/generated/compose/resourceGenerator/kotlin/app/group/empty_res/generated/resources"), + file("build/generated/compose/resourceGenerator/kotlin/commonResClass/app/group/empty_res/generated/resources"), file("expected") ) } @@ -479,13 +480,12 @@ class ResourcesTest : GradlePluginTestBase() { @Test fun testJvmOnlyProject(): Unit = with(testProject("misc/jvmOnlyResources")) { - gradle("generateComposeResClass").checks { + gradle("jar").checks { assertDirectoriesContentEquals( - file("build/generated/compose/resourceGenerator/kotlin/me/app/jvmonlyresources/generated/resources"), + file("build/generated/compose/resourceGenerator/kotlin"), file("expected") ) } - gradle("jar") } //https://github.com/gmazzo/gradle-buildconfig-plugin/issues/131 @@ -509,8 +509,10 @@ class ResourcesTest : GradlePluginTestBase() { } val expectedFilesCount = expected.walkTopDown() + .filter { !it.isDirectory } .map { it.toPath().relativeTo(expectedPath) }.sorted().joinToString("\n") val actualFilesCount = actual.walkTopDown() + .filter { !it.isDirectory } .map { it.toPath().relativeTo(actualPath) }.sorted().joinToString("\n") assertEquals(expectedFilesCount, actualFilesCount) } diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt new file mode 100644 index 00000000000..c657bcaa880 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt @@ -0,0 +1,26 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package my.lib.res + +import kotlin.OptIn +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +private object AndroidMainString0 { + public val android_str: StringResource by + lazy { init_android_str() } +} + +@ExperimentalResourceApi +public val Res.string.android_str: StringResource + get() = AndroidMainString0.android_str + +@ExperimentalResourceApi +private fun init_android_str(): StringResource = org.jetbrains.compose.resources.StringResource( + "string:android_str", "android_str", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.androidMain.cvr", 10, + 39), + ) +) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Drawable0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt similarity index 93% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Drawable0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt index 6bf20319345..290092ea95d 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Drawable0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Drawable0.commonMain.kt @@ -7,7 +7,7 @@ import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi @ExperimentalResourceApi -private object Drawable0 { +private object CommonMainDrawable0 { public val _3_strange_name: DrawableResource by lazy { init__3_strange_name() } @@ -23,7 +23,7 @@ private object Drawable0 { @ExperimentalResourceApi public val Res.drawable._3_strange_name: DrawableResource - get() = Drawable0._3_strange_name + get() = CommonMainDrawable0._3_strange_name @ExperimentalResourceApi private fun init__3_strange_name(): DrawableResource = @@ -36,7 +36,7 @@ private fun init__3_strange_name(): DrawableResource = @ExperimentalResourceApi public val Res.drawable.camelCaseName: DrawableResource - get() = Drawable0.camelCaseName + get() = CommonMainDrawable0.camelCaseName @ExperimentalResourceApi private fun init_camelCaseName(): DrawableResource = @@ -49,7 +49,7 @@ private fun init_camelCaseName(): DrawableResource = @ExperimentalResourceApi public val Res.drawable.vector: DrawableResource - get() = Drawable0.vector + get() = CommonMainDrawable0.vector @ExperimentalResourceApi private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( @@ -74,7 +74,7 @@ private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.Dr @ExperimentalResourceApi public val Res.drawable.vector_2: DrawableResource - get() = Drawable0.vector_2 + get() = CommonMainDrawable0.vector_2 @ExperimentalResourceApi private fun init_vector_2(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Font0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt similarity index 91% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Font0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt index 7bd9c50a6da..a7f4e063735 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Font0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Font0.commonMain.kt @@ -7,14 +7,14 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.FontResource @ExperimentalResourceApi -private object Font0 { +private object CommonMainFont0 { public val emptyFont: FontResource by lazy { init_emptyFont() } } @ExperimentalResourceApi public val Res.font.emptyFont: FontResource - get() = Font0.emptyFont + get() = CommonMainFont0.emptyFont @ExperimentalResourceApi private fun init_emptyFont(): FontResource = org.jetbrains.compose.resources.FontResource( diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Plurals0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt similarity index 83% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Plurals0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt index 11358c09058..a41fe0fadc9 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Plurals0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/Plurals0.commonMain.kt @@ -7,20 +7,21 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.PluralStringResource @ExperimentalResourceApi -private object Plurals0 { +private object CommonMainPlurals0 { public val numberOfSongsAvailable: PluralStringResource by lazy { init_numberOfSongsAvailable() } } @ExperimentalResourceApi public val Res.plurals.numberOfSongsAvailable: PluralStringResource - get() = Plurals0.numberOfSongsAvailable + get() = CommonMainPlurals0.numberOfSongsAvailable @ExperimentalResourceApi private fun init_numberOfSongsAvailable(): PluralStringResource = org.jetbrains.compose.resources.PluralStringResource( "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 10, 124), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 10, + 124), ) ) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/String0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt similarity index 82% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/String0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt index f2164b60fd4..c7848ef50df 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/String0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonMainResourceAccessors/my/lib/res/String0.commonMain.kt @@ -7,7 +7,7 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.StringResource @ExperimentalResourceApi -private object String0 { +private object CommonMainString0 { public val PascalCase: StringResource by lazy { init_PascalCase() } @@ -32,84 +32,91 @@ private object String0 { @ExperimentalResourceApi public val Res.string.PascalCase: StringResource - get() = String0.PascalCase + get() = CommonMainString0.PascalCase @ExperimentalResourceApi private fun init_PascalCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:PascalCase", "PascalCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 172, 34), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 172, + 34), ) ) @ExperimentalResourceApi public val Res.string._1_kebab_case: StringResource - get() = String0._1_kebab_case + get() = CommonMainString0._1_kebab_case @ExperimentalResourceApi private fun init__1_kebab_case(): StringResource = org.jetbrains.compose.resources.StringResource( "string:_1_kebab_case", "_1_kebab_case", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 135, 36), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 135, + 36), ) ) @ExperimentalResourceApi public val Res.string.app_name: StringResource - get() = String0.app_name + get() = CommonMainString0.app_name @ExperimentalResourceApi private fun init_app_name(): StringResource = org.jetbrains.compose.resources.StringResource( "string:app_name", "app_name", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 207, 44), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 207, + 44), ) ) @ExperimentalResourceApi public val Res.string.camelCase: StringResource - get() = String0.camelCase + get() = CommonMainString0.camelCase @ExperimentalResourceApi private fun init_camelCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:camelCase", "camelCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 252, 29), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 252, + 29), ) ) @ExperimentalResourceApi public val Res.string.hello: StringResource - get() = String0.hello + get() = CommonMainString0.hello @ExperimentalResourceApi private fun init_hello(): StringResource = org.jetbrains.compose.resources.StringResource( "string:hello", "hello", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 282, 37), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 282, + 37), ) ) @ExperimentalResourceApi public val Res.string.multi_line: StringResource - get() = String0.multi_line + get() = CommonMainString0.multi_line @ExperimentalResourceApi private fun init_multi_line(): StringResource = org.jetbrains.compose.resources.StringResource( "string:multi_line", "multi_line", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 320, 178), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 320, + 178), ) ) @ExperimentalResourceApi public val Res.string.str_template: StringResource - get() = String0.str_template + get() = CommonMainString0.str_template @ExperimentalResourceApi private fun init_str_template(): StringResource = org.jetbrains.compose.resources.StringResource( "string:str_template", "str_template", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 499, 76), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 499, + 76), ) ) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/Res.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/commonResClass/my/lib/res/Res.kt diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt new file mode 100644 index 00000000000..50c85b8d351 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/desktopMainResourceAccessors/my/lib/res/String0.desktopMain.kt @@ -0,0 +1,26 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package my.lib.res + +import kotlin.OptIn +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +private object DesktopMainString0 { + public val desktop_str: StringResource by + lazy { init_desktop_str() } +} + +@ExperimentalResourceApi +public val Res.string.desktop_str: StringResource + get() = DesktopMainString0.desktop_str + +@ExperimentalResourceApi +private fun init_desktop_str(): StringResource = org.jetbrains.compose.resources.StringResource( + "string:desktop_str", "desktop_str", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "values/desktop_strings.desktopMain.cvr", 10, 39), + ) +) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt new file mode 100644 index 00000000000..a76ea38a4e2 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/androidMainResourceAccessors/app/group/resources_test/generated/resources/String0.androidMain.kt @@ -0,0 +1,26 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package app.group.resources_test.generated.resources + +import kotlin.OptIn +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +private object AndroidMainString0 { + public val android_str: StringResource by + lazy { init_android_str() } +} + +@ExperimentalResourceApi +internal val Res.string.android_str: StringResource + get() = AndroidMainString0.android_str + +@ExperimentalResourceApi +private fun init_android_str(): StringResource = org.jetbrains.compose.resources.StringResource( + "string:android_str", "android_str", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.androidMain.cvr", 10, + 39), + ) +) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Drawable0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt similarity index 93% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Drawable0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt index e424678b9ce..3a17148357f 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Drawable0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Drawable0.commonMain.kt @@ -7,7 +7,7 @@ import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi @ExperimentalResourceApi -private object Drawable0 { +private object CommonMainDrawable0 { public val _3_strange_name: DrawableResource by lazy { init__3_strange_name() } @@ -23,7 +23,7 @@ private object Drawable0 { @ExperimentalResourceApi internal val Res.drawable._3_strange_name: DrawableResource - get() = Drawable0._3_strange_name + get() = CommonMainDrawable0._3_strange_name @ExperimentalResourceApi private fun init__3_strange_name(): DrawableResource = @@ -36,7 +36,7 @@ private fun init__3_strange_name(): DrawableResource = @ExperimentalResourceApi internal val Res.drawable.camelCaseName: DrawableResource - get() = Drawable0.camelCaseName + get() = CommonMainDrawable0.camelCaseName @ExperimentalResourceApi private fun init_camelCaseName(): DrawableResource = @@ -49,7 +49,7 @@ private fun init_camelCaseName(): DrawableResource = @ExperimentalResourceApi internal val Res.drawable.vector: DrawableResource - get() = Drawable0.vector + get() = CommonMainDrawable0.vector @ExperimentalResourceApi private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( @@ -74,7 +74,7 @@ private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.Dr @ExperimentalResourceApi internal val Res.drawable.vector_2: DrawableResource - get() = Drawable0.vector_2 + get() = CommonMainDrawable0.vector_2 @ExperimentalResourceApi private fun init_vector_2(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Font0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt similarity index 92% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Font0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt index c3ec37ed30f..e756e8c84c8 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Font0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Font0.commonMain.kt @@ -7,14 +7,14 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.FontResource @ExperimentalResourceApi -private object Font0 { +private object CommonMainFont0 { public val emptyFont: FontResource by lazy { init_emptyFont() } } @ExperimentalResourceApi internal val Res.font.emptyFont: FontResource - get() = Font0.emptyFont + get() = CommonMainFont0.emptyFont @ExperimentalResourceApi private fun init_emptyFont(): FontResource = org.jetbrains.compose.resources.FontResource( diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Plurals0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt similarity index 84% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Plurals0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt index 2bb9863f7d7..f4fa373e40b 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Plurals0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/Plurals0.commonMain.kt @@ -7,20 +7,21 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.PluralStringResource @ExperimentalResourceApi -private object Plurals0 { +private object CommonMainPlurals0 { public val numberOfSongsAvailable: PluralStringResource by lazy { init_numberOfSongsAvailable() } } @ExperimentalResourceApi internal val Res.plurals.numberOfSongsAvailable: PluralStringResource - get() = Plurals0.numberOfSongsAvailable + get() = CommonMainPlurals0.numberOfSongsAvailable @ExperimentalResourceApi private fun init_numberOfSongsAvailable(): PluralStringResource = org.jetbrains.compose.resources.PluralStringResource( "plurals:numberOfSongsAvailable", "numberOfSongsAvailable", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 10, 124), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 10, + 124), ) ) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/String0.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt similarity index 81% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/String0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt index 0cb840a2711..ddfe1791a4b 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/String0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonMainResourceAccessors/app/group/resources_test/generated/resources/String0.commonMain.kt @@ -7,7 +7,7 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.StringResource @ExperimentalResourceApi -private object String0 { +private object CommonMainString0 { public val PascalCase: StringResource by lazy { init_PascalCase() } @@ -32,84 +32,91 @@ private object String0 { @ExperimentalResourceApi internal val Res.string.PascalCase: StringResource - get() = String0.PascalCase + get() = CommonMainString0.PascalCase @ExperimentalResourceApi private fun init_PascalCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:PascalCase", "PascalCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 172, 34), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 172, + 34), ) ) @ExperimentalResourceApi internal val Res.string._1_kebab_case: StringResource - get() = String0._1_kebab_case + get() = CommonMainString0._1_kebab_case @ExperimentalResourceApi private fun init__1_kebab_case(): StringResource = org.jetbrains.compose.resources.StringResource( "string:_1_kebab_case", "_1_kebab_case", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 135, 36), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 135, + 36), ) ) @ExperimentalResourceApi internal val Res.string.app_name: StringResource - get() = String0.app_name + get() = CommonMainString0.app_name @ExperimentalResourceApi private fun init_app_name(): StringResource = org.jetbrains.compose.resources.StringResource( "string:app_name", "app_name", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 207, 44), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 207, + 44), ) ) @ExperimentalResourceApi internal val Res.string.camelCase: StringResource - get() = String0.camelCase + get() = CommonMainString0.camelCase @ExperimentalResourceApi private fun init_camelCase(): StringResource = org.jetbrains.compose.resources.StringResource( "string:camelCase", "camelCase", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 252, 29), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 252, + 29), ) ) @ExperimentalResourceApi internal val Res.string.hello: StringResource - get() = String0.hello + get() = CommonMainString0.hello @ExperimentalResourceApi private fun init_hello(): StringResource = org.jetbrains.compose.resources.StringResource( "string:hello", "hello", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 282, 37), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 282, + 37), ) ) @ExperimentalResourceApi internal val Res.string.multi_line: StringResource - get() = String0.multi_line + get() = CommonMainString0.multi_line @ExperimentalResourceApi private fun init_multi_line(): StringResource = org.jetbrains.compose.resources.StringResource( "string:multi_line", "multi_line", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 320, 178), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 320, + 178), ) ) @ExperimentalResourceApi internal val Res.string.str_template: StringResource - get() = String0.str_template + get() = CommonMainString0.str_template @ExperimentalResourceApi private fun init_str_template(): StringResource = org.jetbrains.compose.resources.StringResource( "string:str_template", "str_template", setOf( - org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.cvr", 499, 76), + org.jetbrains.compose.resources.ResourceItem(setOf(), "values/strings.commonMain.cvr", 499, + 76), ) ) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/Res.kt rename to gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/commonResClass/app/group/resources_test/generated/resources/Res.kt diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt new file mode 100644 index 00000000000..aa67ed8e2da --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected/desktopMainResourceAccessors/app/group/resources_test/generated/resources/String0.desktopMain.kt @@ -0,0 +1,26 @@ +@file:OptIn(org.jetbrains.compose.resources.InternalResourceApi::class) + +package app.group.resources_test.generated.resources + +import kotlin.OptIn +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.StringResource + +@ExperimentalResourceApi +private object DesktopMainString0 { + public val desktop_str: StringResource by + lazy { init_desktop_str() } +} + +@ExperimentalResourceApi +internal val Res.string.desktop_str: StringResource + get() = DesktopMainString0.desktop_str + +@ExperimentalResourceApi +private fun init_desktop_str(): StringResource = org.jetbrains.compose.resources.StringResource( + "string:desktop_str", "desktop_str", + setOf( + org.jetbrains.compose.resources.ResourceItem(setOf(), + "values/desktop_strings.desktopMain.cvr", 10, 39), + ) +) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml new file mode 100644 index 00000000000..4855fd3e033 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/androidMain/composeResources/values/strings.xml @@ -0,0 +1,3 @@ + + Android string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/desktopMain/composeResources/values/desktop_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/desktopMain/composeResources/values/desktop_strings.xml new file mode 100644 index 00000000000..e3ea685b42f --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/commonResources/src/desktopMain/composeResources/values/desktop_strings.xml @@ -0,0 +1,3 @@ + + Desktop string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/Res.kt b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt similarity index 100% rename from gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/Res.kt rename to gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/commonResClass/me/app/jvmonlyresources/generated/resources/Res.kt diff --git a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/Drawable0.kt b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt similarity index 91% rename from gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/Drawable0.kt rename to gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt index cdc1831274d..0c5db2a8be9 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/Drawable0.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/jvmOnlyResources/expected/mainResourceAccessors/me/app/jvmonlyresources/generated/resources/Drawable0.main.kt @@ -7,14 +7,14 @@ import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi @ExperimentalResourceApi -private object Drawable0 { +private object MainDrawable0 { public val vector: DrawableResource by lazy { init_vector() } } @ExperimentalResourceApi internal val Res.drawable.vector: DrawableResource - get() = Drawable0.vector + get() = MainDrawable0.vector @ExperimentalResourceApi private fun init_vector(): DrawableResource = org.jetbrains.compose.resources.DrawableResource( diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/composeResources/values/android_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/composeResources/values/android_strings.xml new file mode 100644 index 00000000000..4855fd3e033 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/composeResources/values/android_strings.xml @@ -0,0 +1,3 @@ + + Android string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/kotlin/me/sample/app/App.android.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/kotlin/me/sample/app/App.android.kt new file mode 100644 index 00000000000..979e09a4df0 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/androidMain/kotlin/me/sample/app/App.android.kt @@ -0,0 +1,10 @@ +package me.sample.app + +import androidx.compose.runtime.Composable +import kmpresourcepublication.appmodule.generated.resources.Res +import kmpresourcepublication.appmodule.generated.resources.android_str +import org.jetbrains.compose.resources.stringResource + +@Composable +actual fun getPlatformSpecificString(): String = + stringResource(Res.string.android_str) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/commonMain/kotlin/me/sample/app/App.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/commonMain/kotlin/me/sample/app/App.kt index a747f1dd738..2699771cc0c 100644 --- a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/commonMain/kotlin/me/sample/app/App.kt +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/commonMain/kotlin/me/sample/app/App.kt @@ -18,4 +18,7 @@ fun App() { MyLibraryText(txt = txt) MyLibraryIcon(Modifier) } -} \ No newline at end of file +} + +@Composable +expect fun getPlatformSpecificString(): String \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/composeResources/values/ios_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/composeResources/values/ios_strings.xml new file mode 100644 index 00000000000..18c4ad6f071 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/composeResources/values/ios_strings.xml @@ -0,0 +1,3 @@ + + Ios string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/kotlin/me/sample/app/App.ios.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/kotlin/me/sample/app/App.ios.kt new file mode 100644 index 00000000000..ef04cb07d28 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/iosMain/kotlin/me/sample/app/App.ios.kt @@ -0,0 +1,10 @@ +package me.sample.app + +import androidx.compose.runtime.Composable +import kmpresourcepublication.appmodule.generated.resources.Res +import kmpresourcepublication.appmodule.generated.resources.iOS_str +import org.jetbrains.compose.resources.stringResource + +@Composable +actual fun getPlatformSpecificString(): String = + stringResource(Res.string.iOS_str) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/composeResources/values/js_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/composeResources/values/js_strings.xml new file mode 100644 index 00000000000..5164c3e17ca --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/composeResources/values/js_strings.xml @@ -0,0 +1,3 @@ + + JS string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/kotlin/me/sample/app/App.js.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/kotlin/me/sample/app/App.js.kt new file mode 100644 index 00000000000..5ad3a5a225b --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jsMain/kotlin/me/sample/app/App.js.kt @@ -0,0 +1,10 @@ +package me.sample.app + +import androidx.compose.runtime.Composable +import kmpresourcepublication.appmodule.generated.resources.Res +import kmpresourcepublication.appmodule.generated.resources.js_str +import org.jetbrains.compose.resources.stringResource + +@Composable +actual fun getPlatformSpecificString(): String = + stringResource(Res.string.js_str) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/composeResources/values/jvm_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/composeResources/values/jvm_strings.xml new file mode 100644 index 00000000000..e3ea685b42f --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/composeResources/values/jvm_strings.xml @@ -0,0 +1,3 @@ + + Desktop string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/kotlin/me/sample/app/App.jvm.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/kotlin/me/sample/app/App.jvm.kt new file mode 100644 index 00000000000..c789f3497c8 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/jvmMain/kotlin/me/sample/app/App.jvm.kt @@ -0,0 +1,10 @@ +package me.sample.app + +import androidx.compose.runtime.Composable +import kmpresourcepublication.appmodule.generated.resources.Res +import kmpresourcepublication.appmodule.generated.resources.desktop_str +import org.jetbrains.compose.resources.stringResource + +@Composable +actual fun getPlatformSpecificString(): String = + stringResource(Res.string.desktop_str) \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/composeResources/values/wasm_strings.xml b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/composeResources/values/wasm_strings.xml new file mode 100644 index 00000000000..1b1f8de78f2 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/composeResources/values/wasm_strings.xml @@ -0,0 +1,3 @@ + + Wasm string + \ No newline at end of file diff --git a/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/kotlin/me/sample/app/App.wasmJs.kt b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/kotlin/me/sample/app/App.wasmJs.kt new file mode 100644 index 00000000000..eea759a9c37 --- /dev/null +++ b/gradle-plugins/compose/src/test/test-projects/misc/kmpResourcePublication/appModule/src/wasmJsMain/kotlin/me/sample/app/App.wasmJs.kt @@ -0,0 +1,10 @@ +package me.sample.app + +import androidx.compose.runtime.Composable +import kmpresourcepublication.appmodule.generated.resources.Res +import kmpresourcepublication.appmodule.generated.resources.wasm_str +import org.jetbrains.compose.resources.stringResource + +@Composable +actual fun getPlatformSpecificString(): String = + stringResource(Res.string.wasm_str) \ No newline at end of file