From f46e8f3964556561899fc0dec7fa8fc588e8164a Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Sat, 6 Jun 2026 13:56:02 +0700 Subject: [PATCH 01/26] reworked strings generator --- gradle/moko.versions.toml | 2 +- .../gradle/generator/CodeGenerators.kt | 93 ++++- .../gradle/generator/GenerationResult.kt | 4 +- .../generator/PlatformResourceGenerator.kt | 7 + .../gradle/generator/ResourceTypeGenerator.kt | 370 ++++++++++++++++-- .../gradle/generator/ResourcesGenerator.kt | 25 +- .../factory/StringGeneratorFactory.kt | 10 +- .../string/AndroidStringResourceGenerator.kt | 2 + .../string/AppleStringResourceGenerator.kt | 79 +++- .../metadata/container/ContainerMetadata.kt | 1 + .../GenerateMultiplatformResourcesTask.kt | 1 + .../gradle/generator/StringBatchingTest.kt | 242 ++++++++++++ 12 files changed, 784 insertions(+), 52 deletions(-) create mode 100644 resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt diff --git a/gradle/moko.versions.toml b/gradle/moko.versions.toml index 80a171ead..e3ad299dd 100644 --- a/gradle/moko.versions.toml +++ b/gradle/moko.versions.toml @@ -1,5 +1,5 @@ [versions] -resourcesVersion = "0.26.4" +resourcesVersion = "0.27.0" [libraries] resources = { module = "dev.icerock.moko:resources", version.ref = "resourcesVersion" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index aa178062f..d4da8b690 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -138,6 +138,51 @@ internal fun TypeSpec.Builder.addValuesFunction( metadata: List, classType: ClassName, modifier: KModifier? = null, + isExpect: Boolean = false, +) { + addResourceValuesFunction( + metadata = metadata, + classType = classType, + modifier = modifier, + isOverride = true, + isExpect = isExpect + ) +} + +internal fun TypeSpec.Builder.addPlainValuesFunction( + metadata: List, + classType: ClassName, + modifier: KModifier? = null, + isExpect: Boolean = false, +) { + addResourceValuesFunction( + metadata = metadata, + classType = classType, + modifier = modifier, + isOverride = false, + isExpect = isExpect + ) +} + +internal fun TypeSpec.Builder.addAbstractValuesFunction( + classType: ClassName, +): TypeSpec.Builder { + val valuesFun: FunSpec = FunSpec.builder("values") + .returns( + ClassName(packageName = "kotlin.collections", "List") + .parameterizedBy(classType) + ) + .build() + + return addFunction(valuesFun) +} + +private fun TypeSpec.Builder.addResourceValuesFunction( + metadata: List, + classType: ClassName, + modifier: KModifier?, + isOverride: Boolean, + isExpect: Boolean = false, ) { // Find metadata type val resourceMetadata: T = metadata.first() @@ -160,6 +205,36 @@ internal fun TypeSpec.Builder.addValuesFunction( metadata.joinToString { it.key } } + val valuesFun: FunSpec = FunSpec.builder("values") + .also { + if (modifier != null) { + it.addModifiers(modifier) + } + if (isOverride) { + it.addModifiers(KModifier.OVERRIDE) + } + } + .apply { + if (isExpect) { + // No body for expect + } else { + addStatement("return listOf($languageKeysList)") + } + } + .returns( + ClassName(packageName = "kotlin.collections", "List") + .parameterizedBy(classType) + ) + .build() + + addFunction(valuesFun) +} + +internal fun TypeSpec.Builder.addBatchValuesFunction( + groupNames: List, + classType: ClassName, + modifier: KModifier? = null, +) { val valuesFun: FunSpec = FunSpec.builder("values") .also { if (modifier != null) { @@ -167,7 +242,23 @@ internal fun TypeSpec.Builder.addValuesFunction( } } .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") + .addCode( + CodeBlock.builder() + .apply { + if (groupNames.isEmpty()) { + addStatement("return emptyList()") + } else if (groupNames.size == 1) { + addStatement("return %N.values()", groupNames.single()) + } else { + add("return listOf(\n") + groupNames.forEach { groupName -> + add("%N.values(),\n", groupName) + } + add(").flatten()\n") + } + } + .build() + ) .returns( ClassName(packageName = "kotlin.collections", "List") .parameterizedBy(classType) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/GenerationResult.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/GenerationResult.kt index 39378e9e3..bb7a20dc4 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/GenerationResult.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/GenerationResult.kt @@ -4,10 +4,12 @@ package dev.icerock.gradle.generator +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.metadata.container.ContainerMetadata internal data class GenerationResult( val typeSpec: TypeSpec, - val metadata: ContainerMetadata + val metadata: ContainerMetadata, + val fileSpecs: List = emptyList() ) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt index 199aaa8f0..5dfefce8e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.metadata.resource.ResourceMetadata @@ -25,6 +26,12 @@ internal interface PlatformResourceGenerator { modifier: KModifier? = null, ) = Unit + fun supportsBatchedAccessors(): Boolean = false + + fun generateBatchedInitializer(metadata: T): CodeBlock = generateInitializer(metadata) + + fun generateAdditionalBatchedFiles(packageName: String): List = emptyList() + fun generateInitializer(metadata: T): CodeBlock fun generateResourceFiles(data: List) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 4b50f1a09..631b26d67 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -5,6 +5,9 @@ package dev.icerock.gradle.generator import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.PropertySpec @@ -12,6 +15,7 @@ import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.metadata.container.ContainerMetadata import dev.icerock.gradle.metadata.container.ResourceType import dev.icerock.gradle.metadata.resource.ResourceMetadata +import dev.icerock.gradle.utils.capitalize import dev.icerock.gradle.utils.filterClass import org.gradle.api.tasks.util.PatternFilterable import kotlin.reflect.KClass @@ -26,6 +30,9 @@ internal class ResourceTypeGenerator( private val generator: ResourceGenerator, private val platformResourceGenerator: PlatformResourceGenerator, private val filter: PatternFilterable.() -> Unit, + private val resourcesPackageName: String? = null, + private val generatePropertiesAsExtensions: Boolean = false, + private val batchSize: Int = DEFAULT_BATCH_SIZE, ) { fun generateMetadata(files: ResourcesFiles): List { return generator.generateMetadata(files.matching(filter).ownSourceSet.fileTree.files) @@ -36,6 +43,7 @@ internal class ResourceTypeGenerator( fun generateExpectObject( parentObjectName: String, resources: List, + sourceSetName: String, ): GenerationResult? { val typeMetadata: List = resources .filterClass(typeClass = metadataClass) @@ -52,39 +60,60 @@ internal class ResourceTypeGenerator( .addSuperinterface(Constants.resourceContainerName.parameterizedBy(resourceClass)) // implement ResourceContainer platform property .addOverridePlatformProperty() - // add all properties of available resources .also { builder -> - propertiesGenerationStrategy.generateProperties( - builder = builder, - resources = typeMetadata, - modifier = null, - generateProperty = { - generator.generateProperty(it).build() - } - ) + if (!generatePropertiesAsExtensions) { + // add all properties of available resources + propertiesGenerationStrategy.generateProperties( + builder = builder, + resources = typeMetadata, + modifier = null, + generateProperty = { + generator.generateProperty(it).build() + } + ) + } } // implement ResourceContainer values function .addOverrideAbstractValuesFunction(resourceClass) + val fileSpecs: List = if (generatePropertiesAsExtensions) { + createExpectExtensionFileSpecs( + parentObjectName = parentObjectName, + objectName = objectName, + sourceSetName = sourceSetName, + resources = typeMetadata + ) + } else { + emptyList() + } + return GenerationResult( typeSpec = objectBuilder.build(), metadata = ContainerMetadata( parentObjectName = parentObjectName, name = objectName, resourceType = resourceType, - resources = typeMetadata - ) + resources = typeMetadata, + sourceSetName = sourceSetName + ), + fileSpecs = fileSpecs ) } fun generateActualObject( parentObjectName: String, objects: List, + sourceSetName: String, ): GenerationResult? { val typeObject: ContainerMetadata = objects .singleOrNull { it.resourceType == resourceType } ?: return null - val typeResources: List = typeObject.resources.filterClass(metadataClass) + val typeResources: List = typeObject.resources + .filterClass(metadataClass) + .sortedBy { it.key } + val useBatchedAccessors: Boolean = generatePropertiesAsExtensions && + platformResourceGenerator.supportsBatchedAccessors() + val objectBuilder: TypeSpec.Builder = TypeSpec .objectBuilder(typeObject.name) .addModifiers(visibilityModifier) @@ -98,37 +127,70 @@ internal class ResourceTypeGenerator( modifier = KModifier.ACTUAL, ) } - // add all properties of object .also { builder -> - propertiesGenerationStrategy.generateProperties( - builder = builder, - resources = typeResources, - modifier = KModifier.ACTUAL, - generateProperty = ::createActualProperty - ) + if (useBatchedAccessors) { + builder.addBatchValuesFunction( + groupNames = getBatchGroupNames( + sourceSetName = typeObject.sourceSetName ?: sourceSetName, + objectName = typeObject.name, + resources = typeResources + ), + classType = resourceClass, + modifier = KModifier.ACTUAL + ) + } else if (!generatePropertiesAsExtensions) { + propertiesGenerationStrategy.generateProperties( + builder = builder, + resources = typeResources, + modifier = KModifier.ACTUAL, + generateProperty = ::createActualProperty + ) + } } .also { builder -> - platformResourceGenerator.generateAfterProperties( - builder = builder, - metadata = typeResources, - modifier = KModifier.ACTUAL, - ) + if (!useBatchedAccessors) { + platformResourceGenerator.generateAfterProperties( + builder = builder, + metadata = typeResources, + modifier = KModifier.ACTUAL, + ) + } } + val fileSpecs: List = if (generatePropertiesAsExtensions) { + if (useBatchedAccessors) { + createBatchFileSpecs( + parentObjectName = parentObjectName, + objectName = typeObject.name, + resourceSourceSetName = typeObject.sourceSetName ?: sourceSetName, + targetSourceSetName = sourceSetName, + resources = typeResources, + actualModifier = KModifier.ACTUAL + ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) + } else { + emptyList() + } + } else { + emptyList() + } + return GenerationResult( typeSpec = objectBuilder.build(), metadata = ContainerMetadata( parentObjectName = parentObjectName, name = typeObject.name, resourceType = resourceType, - resources = typeObject.resources - ) + resources = typeObject.resources, + sourceSetName = typeObject.sourceSetName + ), + fileSpecs = fileSpecs ) } fun generateObject( parentObjectName: String, resources: List, + sourceSetName: String, ): GenerationResult? { val typeResources: List = resources .filterClass(typeClass = metadataClass) @@ -138,6 +200,8 @@ internal class ResourceTypeGenerator( if (typeResources.isEmpty()) return null val objectName: String = resourceType.name.lowercase() + val useBatchedAccessors: Boolean = generatePropertiesAsExtensions && + platformResourceGenerator.supportsBatchedAccessors() val objectBuilder: TypeSpec.Builder = TypeSpec .objectBuilder(objectName) .addModifiers(visibilityModifier) @@ -150,30 +214,63 @@ internal class ResourceTypeGenerator( metadata = typeResources, ) } - // add all properties of object .also { builder -> - propertiesGenerationStrategy.generateProperties( - builder = builder, - resources = typeResources, - modifier = null, - generateProperty = ::createSimpleProperty - ) + if (useBatchedAccessors) { + builder.addBatchValuesFunction( + groupNames = getBatchGroupNames( + sourceSetName = sourceSetName, + objectName = objectName, + resources = typeResources + ), + classType = resourceClass + ) + } else if (!generatePropertiesAsExtensions) { + propertiesGenerationStrategy.generateProperties( + builder = builder, + resources = typeResources, + modifier = null, + generateProperty = ::createSimpleProperty + ) + } } .also { builder -> - platformResourceGenerator.generateAfterProperties( - builder = builder, - metadata = typeResources, - ) + if (!useBatchedAccessors) { + platformResourceGenerator.generateAfterProperties( + builder = builder, + metadata = typeResources, + ) + } + } + + val fileSpecs: List = if (generatePropertiesAsExtensions) { + val batchFiles = if (useBatchedAccessors) { + createBatchFileSpecs( + parentObjectName = parentObjectName, + objectName = objectName, + resourceSourceSetName = sourceSetName, + targetSourceSetName = sourceSetName, + resources = typeResources, + actualModifier = null + ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) + } else { + emptyList() } + batchFiles + } else { + emptyList() + } + return GenerationResult( typeSpec = objectBuilder.build(), metadata = ContainerMetadata( parentObjectName = parentObjectName, name = objectName, resourceType = resourceType, - resources = typeResources - ) + resources = typeResources, + sourceSetName = sourceSetName + ), + fileSpecs = fileSpecs ) } @@ -202,4 +299,199 @@ internal class ResourceTypeGenerator( .initializer(platformResourceGenerator.generateInitializer(resource)) .build() } + + private fun createExpectExtensionFileSpecs( + parentObjectName: String, + objectName: String, + sourceSetName: String, + resources: List, + ): List { + return resources.chunked(batchSize).mapIndexed { index, batch -> + val groupName: String = getBatchGroupName( + sourceSetName = sourceSetName, + objectName = objectName, + index = index + ) + + val fileSpec = FileSpec.builder( + packageName = requireResourcesPackageName(), + fileName = getBatchFileName( + objectName = objectName, + index = index, + targetSourceSetName = sourceSetName + ) + ) + + val groupObject = TypeSpec.objectBuilder(groupName) + .addModifiers(KModifier.INTERNAL, KModifier.EXPECT) + .addProperties( + batch.map { resource -> + generator.generateProperty(resource) + .build() + } + ) + .also { builder -> + builder.addPlainValuesFunction( + metadata = batch, + classType = resourceClass, + isExpect = true + ) + } + .build() + + fileSpec.addType(groupObject) + + batch.forEach { resource -> + fileSpec.addProperty( + PropertySpec.builder(resource.key, resourceClass) + .receiver(getReceiverClassName(parentObjectName, objectName)) + .addModifiers(visibilityModifier) + .getter( + FunSpec.getterBuilder() + .addStatement("return %N.%N", groupName, resource.key) + .build() + ) + .build() + ) + } + + fileSpec.build() + } + } + + private fun createBatchFileSpecs( + parentObjectName: String, + objectName: String, + resourceSourceSetName: String, + targetSourceSetName: String, + resources: List, + actualModifier: KModifier?, + ): List { + return resources.chunked(batchSize).mapIndexed { index, batch -> + val groupName: String = getBatchGroupName( + sourceSetName = resourceSourceSetName, + objectName = objectName, + index = index + ) + val fileSpec = createExtensionFileSpecBuilder( + fileName = "$groupName.$targetSourceSetName" + ) + + val groupObject = TypeSpec.objectBuilder(groupName) + .addModifiers(KModifier.INTERNAL) + .also { builder -> + if (actualModifier != null) builder.addModifiers(actualModifier) + } + .addProperties( + batch.map { resource -> + generator.generateProperty(resource) + .also { builder -> + if (actualModifier != null) builder.addModifiers(actualModifier) + } + .delegate(CodeBlock.of("lazy { init_%L() }", resource.key)) + .build() + } + ) + .also { builder -> + builder.addPlainValuesFunction( + metadata = batch, + classType = resourceClass, + modifier = actualModifier + ) + } + .build() + + fileSpec.addType(groupObject) + + if (actualModifier == null) { + batch.forEach { resource -> + fileSpec.addProperty( + PropertySpec.builder(resource.key, resourceClass) + .receiver(getReceiverClassName(parentObjectName, objectName)) + .addModifiers(visibilityModifier) + .getter( + FunSpec.getterBuilder() + .addStatement("return %N.%N", groupName, resource.key) + .build() + ) + .build() + ) + } + } + + batch.forEach { resource -> + fileSpec.addFunction( + FunSpec.builder("init_${resource.key}") + .addModifiers(KModifier.PRIVATE) + .returns(resourceClass) + .addStatement( + "return %L", + platformResourceGenerator.generateBatchedInitializer(resource) + ) + .build() + ) + } + + fileSpec.build() + } + } + + private fun createExtensionFileSpecBuilder(fileName: String): FileSpec.Builder { + return FileSpec.builder( + packageName = requireResourcesPackageName(), + fileName = fileName + ).also { fileSpec -> + platformResourceGenerator.imports().forEach { import -> + fileSpec.addImport(import.packageName, import.simpleNames) + } + } + } + + private fun getReceiverClassName(parentObjectName: String, objectName: String): ClassName { + return ClassName( + packageName = requireResourcesPackageName(), + parentObjectName, + objectName + ) + } + + private fun getBatchGroupNames( + sourceSetName: String, + objectName: String, + resources: List, + ): List { + return resources.chunked(batchSize).indices.map { index -> + getBatchGroupName( + sourceSetName = sourceSetName, + objectName = objectName, + index = index + ) + } + } + + private fun getBatchGroupName( + sourceSetName: String, + objectName: String, + index: Int, + ): String { + return "${sourceSetName.capitalize()}${objectName.capitalize()}$index" + } + + private fun getBatchFileName( + objectName: String, + index: Int, + targetSourceSetName: String, + ): String { + return "${objectName.capitalize()}$index.$targetSourceSetName" + } + + private fun requireResourcesPackageName(): String { + return requireNotNull(resourcesPackageName) { + "resourcesPackageName should be provided to generate extension properties" + } + } + + private companion object { + const val DEFAULT_BATCH_SIZE = 100 + } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt index bc34416f8..bc68327b8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt @@ -43,6 +43,7 @@ internal class ResourcesGenerator( ) val outputMetadata: MutableList = mutableListOf() + val additionalFileSpecs: MutableList = mutableListOf() if (inputMetadata.isEmpty()) { // we not have expect - we should generate simple object @@ -51,7 +52,8 @@ internal class ResourcesGenerator( outputMetadata = outputMetadata, parentObjectName = resourcesClassName, fileSpec = fileSpec, - inputMetadata = inputMetadata + inputMetadata = inputMetadata, + additionalFileSpecs = additionalFileSpecs ) } else { val inputMetadataObjectsMap: Map> = @@ -67,10 +69,12 @@ internal class ResourcesGenerator( val objects: List = typesGenerators.mapNotNull { typeGenerator -> typeGenerator.generateActualObject( parentObjectName = expectObjectName, - objects = inputMetadataList + objects = inputMetadataList, + sourceSetName = sourceSetName ) } objects.forEach { outputMetadata.add(it.metadata) } + objects.flatMapTo(additionalFileSpecs) { it.fileSpecs } val objectSpec: TypeSpec.Builder = TypeSpec.objectBuilder(expectObjectName) // default: object MR @@ -97,13 +101,17 @@ internal class ResourcesGenerator( outputMetadata = outputMetadata, parentObjectName = targetObjectResourceName, fileSpec = fileSpec, - inputMetadata = inputMetadata + inputMetadata = inputMetadata, + additionalFileSpecs = additionalFileSpecs ) } } // write file fileSpec.build().writeTo(sourcesGenerationDir) + additionalFileSpecs + .distinctBy { it.packageName + "." + it.name } + .forEach { it.writeTo(sourcesGenerationDir) } return outputMetadata } @@ -114,14 +122,17 @@ internal class ResourcesGenerator( outputMetadata: MutableList, fileSpec: Builder, inputMetadata: List, + additionalFileSpecs: MutableList, ) { val objects: List = typesGenerators.mapNotNull { typeGenerator -> typeGenerator.generateObject( parentObjectName = parentObjectName, - resources = ownMetadata + resources = ownMetadata, + sourceSetName = sourceSetName ) } objects.forEach { outputMetadata.add(it.metadata) } + objects.flatMapTo(additionalFileSpecs) { it.fileSpecs } val objectSpec: TypeSpec.Builder = TypeSpec.objectBuilder(parentObjectName) // default: object MR @@ -155,6 +166,7 @@ internal class ResourcesGenerator( ) val outputMetadata: MutableList = mutableListOf() + val additionalFileSpecs: MutableList = mutableListOf() // if previous levels doesn't have resources should use "MR" // but if resources is found, need generate "MRsourceSet" object @@ -170,6 +182,7 @@ internal class ResourcesGenerator( typeGenerator.generateExpectObject( parentObjectName = expectObjectName, resources = ownMetadata, + sourceSetName = sourceSetName ) } @@ -182,12 +195,16 @@ internal class ResourcesGenerator( objects.forEach { result -> objectSpec.addType(result.typeSpec) outputMetadata.add(result.metadata) + additionalFileSpecs.addAll(result.fileSpecs) } fileSpec.addType(objectSpec.build()) // write file fileSpec.build().writeTo(sourcesGenerationDir) + additionalFileSpecs + .distinctBy { it.packageName + "." + it.name } + .forEach { it.writeTo(sourcesGenerationDir) } return outputMetadata } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt index 65744168b..c96fbc6ef 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt @@ -34,7 +34,8 @@ internal class StringGeneratorFactory( private val kotlinPlatformType: KotlinPlatformType, private val kotlinKonanTarget: () -> KonanTarget, private val androidRClassPackage: () -> String, - private val iosBaseLocalizationRegion: () -> String + private val iosBaseLocalizationRegion: () -> String, + private val appleBundleIdentifier: () -> String, ) { fun create(): ResourceTypeGenerator { return ResourceTypeGenerator( @@ -47,7 +48,9 @@ internal class StringGeneratorFactory( strictLineBreaks = strictLineBreaks ), platformResourceGenerator = createPlatformStringGenerator(), - filter = { include("**/strings*.xml") } + filter = { include("**/strings*.xml") }, + resourcesPackageName = resourcesPackageName, + generatePropertiesAsExtensions = true ) } @@ -66,7 +69,8 @@ internal class StringGeneratorFactory( createApple = { AppleStringResourceGenerator( baseLocalizationRegion = iosBaseLocalizationRegion(), - resourcesGenerationDir = outputResourcesDir + resourcesGenerationDir = outputResourcesDir, + bundleIdentifier = appleBundleIdentifier() ) }, createJvm = { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt index ee9a1652f..2290ae236 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt @@ -29,6 +29,8 @@ internal class AndroidStringResourceGenerator( return CodeBlock.of("StringResource(R.string.%L)", metadata.key) } + override fun supportsBatchedAccessors(): Boolean = true + override fun generateBeforeProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt index 735bdca30..1043a4346 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt @@ -6,11 +6,14 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.PropertySpec +import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator -import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata @@ -20,6 +23,7 @@ import java.io.File internal class AppleStringResourceGenerator( private val baseLocalizationRegion: String, private val resourcesGenerationDir: File, + private val bundleIdentifier: String, ) : PlatformResourceGenerator { override fun imports(): List = emptyList() @@ -27,7 +31,56 @@ internal class AppleStringResourceGenerator( return CodeBlock.of( "StringResource(resourceId = %S, bundle = %L)", metadata.key, - Constants.Apple.platformContainerBundlePropertyName + "$PLATFORM_DETAILS_PROVIDER_NAME.$BUNDLE_PROPERTY_NAME" + ) + } + + override fun supportsBatchedAccessors(): Boolean = true + + override fun generateBatchedInitializer(metadata: StringMetadata): CodeBlock { + return generateInitializer(metadata) + } + + override fun generateAdditionalBatchedFiles(packageName: String): List { + val providerObject = TypeSpec.objectBuilder(PLATFORM_DETAILS_PROVIDER_NAME) + .addModifiers(KModifier.INTERNAL) + .addProperty( + PropertySpec.builder(BUNDLE_PROPERTY_NAME, Constants.Apple.nsBundleName) + .delegate( + CodeBlock.of( + "lazy { NSBundle.loadableBundle(%S) }", + bundleIdentifier + ) + ) + .build() + ) + .addProperty( + PropertySpec.builder(DETAILS_PROPERTY_NAME, Constants.resourcePlatformDetailsName) + .getter( + FunSpec.getterBuilder() + .addStatement( + "return %T(%N)", + Constants.resourcePlatformDetailsName, + BUNDLE_PROPERTY_NAME + ) + .build() + ) + .build() + ) + .build() + + return listOf( + FileSpec.builder(packageName, PLATFORM_DETAILS_PROVIDER_NAME) + .addImport( + Constants.Apple.nsBundleName.packageName, + Constants.Apple.nsBundleName.simpleNames + ) + .addImport( + Constants.Apple.loadableBundleName.packageName, + Constants.Apple.loadableBundleName.simpleNames + ) + .addType(providerObject) + .build() ) } @@ -45,7 +98,21 @@ internal class AppleStringResourceGenerator( metadata: List, modifier: KModifier?, ) { - builder.addAppleContainerBundleInitializerProperty(modifier) + val resourcePlatformDetailsPropertySpec = PropertySpec + .builder( + Constants.PlatformDetails.platformDetailsPropertyName, + Constants.resourcePlatformDetailsName + ) + .also { + if (modifier != null) { + it.addModifiers(modifier) + } + } + .addModifiers(KModifier.OVERRIDE) + .initializer(CodeBlock.of("$PLATFORM_DETAILS_PROVIDER_NAME.$DETAILS_PROPERTY_NAME")) + .build() + + builder.addProperty(resourcePlatformDetailsPropertySpec) } override fun generateAfterProperties( @@ -79,4 +146,10 @@ internal class AppleStringResourceGenerator( regionFile.writeText(content) } } + + private companion object { + const val PLATFORM_DETAILS_PROVIDER_NAME = "PlatformDetailsProvider" + const val BUNDLE_PROPERTY_NAME = "bundle" + const val DETAILS_PROPERTY_NAME = "details" + } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/container/ContainerMetadata.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/container/ContainerMetadata.kt index 21ac71b86..ab6968940 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/container/ContainerMetadata.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/container/ContainerMetadata.kt @@ -16,6 +16,7 @@ internal data class ContainerMetadata( val parentObjectName: String, val resourceType: ResourceType, val resources: List, + val sourceSetName: String? = null, ) { fun contentHash(): String = resources.mapNotNull { it.contentHash() }.calculateHash() } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt index edbdc11f5..3a88b4f49 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt @@ -215,6 +215,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { kotlinKonanTarget = ::kotlinKonanTarget, androidRClassPackage = androidRClassPackage::get, iosBaseLocalizationRegion = iosBaseLocalizationRegion::get, + appleBundleIdentifier = appleBundleIdentifier::get, ).create(), PluralGeneratorFactory( resourcesPackageName = resourcesPackageName.get(), diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt new file mode 100644 index 000000000..4be81507a --- /dev/null +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt @@ -0,0 +1,242 @@ +/* + * Copyright 2026 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator + +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.KModifier +import dev.icerock.gradle.generator.resources.string.AndroidStringResourceGenerator +import dev.icerock.gradle.generator.resources.string.AppleStringResourceGenerator +import dev.icerock.gradle.generator.resources.string.StringResourceGenerator +import dev.icerock.gradle.metadata.container.ResourceType +import dev.icerock.gradle.metadata.resource.StringMetadata +import java.io.File +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class StringBatchingTest { + @Test + fun commonStringsAreGeneratedAsExtensionAccessors() { + val result = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 1), + sourceSetName = COMMON_SOURCE_SET + )!! + + val containerSource = result.typeSpec.toString() + assertFalse(containerSource.contains("val key_000: StringResource"), containerSource) + assertTrue( + result.typeSpec.propertySpecs.any { it.name == "__platformDetails" }, + containerSource + ) + assertTrue( + result.typeSpec.funSpecs.any { it.name == "values" }, + containerSource + ) + + assertEquals(expected = 1, actual = result.fileSpecs.size) + assertEquals(expected = "Strings0.commonMain", actual = result.fileSpecs.single().name) + + val accessorSource = result.fileSpecs.single().toString() + assertTrue( + accessorSource.contains("internal expect object CommonMainStrings0"), + accessorSource + ) + assertTrue( + accessorSource.contains("public val MR.strings.key_000: StringResource"), + accessorSource + ) + assertTrue( + accessorSource.contains("get() = CommonMainStrings0.key_000"), + accessorSource + ) + } + + @Test + fun commonStringsAreSplitIntoHundredItemBatches() { + val oneHundredResult = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 100), + sourceSetName = COMMON_SOURCE_SET + )!! + val oneHundredOneResult = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 101), + sourceSetName = COMMON_SOURCE_SET + )!! + val largeResult = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 1_000), + sourceSetName = COMMON_SOURCE_SET + )!! + + assertEquals(expected = 1, actual = oneHundredResult.fileSpecs.size) + assertEquals( + expected = listOf("Strings0.commonMain", "Strings1.commonMain"), + actual = oneHundredOneResult.fileSpecs.map { it.name } + ) + assertEquals(expected = 10, actual = largeResult.fileSpecs.size) + assertEquals(expected = "Strings0.commonMain", actual = largeResult.fileSpecs.first().name) + assertEquals(expected = "Strings9.commonMain", actual = largeResult.fileSpecs.last().name) + } + + @Test + fun androidActualStringsUseInternalBatchesAndAggregatedValues() { + val commonResult = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 101), + sourceSetName = COMMON_SOURCE_SET + )!! + val androidResult = createAndroidGenerator().generateActualObject( + parentObjectName = MR_CLASS_NAME, + objects = listOf(commonResult.metadata), + sourceSetName = ANDROID_SOURCE_SET + )!! + + val containerSource = androidResult.typeSpec.toString() + assertFalse(containerSource.contains("val key_000: StringResource"), containerSource) + assertTrue(containerSource.contains("CommonMainStrings0.values()"), containerSource) + assertTrue(containerSource.contains("CommonMainStrings1.values()"), containerSource) + + val firstBatchSource = androidResult.fileSpecs + .single { it.name == "CommonMainStrings0.androidMain" } + .toString() + assertTrue( + firstBatchSource.contains("internal actual object CommonMainStrings0"), + firstBatchSource + ) + assertTrue( + firstBatchSource.contains("public actual val key_000: StringResource by"), + firstBatchSource + ) + assertFalse( + firstBatchSource.contains("public actual val MR.strings.key_000: StringResource"), + firstBatchSource + ) + assertTrue(firstBatchSource.contains("private fun init_key_000(): StringResource"), firstBatchSource) + assertTrue(firstBatchSource.contains("StringResource(R.string.key_000)"), firstBatchSource) + + val secondBatchSource = androidResult.fileSpecs + .single { it.name == "CommonMainStrings1.androidMain" } + .toString() + assertTrue(secondBatchSource.contains("StringResource(R.string.key_100)"), secondBatchSource) + } + + @Test + fun appleActualStringsUsePlatformDetailsProvider() { + val commonResult = createCommonGenerator().generateExpectObject( + parentObjectName = MR_CLASS_NAME, + resources = createStrings(count = 1), + sourceSetName = COMMON_SOURCE_SET + )!! + val appleResult = createAppleGenerator().generateActualObject( + parentObjectName = MR_CLASS_NAME, + objects = listOf(commonResult.metadata), + sourceSetName = IOS_SOURCE_SET + )!! + + val containerSource = appleResult.typeSpec.toString() + assertTrue(containerSource.contains("PlatformDetailsProvider.details"), containerSource) + + val batchSource = appleResult.fileSpecs + .single { it.name == "CommonMainStrings0.iosMain" } + .toString() + assertTrue( + batchSource.contains("internal actual object CommonMainStrings0"), + batchSource + ) + assertTrue(batchSource.contains("public actual val key_000: StringResource by"), batchSource) + assertTrue( + batchSource.contains("resourceId = \"key_000\""), + batchSource + ) + assertTrue( + batchSource.contains("PlatformDetailsProvider.bundle"), + batchSource + ) + assertFalse( + batchSource.contains("public actual val MR.strings.key_000: StringResource"), + batchSource + ) + + val providerSource = appleResult.fileSpecs + .single { it.name == "PlatformDetailsProvider" } + .toString() + assertTrue(providerSource.contains("internal object PlatformDetailsProvider"), providerSource) + assertTrue(providerSource.contains("NSBundle.loadableBundle(\"com.example.bundle\")"), providerSource) + assertTrue(providerSource.contains("ResourcePlatformDetails(bundle)"), providerSource) + } + + private fun createCommonGenerator(): ResourceTypeGenerator { + return createGenerator(platformResourceGenerator = EmptyStringPlatformResourceGenerator()) + } + + private fun createAndroidGenerator(): ResourceTypeGenerator { + return createGenerator( + platformResourceGenerator = AndroidStringResourceGenerator( + androidRClassPackage = "com.example", + resourcesGenerationDir = File(".") + ) + ) + } + + private fun createAppleGenerator(): ResourceTypeGenerator { + return createGenerator( + platformResourceGenerator = AppleStringResourceGenerator( + baseLocalizationRegion = "en", + resourcesGenerationDir = File("."), + bundleIdentifier = "com.example.bundle" + ) + ) + } + + private fun createGenerator( + platformResourceGenerator: PlatformResourceGenerator, + ): ResourceTypeGenerator { + return ResourceTypeGenerator( + propertiesGenerationStrategy = FlatPropertiesGenerationStrategy(), + resourceClass = Constants.stringResourceName, + resourceType = ResourceType.STRINGS, + metadataClass = StringMetadata::class, + visibilityModifier = KModifier.PUBLIC, + generator = StringResourceGenerator(strictLineBreaks = false), + platformResourceGenerator = platformResourceGenerator, + filter = {}, + resourcesPackageName = PACKAGE_NAME, + generatePropertiesAsExtensions = true + ) + } + + private fun createStrings(count: Int): List { + return (0 until count).map { index -> + val key = "key_${index.toString().padStart(length = 3, padChar = '0')}" + StringMetadata( + key = key, + values = listOf( + StringMetadata.LocaleItem( + locale = "", + value = key + ) + ) + ) + } + } + + private class EmptyStringPlatformResourceGenerator : PlatformResourceGenerator { + override fun imports(): List = emptyList() + override fun generateInitializer(metadata: StringMetadata): CodeBlock = CodeBlock.of("") + override fun generateResourceFiles(data: List) = Unit + } + + private companion object { + const val PACKAGE_NAME = "com.example.generated" + const val MR_CLASS_NAME = "MR" + const val COMMON_SOURCE_SET = "commonMain" + const val ANDROID_SOURCE_SET = "androidMain" + const val IOS_SOURCE_SET = "iosMain" + } +} From 3192243509a3436badb123935402f86ac26821f8 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 11 Jun 2026 23:20:09 +0700 Subject: [PATCH 02/26] Batch generated resource accessors --- .../gradle/generator/CodeGenerators.kt | 312 ++++++++++--- .../dev/icerock/gradle/generator/Constants.kt | 6 + .../generator/PlatformContainerGenerator.kt | 2 + .../generator/PlatformResourceGenerator.kt | 13 +- .../generator/PropertiesGenerationStrategy.kt | 68 +++ .../gradle/generator/ResourceTypeGenerator.kt | 414 +++++++++--------- .../gradle/generator/ResourcesGenerator.kt | 2 + .../container/AppleContainerGenerator.kt | 45 +- .../container/JvmContainerGenerator.kt | 47 +- .../factory/AssetGeneratorFactory.kt | 2 + .../factory/ColorGeneratorFactory.kt | 4 +- .../generator/factory/FileGeneratorFactory.kt | 2 + .../generator/factory/FontGeneratorFactory.kt | 3 +- .../factory/ImageGeneratorFactory.kt | 2 + .../factory/PluralGeneratorFactory.kt | 3 +- .../factory/StringGeneratorFactory.kt | 7 +- .../resources/NOPResourceGenerator.kt | 6 +- .../asset/AppleAssetResourceGenerator.kt | 22 +- .../asset/JvmAssetResourceGenerator.kt | 16 + .../color/AppleColorResourceGenerator.kt | 20 +- .../file/AppleFileResourceGenerator.kt | 21 +- .../file/JvmFileResourceGenerator.kt | 15 + .../font/AppleFontResourceGenerator.kt | 20 +- .../font/JvmFontResourceGenerator.kt | 15 + .../image/AppleImageResourceGenerator.kt | 20 +- .../image/JvmImageResourceGenerator.kt | 34 ++ .../plural/ApplePluralResourceGenerator.kt | 20 +- .../plural/JsPluralResourceGenerator.kt | 26 ++ .../plural/JvmPluralResourceGenerator.kt | 21 + .../string/AndroidStringResourceGenerator.kt | 2 - .../string/AppleStringResourceGenerator.kt | 88 +--- .../string/JsStringResourceGenerator.kt | 26 ++ .../string/JvmStringResourceGenerator.kt | 21 + .../gradle/metadata/MetadataException.kt | 2 +- .../metadata/resource/ResourceMetadata.kt | 12 +- .../GenerateMultiplatformResourcesTask.kt | 5 +- .../moko/resources/ResourceContainer.kt | 4 + 37 files changed, 992 insertions(+), 356 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index d4da8b690..834300fd2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -7,7 +7,9 @@ package dev.icerock.gradle.generator import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy @@ -21,6 +23,7 @@ import dev.icerock.gradle.generator.platform.js.JsFilePathMode import dev.icerock.gradle.metadata.resource.HierarchyMetadata import dev.icerock.gradle.metadata.resource.ResourceMetadata import org.gradle.api.GradleException +import kotlin.DeprecationLevel internal fun TypeSpec.Builder.addAppleResourcesBundleProperty(bundleIdentifier: String) { val bundleProperty: PropertySpec = PropertySpec.builder( @@ -33,6 +36,17 @@ internal fun TypeSpec.Builder.addAppleResourcesBundleProperty(bundleIdentifier: addProperty(bundleProperty) } +internal fun FileSpec.Builder.addAppleResourcesBundleProperty(bundleIdentifier: String) { + addProperty( + PropertySpec.builder( + Apple.resourcesBundlePropertyName, + Apple.nsBundleName, + KModifier.PRIVATE + ).delegate(CodeBlock.of("lazy { NSBundle.loadableBundle(%S) }", bundleIdentifier)) + .build() + ) +} + internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { val bundleProperty: PropertySpec = PropertySpec.builder("contentHash", STRING, KModifier.PRIVATE) @@ -45,24 +59,26 @@ internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { internal fun TypeSpec.Builder.addAppleContainerBundleInitializerProperty( modifier: KModifier? = null, ) { - val codeBlock = "${PlatformDetails.platformDetailsClass}(${Apple.resourcesBundlePropertyName})" + addContainerPlatformDetailsProperty( + initializer = CodeBlock.of(PlatformDetails.providerReference), + modifier = modifier + ) +} - val resourcePlatformDetailsPropertySpec = PropertySpec - .builder( - PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName +internal fun TypeSpec.Builder.addAppleBatchedBundleInitializerProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of( + "${PlatformDetails.platformDetailsClass}(${Apple.resourcesBundlePropertyName})" ) - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .initializer( - CodeBlock.of(codeBlock) - ).build() + ) +} - addProperty(resourcePlatformDetailsPropertySpec) +internal fun FileSpec.Builder.addAppleBatchedBundleInitializerProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of( + "${PlatformDetails.platformDetailsClass}(${Apple.resourcesBundlePropertyName})" + ) + ) } internal fun TypeSpec.Builder.addJvmClassLoaderProperty(resourcesClassName: String) { @@ -76,27 +92,41 @@ internal fun TypeSpec.Builder.addJvmClassLoaderProperty(resourcesClassName: Stri addProperty(property) } +internal fun FileSpec.Builder.addJvmClassLoaderProperty(resourcesClassName: String) { + addImport("kotlin.jvm", "java") + addProperty( + PropertySpec.builder( + Jvm.resourcesClassLoaderPropertyName, + Jvm.classLoaderName, + KModifier.PRIVATE + ).initializer(CodeBlock.of("$resourcesClassName::class.java.classLoader")) + .build() + ) +} + internal fun TypeSpec.Builder.addJvmPlatformResourceClassLoaderProperty( modifier: KModifier? = null, ) { - val codeBlock = - "${PlatformDetails.platformDetailsClass}(${Jvm.resourcesClassLoaderPropertyName})" + addContainerPlatformDetailsProperty( + initializer = CodeBlock.of(PlatformDetails.providerReference), + modifier = modifier + ) +} - val resourcePlatformDetailsPropertySpec = PropertySpec - .builder( - PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName +internal fun TypeSpec.Builder.addJvmBatchedPlatformResourceClassLoaderProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of( + "${PlatformDetails.platformDetailsClass}(${Jvm.resourcesClassLoaderPropertyName})" ) - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .initializer(CodeBlock.of(codeBlock)) - .build() + ) +} - addProperty(resourcePlatformDetailsPropertySpec) +internal fun FileSpec.Builder.addJvmBatchedPlatformResourceClassLoaderProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of( + "${PlatformDetails.platformDetailsClass}(${Jvm.resourcesClassLoaderPropertyName})" + ) + ) } internal fun TypeSpec.Builder.addJvmPlatformResourceBundleProperty( @@ -113,37 +143,53 @@ internal fun TypeSpec.Builder.addJvmPlatformResourceBundleProperty( addProperty(property) } +internal fun FileSpec.Builder.addJvmPlatformResourceBundleProperty( + bundlePropertyName: String, + bundlePath: String +) { + addProperty( + PropertySpec.builder( + name = bundlePropertyName, + type = STRING, + KModifier.PRIVATE + ).initializer(CodeBlock.of("\"%L/%L\"", Jvm.localizationDir, bundlePath)) + .build() + ) +} + internal fun TypeSpec.Builder.addEmptyPlatformResourceProperty( modifier: KModifier? = null, ) { - val resourcePlatformDetailsPropertySpec = PropertySpec - .builder( - PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName - ) - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .initializer( - CodeBlock.of("${PlatformDetails.platformDetailsClass}()") - ).build() + addContainerPlatformDetailsProperty( + initializer = CodeBlock.of("${PlatformDetails.platformDetailsClass}()"), + modifier = modifier + ) +} - addProperty(resourcePlatformDetailsPropertySpec) +internal fun TypeSpec.Builder.addEmptyBatchedPlatformResourceProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of("${PlatformDetails.platformDetailsClass}()") + ) +} + +internal fun FileSpec.Builder.addEmptyBatchedPlatformResourceProperty() { + addBatchedPlatformDetailsProperty( + initializer = CodeBlock.of("${PlatformDetails.platformDetailsClass}()") + ) } internal fun TypeSpec.Builder.addValuesFunction( metadata: List, classType: ClassName, modifier: KModifier? = null, + memberModifier: KModifier? = null, isExpect: Boolean = false, ) { addResourceValuesFunction( metadata = metadata, classType = classType, modifier = modifier, + memberModifier = memberModifier, isOverride = true, isExpect = isExpect ) @@ -153,12 +199,14 @@ internal fun TypeSpec.Builder.addPlainValuesFunction( metadata: List, classType: ClassName, modifier: KModifier? = null, + memberModifier: KModifier? = null, isExpect: Boolean = false, ) { addResourceValuesFunction( metadata = metadata, classType = classType, modifier = modifier, + memberModifier = memberModifier, isOverride = false, isExpect = isExpect ) @@ -181,6 +229,7 @@ private fun TypeSpec.Builder.addResourceValuesFunction( metadata: List, classType: ClassName, modifier: KModifier?, + memberModifier: KModifier?, isOverride: Boolean, isExpect: Boolean = false, ) { @@ -207,6 +256,9 @@ private fun TypeSpec.Builder.addResourceValuesFunction( val valuesFun: FunSpec = FunSpec.builder("values") .also { + if (memberModifier != null) { + it.addModifiers(memberModifier) + } if (modifier != null) { it.addModifiers(modifier) } @@ -215,9 +267,7 @@ private fun TypeSpec.Builder.addResourceValuesFunction( } } .apply { - if (isExpect) { - // No body for expect - } else { + if (!isExpect) { addStatement("return listOf($languageKeysList)") } } @@ -268,12 +318,38 @@ internal fun TypeSpec.Builder.addBatchValuesFunction( addFunction(valuesFun) } +internal fun TypeSpec.Builder.addReferencedValuesFunction( + propertyReferences: List, + classType: ClassName, + memberModifier: KModifier? = null, +) { + val valuesFun: FunSpec = FunSpec.builder("values") + .also { + if (memberModifier != null) { + it.addModifiers(memberModifier) + } + } + .addStatement( + "return listOf(%L)", + propertyReferences.joinToString() + ) + .returns( + ClassName(packageName = "kotlin.collections", "List") + .parameterizedBy(classType) + ) + .build() + + addFunction(valuesFun) +} + internal fun TypeSpec.Builder.addOverridePlatformProperty(): TypeSpec.Builder { val resourcePlatformDetailsPropertySpec = PropertySpec.builder( PlatformDetails.platformDetailsPropertyName, Constants.resourcePlatformDetailsName, KModifier.OVERRIDE - ).build() + ) + .addAnnotation(hiddenInternalApiAnnotation()) + .build() return addProperty(resourcePlatformDetailsPropertySpec) } @@ -292,6 +368,13 @@ internal fun TypeSpec.Builder.addOverrideAbstractValuesFunction( return addFunction(valuesFun) } +private fun hiddenInternalApiAnnotation(): AnnotationSpec { + return AnnotationSpec.builder(Deprecated::class) + .addMember("message = %S", "Internal resource container detail") + .addMember("level = %T.HIDDEN", DeprecationLevel::class) + .build() +} + internal fun TypeSpec.Builder.addJsFallbackProperty( fallbackFilePath: String, filePathMode: JsFilePathMode @@ -310,6 +393,24 @@ internal fun TypeSpec.Builder.addJsFallbackProperty( addProperty(property) } +internal fun FileSpec.Builder.addJsFallbackProperty( + fallbackFilePath: String, + filePathMode: JsFilePathMode +) { + addProperty( + PropertySpec + .builder(Constants.Js.fallbackFilePropertyName, String::class, KModifier.PRIVATE) + .initializer( + CodeBlock.of( + "${filePathMode.format} as %T", + filePathMode.argument(fallbackFilePath), + String::class + ) + ) + .build() + ) +} + internal fun TypeSpec.Builder.addJsSupportedLocalesProperty( bcpLangToPath: List>, filePathMode: JsFilePathMode @@ -340,6 +441,36 @@ internal fun TypeSpec.Builder.addJsSupportedLocalesProperty( addProperty(property) } +internal fun FileSpec.Builder.addJsSupportedLocalesProperty( + bcpLangToPath: List>, + filePathMode: JsFilePathMode +) { + addProperty( + PropertySpec + .builder( + Constants.Js.supportedLocalesPropertyName, + Constants.Js.supportedLocalesName, + KModifier.PRIVATE + ).initializer( + CodeBlock + .builder() + .apply { + add("%T(listOf(\n", Constants.Js.supportedLocalesName) + bcpLangToPath.forEach { (bcpLang, filePath) -> + add( + "%T(%S, ${filePathMode.format} as %T),\n", + Constants.Js.supportedLocaleName, + bcpLang, + filePathMode.argument(filePath), + String::class + ) + } + add("))") + }.build() + ).build() + ) +} + internal fun TypeSpec.Builder.addJsContainerStringsLoaderProperty() { val property = PropertySpec.builder( Constants.Js.stringsLoaderPropertyName, @@ -354,3 +485,86 @@ internal fun TypeSpec.Builder.addJsContainerStringsLoaderProperty() { ).build() addProperty(property) } + +internal fun TypeSpec.Builder.addJsBatchedStringsLoaderProperty() { + val property = PropertySpec.builder( + Constants.Js.stringsLoaderPropertyName, + Constants.Js.stringLoaderName, + KModifier.PRIVATE + ).initializer( + CodeBlock.of( + "${Constants.Js.remoteStringLoaderClassName}.Impl(supportedLocales = %N, fallbackFileUri = %N)", + Constants.Js.supportedLocalesPropertyName, + Constants.Js.fallbackFilePropertyName + ) + ).build() + addProperty(property) +} + +internal fun FileSpec.Builder.addJsBatchedStringsLoaderProperty() { + addProperty( + PropertySpec.builder( + Constants.Js.stringsLoaderPropertyName, + Constants.Js.stringLoaderName, + KModifier.PRIVATE + ).initializer( + CodeBlock.of( + "${Constants.Js.remoteStringLoaderClassName}.Impl(supportedLocales = %N, fallbackFileUri = %N)", + Constants.Js.supportedLocalesPropertyName, + Constants.Js.fallbackFilePropertyName + ) + ).build() + ) +} + +private fun TypeSpec.Builder.addContainerPlatformDetailsProperty( + initializer: CodeBlock, + modifier: KModifier? = null, +) { + val resourcePlatformDetailsPropertySpec = PropertySpec + .builder( + PlatformDetails.platformDetailsPropertyName, + Constants.resourcePlatformDetailsName + ) + .addAnnotation(hiddenInternalApiAnnotation()) + .also { + if (modifier != null) { + it.addModifiers(modifier) + } + } + .addModifiers(KModifier.OVERRIDE) + .initializer(initializer) + .build() + + addProperty(resourcePlatformDetailsPropertySpec) +} + +private fun TypeSpec.Builder.addBatchedPlatformDetailsProperty( + initializer: CodeBlock, +) { + val resourcePlatformDetailsPropertySpec = PropertySpec + .builder( + PlatformDetails.platformDetailsPropertyName, + Constants.resourcePlatformDetailsName, + KModifier.PRIVATE + ) + .initializer(initializer) + .build() + + addProperty(resourcePlatformDetailsPropertySpec) +} + +private fun FileSpec.Builder.addBatchedPlatformDetailsProperty( + initializer: CodeBlock, +) { + addProperty( + PropertySpec + .builder( + PlatformDetails.platformDetailsPropertyName, + Constants.resourcePlatformDetailsName, + KModifier.PRIVATE + ) + .initializer(initializer) + .build() + ) +} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/Constants.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/Constants.kt index c6a8ecefb..0bb46a1ff 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/Constants.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/Constants.kt @@ -23,6 +23,9 @@ internal object Constants { object PlatformDetails { const val platformDetailsPropertyName = "__platformDetails" const val platformDetailsClass: String = "ResourcePlatformDetails" + const val providerObjectName = "PlatformDetailsProvider" + const val providerDetailsPropertyName = "details" + const val providerReference = "$providerObjectName.$providerDetailsPropertyName" } object Apple { @@ -34,12 +37,15 @@ internal object Constants { const val resourcesBundlePropertyName = "bundle" private const val containerBundlePropertyName = "nsBundle" val platformContainerBundlePropertyName = "$platformDetailsPropertyName.$containerBundlePropertyName" + val providerBundleReference = "${PlatformDetails.providerReference}.$containerBundlePropertyName" } object Jvm { val classLoaderName = ClassName("java.lang", "ClassLoader") const val resourcesClassLoaderPropertyName = "resourcesClassLoader" const val localizationDir = "localization" + val providerClassLoaderReference = + "${PlatformDetails.providerReference}.$resourcesClassLoaderPropertyName" } object Js { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformContainerGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformContainerGenerator.kt index a7ee8813c..eb68adcfd 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformContainerGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformContainerGenerator.kt @@ -5,10 +5,12 @@ package dev.icerock.gradle.generator import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.TypeSpec internal interface PlatformContainerGenerator { fun getImports(): List = emptyList() + fun generateAdditionalFiles(packageName: String): List = emptyList() fun generateBeforeTypes(objectName: String, builder: TypeSpec.Builder) = Unit fun generateAfterTypes(builder: TypeSpec.Builder) = Unit } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt index 5dfefce8e..fd7d1cd66 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt @@ -20,16 +20,25 @@ internal interface PlatformResourceGenerator { modifier: KModifier? = null, ) = Unit + fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + fun generateAfterProperties( builder: Builder, metadata: List, modifier: KModifier? = null, ) = Unit - fun supportsBatchedAccessors(): Boolean = false - fun generateBatchedInitializer(metadata: T): CodeBlock = generateInitializer(metadata) + fun generateBatchedInitializer( + metadata: T, + batchObjectName: String, + ): CodeBlock = generateBatchedInitializer(metadata) + fun generateAdditionalBatchedFiles(packageName: String): List = emptyList() fun generateInitializer(metadata: T): CodeBlock diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PropertiesGenerationStrategy.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PropertiesGenerationStrategy.kt index 739f77914..3d9b7a18e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PropertiesGenerationStrategy.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PropertiesGenerationStrategy.kt @@ -17,6 +17,13 @@ internal interface PropertiesGenerationStrategy { modifier: KModifier?, generateProperty: (T) -> PropertySpec, ) + + fun generateSkeleton( + builder: TypeSpec.Builder, + resources: List, + modifier: KModifier?, + generateProperty: (T) -> PropertySpec, + ) = Unit } internal class FlatPropertiesGenerationStrategy : @@ -50,6 +57,19 @@ internal class HierarchyPropertiesGenerationStrategy : ) } + override fun generateSkeleton( + builder: TypeSpec.Builder, + resources: List, + modifier: KModifier?, + generateProperty: (T) -> PropertySpec, + ) { + builder.addObjectsSkeleton( + typeResources = resources, + generateProperty = generateProperty, + modifier = modifier + ) + } + private fun TypeSpec.Builder.addObjectsProperties( typeResources: List, generateProperty: (T) -> PropertySpec, @@ -70,6 +90,26 @@ internal class HierarchyPropertiesGenerationStrategy : ) } + private fun TypeSpec.Builder.addObjectsSkeleton( + typeResources: List, + generateProperty: (T) -> PropertySpec, + modifier: KModifier? = null, + ) { + val filesMap = typeResources.groupBy { + it.path + }.mapValues { + it.value.map { resValue -> + generateProperty(resValue) + } + } + + this.generateSkeletonObjects( + map = filesMap, + objectKey = emptyList(), + modifier = modifier + ) + } + private fun TypeSpec.Builder.generateObjects( map: Map, List>, objectKey: List, @@ -99,4 +139,32 @@ internal class HierarchyPropertiesGenerationStrategy : } ) } + + private fun TypeSpec.Builder.generateSkeletonObjects( + map: Map, List>, + objectKey: List, + modifier: KModifier?, + ) { + addTypes( + map.filter { + it.key.size == objectKey.size + 1 + }.filter { + it.key.dropLast(1) == objectKey + }.map { + TypeSpec + .objectBuilder(it.key.last()) + .also { builder -> + builder.generateSkeletonObjects( + map = map, + objectKey = it.key, + modifier = modifier + ) + }.also { builder -> + if (modifier == KModifier.ACTUAL) { + builder.addModifiers(KModifier.ACTUAL) + } + }.build() + } + ) + } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 631b26d67..179e94ed2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -14,6 +14,7 @@ import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.metadata.container.ContainerMetadata import dev.icerock.gradle.metadata.container.ResourceType +import dev.icerock.gradle.metadata.resource.HierarchyMetadata import dev.icerock.gradle.metadata.resource.ResourceMetadata import dev.icerock.gradle.utils.capitalize import dev.icerock.gradle.utils.filterClass @@ -31,7 +32,6 @@ internal class ResourceTypeGenerator( private val platformResourceGenerator: PlatformResourceGenerator, private val filter: PatternFilterable.() -> Unit, private val resourcesPackageName: String? = null, - private val generatePropertiesAsExtensions: Boolean = false, private val batchSize: Int = DEFAULT_BATCH_SIZE, ) { fun generateMetadata(files: ResourcesFiles): List { @@ -47,7 +47,7 @@ internal class ResourceTypeGenerator( ): GenerationResult? { val typeMetadata: List = resources .filterClass(typeClass = metadataClass) - .sortedBy { it.key } + .sortedResources() // if we not have any resources of our type at all - not generate object if (typeMetadata.isEmpty()) return null @@ -61,12 +61,11 @@ internal class ResourceTypeGenerator( // implement ResourceContainer platform property .addOverridePlatformProperty() .also { builder -> - if (!generatePropertiesAsExtensions) { - // add all properties of available resources - propertiesGenerationStrategy.generateProperties( + if (isHierarchyPropertiesStrategy()) { + propertiesGenerationStrategy.generateSkeleton( builder = builder, resources = typeMetadata, - modifier = null, + modifier = KModifier.EXPECT, generateProperty = { generator.generateProperty(it).build() } @@ -76,16 +75,12 @@ internal class ResourceTypeGenerator( // implement ResourceContainer values function .addOverrideAbstractValuesFunction(resourceClass) - val fileSpecs: List = if (generatePropertiesAsExtensions) { - createExpectExtensionFileSpecs( - parentObjectName = parentObjectName, - objectName = objectName, - sourceSetName = sourceSetName, - resources = typeMetadata - ) - } else { - emptyList() - } + val fileSpecs: List = createExpectExtensionFileSpecs( + parentObjectName = parentObjectName, + objectName = objectName, + sourceSetName = sourceSetName, + resources = typeMetadata + ) return GenerationResult( typeSpec = objectBuilder.build(), @@ -110,9 +105,7 @@ internal class ResourceTypeGenerator( val typeResources: List = typeObject.resources .filterClass(metadataClass) - .sortedBy { it.key } - val useBatchedAccessors: Boolean = generatePropertiesAsExtensions && - platformResourceGenerator.supportsBatchedAccessors() + .sortedResources() val objectBuilder: TypeSpec.Builder = TypeSpec .objectBuilder(typeObject.name) @@ -128,51 +121,35 @@ internal class ResourceTypeGenerator( ) } .also { builder -> - if (useBatchedAccessors) { - builder.addBatchValuesFunction( - groupNames = getBatchGroupNames( - sourceSetName = typeObject.sourceSetName ?: sourceSetName, - objectName = typeObject.name, - resources = typeResources - ), - classType = resourceClass, - modifier = KModifier.ACTUAL - ) - } else if (!generatePropertiesAsExtensions) { - propertiesGenerationStrategy.generateProperties( + if (isHierarchyPropertiesStrategy()) { + propertiesGenerationStrategy.generateSkeleton( builder = builder, resources = typeResources, modifier = KModifier.ACTUAL, - generateProperty = ::createActualProperty - ) - } - } - .also { builder -> - if (!useBatchedAccessors) { - platformResourceGenerator.generateAfterProperties( - builder = builder, - metadata = typeResources, - modifier = KModifier.ACTUAL, + generateProperty = { + generator.generateProperty(it).build() + } ) } + builder.addBatchValuesFunction( + groupNames = getBatchGroupNames( + sourceSetName = typeObject.sourceSetName ?: sourceSetName, + objectName = typeObject.name, + resources = typeResources + ), + classType = resourceClass, + modifier = KModifier.ACTUAL + ) } - val fileSpecs: List = if (generatePropertiesAsExtensions) { - if (useBatchedAccessors) { - createBatchFileSpecs( - parentObjectName = parentObjectName, - objectName = typeObject.name, - resourceSourceSetName = typeObject.sourceSetName ?: sourceSetName, - targetSourceSetName = sourceSetName, - resources = typeResources, - actualModifier = KModifier.ACTUAL - ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) - } else { - emptyList() - } - } else { - emptyList() - } + val fileSpecs: List = createBatchFileSpecs( + parentObjectName = parentObjectName, + objectName = typeObject.name, + resourceSourceSetName = typeObject.sourceSetName ?: sourceSetName, + targetSourceSetName = sourceSetName, + resources = typeResources, + actualModifier = KModifier.ACTUAL + ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) return GenerationResult( typeSpec = objectBuilder.build(), @@ -194,14 +171,12 @@ internal class ResourceTypeGenerator( ): GenerationResult? { val typeResources: List = resources .filterClass(typeClass = metadataClass) - .sortedBy { it.key } + .sortedResources() // if we not have any resources of our type at all - not generate object if (typeResources.isEmpty()) return null val objectName: String = resourceType.name.lowercase() - val useBatchedAccessors: Boolean = generatePropertiesAsExtensions && - platformResourceGenerator.supportsBatchedAccessors() val objectBuilder: TypeSpec.Builder = TypeSpec .objectBuilder(objectName) .addModifiers(visibilityModifier) @@ -215,51 +190,34 @@ internal class ResourceTypeGenerator( ) } .also { builder -> - if (useBatchedAccessors) { - builder.addBatchValuesFunction( - groupNames = getBatchGroupNames( - sourceSetName = sourceSetName, - objectName = objectName, - resources = typeResources - ), - classType = resourceClass - ) - } else if (!generatePropertiesAsExtensions) { - propertiesGenerationStrategy.generateProperties( + if (isHierarchyPropertiesStrategy()) { + propertiesGenerationStrategy.generateSkeleton( builder = builder, resources = typeResources, modifier = null, - generateProperty = ::createSimpleProperty - ) - } - } - .also { builder -> - if (!useBatchedAccessors) { - platformResourceGenerator.generateAfterProperties( - builder = builder, - metadata = typeResources, + generateProperty = { + generator.generateProperty(it).build() + } ) } + builder.addBatchValuesFunction( + groupNames = getBatchGroupNames( + sourceSetName = sourceSetName, + objectName = objectName, + resources = typeResources + ), + classType = resourceClass + ) } - val fileSpecs: List = if (generatePropertiesAsExtensions) { - val batchFiles = if (useBatchedAccessors) { - createBatchFileSpecs( - parentObjectName = parentObjectName, - objectName = objectName, - resourceSourceSetName = sourceSetName, - targetSourceSetName = sourceSetName, - resources = typeResources, - actualModifier = null - ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) - } else { - emptyList() - } - - batchFiles - } else { - emptyList() - } + val fileSpecs: List = createBatchFileSpecs( + parentObjectName = parentObjectName, + objectName = objectName, + resourceSourceSetName = sourceSetName, + targetSourceSetName = sourceSetName, + resources = typeResources, + actualModifier = null + ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) return GenerationResult( typeSpec = objectBuilder.build(), @@ -280,26 +238,6 @@ internal class ResourceTypeGenerator( platformResourceGenerator.generateResourceFiles(typeMetadata) } - private fun createSimpleProperty(resource: T): PropertySpec { - return createProperty(resource) - } - - private fun createActualProperty(resource: T): PropertySpec { - return createProperty(resource, KModifier.ACTUAL) - } - - private fun createProperty( - resource: T, - modifier: KModifier? = null, - ): PropertySpec { - return generator.generateProperty(resource) - .apply { - if (modifier != null) addModifiers(modifier) - } - .initializer(platformResourceGenerator.generateInitializer(resource)) - .build() - } - private fun createExpectExtensionFileSpecs( parentObjectName: String, objectName: String, @@ -313,49 +251,16 @@ internal class ResourceTypeGenerator( index = index ) - val fileSpec = FileSpec.builder( - packageName = requireResourcesPackageName(), - fileName = getBatchFileName( - objectName = objectName, - index = index, - targetSourceSetName = sourceSetName - ) - ) - - val groupObject = TypeSpec.objectBuilder(groupName) - .addModifiers(KModifier.INTERNAL, KModifier.EXPECT) - .addProperties( - batch.map { resource -> - generator.generateProperty(resource) - .build() - } - ) - .also { builder -> - builder.addPlainValuesFunction( - metadata = batch, - classType = resourceClass, - isExpect = true + createExtensionFileSpecBuilder("$groupName.$sourceSetName") + .also { fileSpec -> + addExpectExtensionAccessors( + fileSpec = fileSpec, + parentObjectName = parentObjectName, + objectName = objectName, + resources = batch ) } .build() - - fileSpec.addType(groupObject) - - batch.forEach { resource -> - fileSpec.addProperty( - PropertySpec.builder(resource.key, resourceClass) - .receiver(getReceiverClassName(parentObjectName, objectName)) - .addModifiers(visibilityModifier) - .getter( - FunSpec.getterBuilder() - .addStatement("return %N.%N", groupName, resource.key) - .build() - ) - .build() - ) - } - - fileSpec.build() } } @@ -373,69 +278,117 @@ internal class ResourceTypeGenerator( objectName = objectName, index = index ) + val batchedResources: List> = buildBatchedResources(batch) val fileSpec = createExtensionFileSpecBuilder( fileName = "$groupName.$targetSourceSetName" ) + platformResourceGenerator.generateBeforeBatchedFile( + builder = fileSpec, + metadata = batch, + objectName = groupName + ) + val groupObject = TypeSpec.objectBuilder(groupName) .addModifiers(KModifier.INTERNAL) .also { builder -> - if (actualModifier != null) builder.addModifiers(actualModifier) - } - .addProperties( - batch.map { resource -> - generator.generateProperty(resource) - .also { builder -> - if (actualModifier != null) builder.addModifiers(actualModifier) - } - .delegate(CodeBlock.of("lazy { init_%L() }", resource.key)) - .build() + batchedResources.forEach { resource -> + builder.addProperty( + PropertySpec.builder(resource.internalName, resourceClass) + .addModifiers(KModifier.INTERNAL) + .delegate( + CodeBlock.of( + "lazy { %L() }", + initFunctionName(resource.internalName) + ) + ) + .build() + ) } - ) - .also { builder -> - builder.addPlainValuesFunction( - metadata = batch, + builder.addReferencedValuesFunction( + propertyReferences = batchedResources.map { it.internalName }, classType = resourceClass, - modifier = actualModifier + memberModifier = KModifier.INTERNAL ) } .build() fileSpec.addType(groupObject) - if (actualModifier == null) { - batch.forEach { resource -> - fileSpec.addProperty( - PropertySpec.builder(resource.key, resourceClass) - .receiver(getReceiverClassName(parentObjectName, objectName)) - .addModifiers(visibilityModifier) - .getter( - FunSpec.getterBuilder() - .addStatement("return %N.%N", groupName, resource.key) - .build() - ) - .build() - ) - } - } - - batch.forEach { resource -> + batchedResources.forEach { resource -> fileSpec.addFunction( - FunSpec.builder("init_${resource.key}") + FunSpec.builder(initFunctionName(resource.internalName)) .addModifiers(KModifier.PRIVATE) .returns(resourceClass) .addStatement( "return %L", - platformResourceGenerator.generateBatchedInitializer(resource) + platformResourceGenerator.generateBatchedInitializer(resource.metadata) ) .build() ) } + addActualExtensionAccessors( + fileSpec = fileSpec, + parentObjectName = parentObjectName, + objectName = objectName, + groupName = groupName, + resources = batchedResources, + actualModifier = actualModifier + ) + fileSpec.build() } } + private fun addExpectExtensionAccessors( + fileSpec: FileSpec.Builder, + parentObjectName: String, + objectName: String, + resources: List, + ) { + resources.forEach { resource -> + fileSpec.addProperty( + PropertySpec.builder(resource.key, resourceClass) + .receiver(getReceiverClassName(parentObjectName, objectName, resource.pathSegments())) + .addModifiers(visibilityModifier, KModifier.EXPECT) + .build() + ) + } + } + + private fun addActualExtensionAccessors( + fileSpec: FileSpec.Builder, + parentObjectName: String, + objectName: String, + groupName: String, + resources: List>, + actualModifier: KModifier?, + ) { + resources.forEach { resource -> + val resourcePath: List = resource.metadata.pathSegments() + fileSpec.addProperty( + PropertySpec.builder(resource.metadata.key, resourceClass) + .receiver(getReceiverClassName(parentObjectName, objectName, resourcePath)) + .addModifiers(visibilityModifier) + .also { property -> + if (actualModifier != null) { + property.addModifiers(actualModifier) + } + } + .getter( + FunSpec.getterBuilder() + .addStatement( + "return %L", + "$groupName.${resource.internalName}" + ) + .build() + ) + .build() + ) + } + } + private fun createExtensionFileSpecBuilder(fileName: String): FileSpec.Builder { return FileSpec.builder( packageName = requireResourcesPackageName(), @@ -447,14 +400,51 @@ internal class ResourceTypeGenerator( } } - private fun getReceiverClassName(parentObjectName: String, objectName: String): ClassName { + private fun getReceiverClassName( + parentObjectName: String, + objectName: String, + path: List = emptyList(), + ): ClassName { + val simpleNames: Array = arrayOf(parentObjectName, objectName, *path.toTypedArray()) return ClassName( packageName = requireResourcesPackageName(), - parentObjectName, - objectName + *simpleNames ) } + private fun buildBatchedResources(resources: List): List> { + if (!isHierarchyPropertiesStrategy()) { + return resources.map { resource -> + BatchedResource(metadata = resource, internalName = resource.key) + } + } + + val duplicates: Map> = resources + .groupBy { it.key } + .mapValues { (_, groupedResources) -> + groupedResources.sortedBy { resourceLogicalPath(it = it) } + } + + return resources.map { resource -> + val duplicateGroup: List = duplicates.getValue(resource.key) + val internalName = if (duplicateGroup.size == 1) { + resource.key + } else { + "${resource.key}__${duplicateGroup.indexOf(resource)}" + } + + BatchedResource(metadata = resource, internalName = internalName) + } + } + + private fun initFunctionName(internalName: String): String { + return "init_$internalName" + } + + private fun resourceLogicalPath(it: T): String { + return it.pathSegments().joinToString(separator = "/") + "/${it.key}" + } + private fun getBatchGroupNames( sourceSetName: String, objectName: String, @@ -477,21 +467,37 @@ internal class ResourceTypeGenerator( return "${sourceSetName.capitalize()}${objectName.capitalize()}$index" } - private fun getBatchFileName( - objectName: String, - index: Int, - targetSourceSetName: String, - ): String { - return "${objectName.capitalize()}$index.$targetSourceSetName" - } - private fun requireResourcesPackageName(): String { return requireNotNull(resourcesPackageName) { "resourcesPackageName should be provided to generate extension properties" } } + private fun isHierarchyPropertiesStrategy(): Boolean { + return propertiesGenerationStrategy is HierarchyPropertiesGenerationStrategy<*> + } + + private fun T.pathSegments(): List { + return (this as? HierarchyMetadata)?.path.orEmpty() + } + + private fun List.sortedResources(): List { + return if (firstOrNull() is HierarchyMetadata) { + sortedBy { + val hierarchy = it as HierarchyMetadata + hierarchy.path.joinToString(separator = "/") + "/" + it.key + } + } else { + sortedBy { it.key } + } + } + private companion object { - const val DEFAULT_BATCH_SIZE = 100 + const val DEFAULT_BATCH_SIZE = 50 } + + private data class BatchedResource( + val metadata: T, + val internalName: String, + ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt index bc68327b8..f360b2245 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt @@ -44,6 +44,7 @@ internal class ResourcesGenerator( val outputMetadata: MutableList = mutableListOf() val additionalFileSpecs: MutableList = mutableListOf() + additionalFileSpecs.addAll(containerGenerator.generateAdditionalFiles(resourcesPackageName)) if (inputMetadata.isEmpty()) { // we not have expect - we should generate simple object @@ -167,6 +168,7 @@ internal class ResourcesGenerator( val outputMetadata: MutableList = mutableListOf() val additionalFileSpecs: MutableList = mutableListOf() + additionalFileSpecs.addAll(containerGenerator.generateAdditionalFiles(resourcesPackageName)) // if previous levels doesn't have resources should use "MR" // but if resources is found, need generate "MRsourceSet" object diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/AppleContainerGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/AppleContainerGenerator.kt index cf11256df..cb065648e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/AppleContainerGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/AppleContainerGenerator.kt @@ -5,10 +5,13 @@ package dev.icerock.gradle.generator.container import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformContainerGenerator -import dev.icerock.gradle.generator.addAppleResourcesBundleProperty internal class AppleContainerGenerator( private val bundleIdentifier: String, @@ -20,7 +23,43 @@ internal class AppleContainerGenerator( ) } - override fun generateBeforeTypes(objectName: String, builder: TypeSpec.Builder) { - builder.addAppleResourcesBundleProperty(bundleIdentifier) + override fun generateAdditionalFiles(packageName: String): List { + val provider = TypeSpec.objectBuilder(Constants.PlatformDetails.providerObjectName) + .addModifiers(KModifier.INTERNAL) + .addProperty( + PropertySpec.builder( + Constants.Apple.resourcesBundlePropertyName, + Constants.Apple.nsBundleName, + KModifier.PRIVATE + ).delegate(CodeBlock.of("lazy { NSBundle.loadableBundle(%S) }", bundleIdentifier)) + .build() + ) + .addProperty( + PropertySpec.builder( + Constants.PlatformDetails.providerDetailsPropertyName, + Constants.resourcePlatformDetailsName + ).delegate( + CodeBlock.of( + "lazy { %T(%N) }", + Constants.resourcePlatformDetailsName, + Constants.Apple.resourcesBundlePropertyName + ) + ).build() + ) + .build() + + return listOf( + FileSpec.builder(packageName, Constants.PlatformDetails.providerObjectName) + .addImport( + Constants.Apple.nsBundleName.packageName, + Constants.Apple.nsBundleName.simpleNames + ) + .addImport( + Constants.Apple.loadableBundleName.packageName, + Constants.Apple.loadableBundleName.simpleNames + ) + .addType(provider) + .build() + ) } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/JvmContainerGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/JvmContainerGenerator.kt index e58fec59b..68818c0b3 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/JvmContainerGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/container/JvmContainerGenerator.kt @@ -5,17 +5,56 @@ package dev.icerock.gradle.generator.container import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformContainerGenerator -import dev.icerock.gradle.generator.addJvmClassLoaderProperty internal class JvmContainerGenerator : PlatformContainerGenerator { override fun getImports(): List { - return listOf(Constants.Jvm.classLoaderName) + return listOf( + Constants.Jvm.classLoaderName, + ClassName("kotlin.jvm", "java") + ) } - override fun generateBeforeTypes(objectName: String, builder: TypeSpec.Builder) { - builder.addJvmClassLoaderProperty(objectName) + override fun generateAdditionalFiles(packageName: String): List { + val provider = TypeSpec.objectBuilder(Constants.PlatformDetails.providerObjectName) + .addModifiers(KModifier.INTERNAL) + .addProperty( + PropertySpec.builder( + Constants.Jvm.resourcesClassLoaderPropertyName, + Constants.Jvm.classLoaderName, + KModifier.PRIVATE + ).initializer( + CodeBlock.of( + "%L::class.java.classLoader", + Constants.PlatformDetails.providerObjectName + ) + ).build() + ) + .addProperty( + PropertySpec.builder( + Constants.PlatformDetails.providerDetailsPropertyName, + Constants.resourcePlatformDetailsName + ).delegate( + CodeBlock.of( + "lazy { %T(%N) }", + Constants.resourcePlatformDetailsName, + Constants.Jvm.resourcesClassLoaderPropertyName + ) + ).build() + ) + .build() + + return listOf( + FileSpec.builder(packageName, Constants.PlatformDetails.providerObjectName) + .addImport("kotlin.jvm", "java") + .addType(provider) + .build() + ) } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/AssetGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/AssetGeneratorFactory.kt index 447421a77..4937fdb5b 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/AssetGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/AssetGeneratorFactory.kt @@ -28,6 +28,7 @@ import java.io.File @Suppress("LongParameterList") internal class AssetGeneratorFactory( + private val resourcesPackageName: String, private val resourcesVisibility: MRVisibility, private val outputResourcesDir: File, private val outputAssetsDir: File, @@ -51,6 +52,7 @@ internal class AssetGeneratorFactory( .toSet() ), platformResourceGenerator = createPlatformAssetGenerator(), + resourcesPackageName = resourcesPackageName, filter = { include("assets/**") } ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ColorGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ColorGeneratorFactory.kt index 8ebbd9109..db7d362a7 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ColorGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ColorGeneratorFactory.kt @@ -25,6 +25,7 @@ import java.io.File @Suppress("LongParameterList") internal class ColorGeneratorFactory( + private val resourcesPackageName: String, private val resourcesVisibility: MRVisibility, private val outputResourcesDir: File, private val outputAssetsDir: File, @@ -41,7 +42,8 @@ internal class ColorGeneratorFactory( visibilityModifier = resourcesVisibility.toModifier(), generator = ColorResourceGenerator(), platformResourceGenerator = createPlatformColorGenerator(), - filter = { include("**/colors*.xml") } + filter = { include("**/colors*.xml") }, + resourcesPackageName = resourcesPackageName ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FileGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FileGeneratorFactory.kt index de9616338..d34dde21a 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FileGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FileGeneratorFactory.kt @@ -28,6 +28,7 @@ import java.io.File @Suppress("LongParameterList") internal class FileGeneratorFactory( + private val resourcesPackageName: String, private val resourcesVisibility: MRVisibility, private val outputResourcesDir: File, private val kotlinPlatformType: KotlinPlatformType, @@ -50,6 +51,7 @@ internal class FileGeneratorFactory( .toSet() ), platformResourceGenerator = createPlatformFileGenerator(), + resourcesPackageName = resourcesPackageName, filter = { include("files/**") } ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FontGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FontGeneratorFactory.kt index 723f4f329..9ceae4c00 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FontGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/FontGeneratorFactory.kt @@ -42,7 +42,8 @@ internal class FontGeneratorFactory( visibilityModifier = resourcesVisibility.toModifier(), generator = FontResourceGenerator(), platformResourceGenerator = createPlatformFontGenerator(), - filter = { include("fonts/**.ttf", "fonts/**.otf") } + filter = { include("fonts/**.ttf", "fonts/**.otf") }, + resourcesPackageName = resourcesPackageName ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ImageGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ImageGeneratorFactory.kt index 0dda5d84c..88237f7df 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ImageGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/ImageGeneratorFactory.kt @@ -27,6 +27,7 @@ import java.io.File @Suppress("LongParameterList") internal class ImageGeneratorFactory( + private val resourcesPackageName: String, private val resourcesVisibility: MRVisibility, private val outputResourcesDir: File, private val outputAssetsDir: File, @@ -44,6 +45,7 @@ internal class ImageGeneratorFactory( visibilityModifier = resourcesVisibility.toModifier(), generator = ImageResourceGenerator(), platformResourceGenerator = createPlatformImageGenerator(), + resourcesPackageName = resourcesPackageName, filter = { include("images/**/*.png", "images/**/*.jpg", "images/**/*.svg") } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/PluralGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/PluralGeneratorFactory.kt index d97efeca2..b0c363f2b 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/PluralGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/PluralGeneratorFactory.kt @@ -47,7 +47,8 @@ internal class PluralGeneratorFactory( strictLineBreaks = strictLineBreaks ), platformResourceGenerator = createPlatformPluralGenerator(), - filter = { include("**/plurals*.xml") } + filter = { include("**/plurals*.xml") }, + resourcesPackageName = resourcesPackageName ) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt index c96fbc6ef..86070be05 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt @@ -35,7 +35,6 @@ internal class StringGeneratorFactory( private val kotlinKonanTarget: () -> KonanTarget, private val androidRClassPackage: () -> String, private val iosBaseLocalizationRegion: () -> String, - private val appleBundleIdentifier: () -> String, ) { fun create(): ResourceTypeGenerator { return ResourceTypeGenerator( @@ -49,8 +48,7 @@ internal class StringGeneratorFactory( ), platformResourceGenerator = createPlatformStringGenerator(), filter = { include("**/strings*.xml") }, - resourcesPackageName = resourcesPackageName, - generatePropertiesAsExtensions = true + resourcesPackageName = resourcesPackageName ) } @@ -69,8 +67,7 @@ internal class StringGeneratorFactory( createApple = { AppleStringResourceGenerator( baseLocalizationRegion = iosBaseLocalizationRegion(), - resourcesGenerationDir = outputResourcesDir, - bundleIdentifier = appleBundleIdentifier() + resourcesGenerationDir = outputResourcesDir ) }, createJvm = { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/NOPResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/NOPResourceGenerator.kt index 77f23bcb1..edd0f0504 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/NOPResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/NOPResourceGenerator.kt @@ -11,14 +11,14 @@ import dev.icerock.gradle.metadata.resource.ResourceMetadata internal class NOPResourceGenerator : PlatformResourceGenerator { override fun imports(): List { - TODO("Not yet implemented") + return emptyList() } override fun generateResourceFiles(data: List) { - TODO("Not yet implemented") + Unit } override fun generateInitializer(metadata: T): CodeBlock { - TODO("Not yet implemented") + return CodeBlock.of("error(%S)", "NOP resource generator should not create initializers") } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt index abb658795..510b50334 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.asset import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -18,7 +19,10 @@ import java.io.File internal class AppleAssetResourceGenerator( private val resourcesGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: AssetMetadata): CodeBlock { return CodeBlock.of( @@ -30,6 +34,16 @@ internal class AppleAssetResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: AssetMetadata): CodeBlock { + return CodeBlock.of( + "AssetResource(originalPath = %S, fileName = %S, extension = %S, bundle = %L)", + metadata.pathRelativeToBase.invariantSeparatorsPath, + processedFilePath(metadata).substringBeforeLast('.'), + metadata.filePath.extension, + Constants.Apple.providerBundleReference + ) + } + override fun generateResourceFiles(data: List) { data.forEach { metadata -> val newName: String = processedFilePath(metadata) @@ -50,6 +64,12 @@ internal class AppleAssetResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt index b0e7cd3f4..8facec5c1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.asset import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -31,6 +32,15 @@ internal class JvmAssetResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: AssetMetadata): CodeBlock { + return CodeBlock.of( + "AssetResource(resourcesClassLoader = %L, originalPath = %S, path = %S)", + Jvm.providerClassLoaderReference, + metadata.pathRelativeToBase.invariantSeparatorsPath, + buildAssetPath(metadata) + ) + } + override fun generateResourceFiles(data: List) { data.forEach { metadata -> metadata.filePath.copyTo(File(resourcesGenerationDir, buildAssetPath(metadata))) @@ -45,6 +55,12 @@ internal class JvmAssetResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt index 1e379f45d..64c6ddf69 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.color import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -23,7 +24,10 @@ import java.io.File internal class AppleColorResourceGenerator( private val assetsGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: ColorMetadata): CodeBlock { return CodeBlock.of( @@ -33,6 +37,14 @@ internal class AppleColorResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: ColorMetadata): CodeBlock { + return CodeBlock.of( + "ColorResource(name = %S, bundle = %L)", + metadata.key, + Constants.Apple.providerBundleReference + ) + } + override fun generateResourceFiles(data: List) { val assetsDirectory = File(assetsGenerationDir, Constants.Apple.assetsDirectoryName) @@ -95,6 +107,12 @@ internal class AppleColorResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt index f662956dd..72d12c626 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.file import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -18,7 +19,10 @@ import java.io.File internal class AppleFileResourceGenerator( private val resourcesGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: FileMetadata): CodeBlock { return CodeBlock.of( @@ -29,6 +33,15 @@ internal class AppleFileResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: FileMetadata): CodeBlock { + return CodeBlock.of( + "FileResource(fileName = %S, extension = %S, bundle = %L)", + metadata.filePath.nameWithoutExtension, + metadata.filePath.extension, + Constants.Apple.providerBundleReference + ) + } + override fun generateResourceFiles(data: List) { val targetDir = File(resourcesGenerationDir, "files") targetDir.mkdirs() @@ -46,6 +59,12 @@ internal class AppleFileResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt index b8e98b114..d658f9923 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.file import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -30,6 +31,14 @@ internal class JvmFileResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: FileMetadata): CodeBlock { + return CodeBlock.of( + "FileResource(resourcesClassLoader = %L, filePath = %S)", + Jvm.providerClassLoaderReference, + "$FILES_DIR/${metadata.filePath.name}" + ) + } + override fun generateResourceFiles(data: List) { val fontsDir = File(resourcesGenerationDir, FILES_DIR) fontsDir.mkdirs() @@ -47,6 +56,12 @@ internal class JvmFileResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt index 98acc57db..9bedb66d3 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.font import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -18,7 +19,10 @@ import java.io.File internal class AppleFontResourceGenerator( private val resourcesGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: FontMetadata): CodeBlock { return CodeBlock.of( @@ -28,6 +32,14 @@ internal class AppleFontResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: FontMetadata): CodeBlock { + return CodeBlock.of( + "FontResource(fontName = %S, bundle = %L)", + metadata.filePath.name, + Constants.Apple.providerBundleReference + ) + } + override fun generateResourceFiles(data: List) { data.map { it.filePath }.forEach { file -> file.copyTo(File(resourcesGenerationDir, file.name)) @@ -42,6 +54,12 @@ internal class AppleFontResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt index 79aaf3e45..3f5b31ac0 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.font import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -30,6 +31,14 @@ internal class JvmFontResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: FontMetadata): CodeBlock { + return CodeBlock.of( + "FontResource(resourcesClassLoader = %L, filePath = %S)", + Jvm.providerClassLoaderReference, + "$FONTS_DIR/${metadata.filePath.name}" + ) + } + override fun generateResourceFiles(data: List) { val fontsDir = File(resourcesGenerationDir, FONTS_DIR) fontsDir.mkdirs() @@ -47,6 +56,12 @@ internal class JvmFontResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt index e9156488b..dd7daf23f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.image import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -24,7 +25,10 @@ import java.io.File internal class AppleImageResourceGenerator( private val assetsGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: ImageMetadata): CodeBlock { return CodeBlock.of( @@ -34,6 +38,14 @@ internal class AppleImageResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: ImageMetadata): CodeBlock { + return CodeBlock.of( + "ImageResource(assetImageName = %S, bundle = %L)", + metadata.key, + Constants.Apple.providerBundleReference + ) + } + @Suppress("LongMethod") override fun generateResourceFiles(data: List) { val assetsDirectory = File(assetsGenerationDir, Constants.Apple.assetsDirectoryName) @@ -67,6 +79,12 @@ internal class AppleImageResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt index 967dddd2b..05737e61c 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.image import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -50,6 +51,33 @@ internal class JvmImageResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: ImageMetadata): CodeBlock { + var fileName: String = "" + var darkFileName: String? = null + + metadata.values.groupBy { it.appearance }.forEach { (theme, resources) -> + val item: ImageMetadata.ImageItem = resources.getHighestQualityItem(theme) + + if (theme == Appearance.DARK) { + darkFileName = "${metadata.key}${theme.themeSuffix}.${item.filePath.extension}" + } else { + fileName = "${metadata.key}.${item.filePath.extension}" + } + } + + val darkFilePath: String = if (darkFileName != null) { + "\"$IMAGES_DIR/$darkFileName\"" + } else { + "null" + } + + return CodeBlock.of( + "ImageResource(resourcesClassLoader = %L, filePath = %S, darkFilePath = $darkFilePath)", + Jvm.providerClassLoaderReference, + "$IMAGES_DIR/$fileName" + ) + } + override fun generateResourceFiles(data: List) { generateHighestQualityImageResources( resourcesGenerationDir = resourcesGenerationDir, @@ -66,6 +94,12 @@ internal class JvmImageResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt index 96dd8e0c6..03549ab5c 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.plural import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -21,7 +22,10 @@ internal class ApplePluralResourceGenerator( private val baseLocalizationRegion: String, private val resourcesGenerationDir: File, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: PluralMetadata): CodeBlock { return CodeBlock.of( @@ -31,6 +35,14 @@ internal class ApplePluralResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: PluralMetadata): CodeBlock { + return CodeBlock.of( + "PluralsResource(resourceId = %S, bundle = %L)", + metadata.key, + Constants.Apple.providerBundleReference + ) + } + override fun generateResourceFiles(data: List) { data.processLanguages().forEach { (lang, strings) -> generateLanguageFile( @@ -48,6 +60,12 @@ internal class ApplePluralResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt index c5d99cc78..97ef2a7dd 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.plural import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy @@ -13,6 +14,7 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty +import dev.icerock.gradle.generator.addJsBatchedStringsLoaderProperty import dev.icerock.gradle.generator.addJsContainerStringsLoaderProperty import dev.icerock.gradle.generator.addJsFallbackProperty import dev.icerock.gradle.generator.addJsSupportedLocalesProperty @@ -79,6 +81,30 @@ internal class JsPluralResourceGenerator( builder.addJsContainerStringsLoaderProperty() } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) { + builder.addJsFallbackProperty( + fallbackFilePath = "./" + LOCALIZATION_DIR + "/" + getFileNameForLanguage(LanguageType.Base), + filePathMode = filePathMode + ) + builder.addJsSupportedLocalesProperty( + bcpLangToPath = metadata.asSequence() + .flatMap { resource -> + resource.values.map { it.locale } + }.distinct().map { locale -> + LanguageType.fromLanguage(locale) + }.filterIsInstance().map { language -> + val fileName: String = getFileNameForLanguage(language) + language.toBcpString() to "./$LOCALIZATION_DIR/$fileName" + }.toList(), + filePathMode = filePathMode + ) + builder.addJsBatchedStringsLoaderProperty() + } + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt index 2e056c7c6..c280b2b64 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.plural import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -35,6 +36,15 @@ internal class JvmPluralResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: PluralMetadata): CodeBlock { + return CodeBlock.of( + "PluralsResource(resourcesClassLoader = %L, bundleName = %L, key = %S)", + Jvm.providerClassLoaderReference, + pluralsBundlePropertyName, + metadata.key + ) + } + override fun generateResourceFiles(data: List) { data.processLanguages().forEach { (lang, strings) -> generateLanguageFile( @@ -57,6 +67,17 @@ internal class JvmPluralResourceGenerator( ) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) { + builder.addJvmPlatformResourceBundleProperty( + bundlePropertyName = pluralsBundlePropertyName, + bundlePath = getBundlePath() + ) + } + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt index 2290ae236..ee9a1652f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt @@ -29,8 +29,6 @@ internal class AndroidStringResourceGenerator( return CodeBlock.of("StringResource(R.string.%L)", metadata.key) } - override fun supportsBatchedAccessors(): Boolean = true - override fun generateBeforeProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt index 1043a4346..5fdf29265 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt @@ -7,13 +7,11 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec -import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.PropertySpec -import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator +import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata @@ -23,64 +21,25 @@ import java.io.File internal class AppleStringResourceGenerator( private val baseLocalizationRegion: String, private val resourcesGenerationDir: File, - private val bundleIdentifier: String, ) : PlatformResourceGenerator { - override fun imports(): List = emptyList() + override fun imports(): List = listOf( + Constants.Apple.nsBundleName, + Constants.Apple.loadableBundleName + ) override fun generateInitializer(metadata: StringMetadata): CodeBlock { return CodeBlock.of( "StringResource(resourceId = %S, bundle = %L)", metadata.key, - "$PLATFORM_DETAILS_PROVIDER_NAME.$BUNDLE_PROPERTY_NAME" + Constants.Apple.platformContainerBundlePropertyName ) } - override fun supportsBatchedAccessors(): Boolean = true - override fun generateBatchedInitializer(metadata: StringMetadata): CodeBlock { - return generateInitializer(metadata) - } - - override fun generateAdditionalBatchedFiles(packageName: String): List { - val providerObject = TypeSpec.objectBuilder(PLATFORM_DETAILS_PROVIDER_NAME) - .addModifiers(KModifier.INTERNAL) - .addProperty( - PropertySpec.builder(BUNDLE_PROPERTY_NAME, Constants.Apple.nsBundleName) - .delegate( - CodeBlock.of( - "lazy { NSBundle.loadableBundle(%S) }", - bundleIdentifier - ) - ) - .build() - ) - .addProperty( - PropertySpec.builder(DETAILS_PROPERTY_NAME, Constants.resourcePlatformDetailsName) - .getter( - FunSpec.getterBuilder() - .addStatement( - "return %T(%N)", - Constants.resourcePlatformDetailsName, - BUNDLE_PROPERTY_NAME - ) - .build() - ) - .build() - ) - .build() - - return listOf( - FileSpec.builder(packageName, PLATFORM_DETAILS_PROVIDER_NAME) - .addImport( - Constants.Apple.nsBundleName.packageName, - Constants.Apple.nsBundleName.simpleNames - ) - .addImport( - Constants.Apple.loadableBundleName.packageName, - Constants.Apple.loadableBundleName.simpleNames - ) - .addType(providerObject) - .build() + return CodeBlock.of( + "StringResource(resourceId = %S, bundle = %L)", + metadata.key, + Constants.Apple.providerBundleReference ) } @@ -98,23 +57,15 @@ internal class AppleStringResourceGenerator( metadata: List, modifier: KModifier?, ) { - val resourcePlatformDetailsPropertySpec = PropertySpec - .builder( - Constants.PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName - ) - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .initializer(CodeBlock.of("$PLATFORM_DETAILS_PROVIDER_NAME.$DETAILS_PROPERTY_NAME")) - .build() - - builder.addProperty(resourcePlatformDetailsPropertySpec) + builder.addAppleContainerBundleInitializerProperty(modifier) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) = Unit + override fun generateAfterProperties( builder: Builder, metadata: List, @@ -147,9 +98,4 @@ internal class AppleStringResourceGenerator( } } - private companion object { - const val PLATFORM_DETAILS_PROVIDER_NAME = "PlatformDetailsProvider" - const val BUNDLE_PROPERTY_NAME = "bundle" - const val DETAILS_PROPERTY_NAME = "details" - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt index 52fa3d3ff..31c187d58 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy @@ -13,6 +14,7 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty +import dev.icerock.gradle.generator.addJsBatchedStringsLoaderProperty import dev.icerock.gradle.generator.addJsContainerStringsLoaderProperty import dev.icerock.gradle.generator.addJsFallbackProperty import dev.icerock.gradle.generator.addJsSupportedLocalesProperty @@ -79,6 +81,30 @@ internal class JsStringResourceGenerator( builder.addJsContainerStringsLoaderProperty() } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) { + builder.addJsFallbackProperty( + fallbackFilePath = "./" + LOCALIZATION_DIR + "/" + getFileNameForLanguage(LanguageType.Base), + filePathMode = filePathMode + ) + builder.addJsSupportedLocalesProperty( + bcpLangToPath = metadata.asSequence() + .flatMap { resource -> + resource.values.map { it.locale } + }.distinct().map { locale -> + LanguageType.fromLanguage(locale) + }.filterIsInstance().map { language -> + val fileName: String = getFileNameForLanguage(language) + language.toBcpString() to "./$LOCALIZATION_DIR/$fileName" + }.toList(), + filePathMode = filePathMode + ) + builder.addJsBatchedStringsLoaderProperty() + } + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt index e4514ce39..dee912da0 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants @@ -35,6 +36,15 @@ internal class JvmStringResourceGenerator( ) } + override fun generateBatchedInitializer(metadata: StringMetadata): CodeBlock { + return CodeBlock.of( + "StringResource(resourcesClassLoader = %L, bundleName = %L, key = %S)", + Jvm.providerClassLoaderReference, + stringsBundlePropertyName, + metadata.key + ) + } + override fun generateResourceFiles(data: List) { data.processLanguages().forEach { (lang, strings) -> generateLanguageFile( @@ -57,6 +67,17 @@ internal class JvmStringResourceGenerator( ) } + override fun generateBeforeBatchedFile( + builder: FileSpec.Builder, + metadata: List, + objectName: String, + ) { + builder.addJvmPlatformResourceBundleProperty( + bundlePropertyName = stringsBundlePropertyName, + bundlePath = getBundlePath() + ) + } + override fun generateAfterProperties( builder: Builder, metadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/MetadataException.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/MetadataException.kt index 5b8203937..ef4ed46a1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/MetadataException.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/MetadataException.kt @@ -9,7 +9,7 @@ class InvalidResourceKeyException(val key: String) : Exception( " underscores or digits: $key" ) -class InvalidImageResourceConfiguration(val imageName: String) : Exception( +class InvalidImageResourceConfiguration(imageName: String) : Exception( "For image {$imageName} found only dark image resources." + " Please, add correct resources, or remove '-dark' flag from name." ) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt index 06bf63e16..f6d23fb31 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt @@ -256,7 +256,11 @@ internal data class FileMetadata( override val path: List = getFilePath(filePath, relativePath) - override fun contentHash(): String = filePath.calculateResourcesHash() + override fun contentHash(): String = listOf( + key, + path.joinToString(separator = "/"), + filePath.calculateResourcesHash() + ).calculateHash() } @Serializable @@ -278,7 +282,11 @@ internal data class AssetMetadata( override val path: List = getFilePath(filePath, relativePath) - override fun contentHash(): String = filePath.calculateResourcesHash() + override fun contentHash(): String = listOf( + key, + path.joinToString(separator = "/"), + filePath.calculateResourcesHash() + ).calculateHash() } interface HierarchyMetadata : ResourceMetadata { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt index 3a88b4f49..8829cb8b8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt @@ -215,7 +215,6 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { kotlinKonanTarget = ::kotlinKonanTarget, androidRClassPackage = androidRClassPackage::get, iosBaseLocalizationRegion = iosBaseLocalizationRegion::get, - appleBundleIdentifier = appleBundleIdentifier::get, ).create(), PluralGeneratorFactory( resourcesPackageName = resourcesPackageName.get(), @@ -228,6 +227,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { iosBaseLocalizationRegion = iosBaseLocalizationRegion::get, ).create(), ImageGeneratorFactory( + resourcesPackageName = resourcesPackageName.get(), resourcesVisibility = resourcesVisibility.get(), outputResourcesDir = outputResourcesDir.get().asFile, outputAssetsDir = outputAssetsDir.get().asFile, @@ -237,6 +237,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { logger = logger ).create(), ColorGeneratorFactory( + resourcesPackageName = resourcesPackageName.get(), resourcesVisibility = resourcesVisibility.get(), outputResourcesDir = outputResourcesDir.get().asFile, outputAssetsDir = outputAssetsDir.get().asFile, @@ -253,6 +254,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { androidRClassPackage = androidRClassPackage::get, ).create(), FileGeneratorFactory( + resourcesPackageName = resourcesPackageName.get(), resourcesVisibility = resourcesVisibility.get(), outputResourcesDir = outputResourcesDir.get().asFile, kotlinPlatformType = kotlinPlatformType, @@ -261,6 +263,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { ownResources = ownResources ).create(), AssetGeneratorFactory( + resourcesPackageName = resourcesPackageName.get(), resourcesVisibility = resourcesVisibility.get(), outputResourcesDir = outputResourcesDir.get().asFile, outputAssetsDir = outputAssetsDir.get().asFile, diff --git a/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt b/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt index b77b406a7..ccc5b188c 100644 --- a/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt +++ b/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt @@ -9,6 +9,10 @@ expect fun ResourceContainer.getAssetByFilePath(filePath: String) interface ResourceContainer { @Suppress("VariableNaming") + @Deprecated( + message = "Internal resource container detail", + level = DeprecationLevel.HIDDEN + ) val __platformDetails: ResourcePlatformDetails fun values(): List } From 59616231fbfd57a571ee074b3ef7b197d2bf0585 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 11 Jun 2026 23:20:31 +0700 Subject: [PATCH 03/26] Cover batched string generation --- .../gradle/generator/StringBatchingTest.kt | 89 +++++++++++-------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt index 4be81507a..becd35a5a 100644 --- a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt @@ -33,31 +33,28 @@ class StringBatchingTest { result.typeSpec.propertySpecs.any { it.name == "__platformDetails" }, containerSource ) + assertTrue( + containerSource.contains("public override val __platformDetails"), + containerSource + ) assertTrue( result.typeSpec.funSpecs.any { it.name == "values" }, containerSource ) assertEquals(expected = 1, actual = result.fileSpecs.size) - assertEquals(expected = "Strings0.commonMain", actual = result.fileSpecs.single().name) + assertEquals(expected = "CommonMainStrings0.commonMain", actual = result.fileSpecs.single().name) val accessorSource = result.fileSpecs.single().toString() assertTrue( - accessorSource.contains("internal expect object CommonMainStrings0"), - accessorSource - ) - assertTrue( - accessorSource.contains("public val MR.strings.key_000: StringResource"), - accessorSource - ) - assertTrue( - accessorSource.contains("get() = CommonMainStrings0.key_000"), + accessorSource.contains("public expect val MR.strings.key_000: StringResource"), accessorSource ) + assertFalse(accessorSource.contains("CommonMainStrings0"), accessorSource) } @Test - fun commonStringsAreSplitIntoHundredItemBatches() { + fun commonStringsAreSplitIntoFiftyItemBatches() { val oneHundredResult = createCommonGenerator().generateExpectObject( parentObjectName = MR_CLASS_NAME, resources = createStrings(count = 100), @@ -74,14 +71,18 @@ class StringBatchingTest { sourceSetName = COMMON_SOURCE_SET )!! - assertEquals(expected = 1, actual = oneHundredResult.fileSpecs.size) + assertEquals(expected = 2, actual = oneHundredResult.fileSpecs.size) assertEquals( - expected = listOf("Strings0.commonMain", "Strings1.commonMain"), + expected = listOf( + "CommonMainStrings0.commonMain", + "CommonMainStrings1.commonMain", + "CommonMainStrings2.commonMain" + ), actual = oneHundredOneResult.fileSpecs.map { it.name } ) - assertEquals(expected = 10, actual = largeResult.fileSpecs.size) - assertEquals(expected = "Strings0.commonMain", actual = largeResult.fileSpecs.first().name) - assertEquals(expected = "Strings9.commonMain", actual = largeResult.fileSpecs.last().name) + assertEquals(expected = 20, actual = largeResult.fileSpecs.size) + assertEquals(expected = "CommonMainStrings0.commonMain", actual = largeResult.fileSpecs.first().name) + assertEquals(expected = "CommonMainStrings19.commonMain", actual = largeResult.fileSpecs.last().name) } @Test @@ -101,33 +102,34 @@ class StringBatchingTest { assertFalse(containerSource.contains("val key_000: StringResource"), containerSource) assertTrue(containerSource.contains("CommonMainStrings0.values()"), containerSource) assertTrue(containerSource.contains("CommonMainStrings1.values()"), containerSource) + assertTrue(containerSource.contains("CommonMainStrings2.values()"), containerSource) val firstBatchSource = androidResult.fileSpecs .single { it.name == "CommonMainStrings0.androidMain" } .toString() assertTrue( - firstBatchSource.contains("internal actual object CommonMainStrings0"), + firstBatchSource.contains("internal object CommonMainStrings0"), firstBatchSource ) assertTrue( - firstBatchSource.contains("public actual val key_000: StringResource by"), + firstBatchSource.contains("internal val key_000: StringResource by"), firstBatchSource ) - assertFalse( + assertTrue(firstBatchSource.contains("private fun init_key_000(): StringResource"), firstBatchSource) + assertTrue(firstBatchSource.contains("StringResource(R.string.key_000)"), firstBatchSource) + assertTrue( firstBatchSource.contains("public actual val MR.strings.key_000: StringResource"), firstBatchSource ) - assertTrue(firstBatchSource.contains("private fun init_key_000(): StringResource"), firstBatchSource) - assertTrue(firstBatchSource.contains("StringResource(R.string.key_000)"), firstBatchSource) val secondBatchSource = androidResult.fileSpecs - .single { it.name == "CommonMainStrings1.androidMain" } + .single { it.name == "CommonMainStrings2.androidMain" } .toString() assertTrue(secondBatchSource.contains("StringResource(R.string.key_100)"), secondBatchSource) } @Test - fun appleActualStringsUsePlatformDetailsProvider() { + fun appleActualStringsUseSharedPlatformDetailsProvider() { val commonResult = createCommonGenerator().generateExpectObject( parentObjectName = MR_CLASS_NAME, resources = createStrings(count = 1), @@ -140,35 +142,46 @@ class StringBatchingTest { )!! val containerSource = appleResult.typeSpec.toString() + assertTrue(containerSource.contains("public actual override val __platformDetails"), containerSource) assertTrue(containerSource.contains("PlatformDetailsProvider.details"), containerSource) val batchSource = appleResult.fileSpecs .single { it.name == "CommonMainStrings0.iosMain" } .toString() assertTrue( - batchSource.contains("internal actual object CommonMainStrings0"), + batchSource.contains("internal object CommonMainStrings0"), batchSource ) - assertTrue(batchSource.contains("public actual val key_000: StringResource by"), batchSource) + assertTrue(batchSource.contains("internal val key_000: StringResource by"), batchSource) assertTrue( batchSource.contains("resourceId = \"key_000\""), batchSource ) assertTrue( - batchSource.contains("PlatformDetailsProvider.bundle"), - batchSource - ) - assertFalse( - batchSource.contains("public actual val MR.strings.key_000: StringResource"), + batchSource.contains("PlatformDetailsProvider.details.nsBundle"), batchSource ) + assertFalse(batchSource.contains("private val bundle"), batchSource) + assertFalse(batchSource.contains("private val __platformDetails"), batchSource) + assertTrue(batchSource.contains("public actual val MR.strings.key_000: StringResource"), batchSource) + } + + @Test + fun targetSpecificStringsUseCorrectVisibility() { + val result = createAndroidGenerator().generateObject( + parentObjectName = "MRandroidMain", + resources = createStrings(count = 1), + sourceSetName = ANDROID_SOURCE_SET + )!! - val providerSource = appleResult.fileSpecs - .single { it.name == "PlatformDetailsProvider" } + val batchSource = result.fileSpecs + .single { it.name == "AndroidMainStrings0.androidMain" } .toString() - assertTrue(providerSource.contains("internal object PlatformDetailsProvider"), providerSource) - assertTrue(providerSource.contains("NSBundle.loadableBundle(\"com.example.bundle\")"), providerSource) - assertTrue(providerSource.contains("ResourcePlatformDetails(bundle)"), providerSource) + + // Batch object should be public (visibilityModifier) + assertTrue(batchSource.contains("internal object AndroidMainStrings0"), batchSource) + // Extension property should be public + assertTrue(batchSource.contains("public val MRandroidMain.strings.key_000: StringResource"), batchSource) } private fun createCommonGenerator(): ResourceTypeGenerator { @@ -188,8 +201,7 @@ class StringBatchingTest { return createGenerator( platformResourceGenerator = AppleStringResourceGenerator( baseLocalizationRegion = "en", - resourcesGenerationDir = File("."), - bundleIdentifier = "com.example.bundle" + resourcesGenerationDir = File(".") ) ) } @@ -206,8 +218,7 @@ class StringBatchingTest { generator = StringResourceGenerator(strictLineBreaks = false), platformResourceGenerator = platformResourceGenerator, filter = {}, - resourcesPackageName = PACKAGE_NAME, - generatePropertiesAsExtensions = true + resourcesPackageName = PACKAGE_NAME ) } From 5f454253ecaf41535039e7fee16ae391aae2f358 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 11 Jun 2026 23:21:18 +0700 Subject: [PATCH 04/26] Update samples for batched resource access --- .../kotlin/com/icerockdev/mpp/MainActivity.kt | 11 ++++++++-- .../moko-resources/base/strings.xml | 4 ++++ .../kotlin/com/icerockdev/library/TestRes.kt | 4 ++++ .../moko-resources/base/strings.xml | 22 +++++++++++++++++++ .../gradle.properties | 2 ++ .../src/commonMain/kotlin/Main.macos.kt | 1 + .../shared/src/commonMain/kotlin/App.kt | 16 +++++++++++++- 7 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 samples/android-mpp-app/app/src/androidMain/moko-resources/base/strings.xml diff --git a/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt b/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt index 5ce14f92c..b25dfce64 100755 --- a/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt +++ b/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt @@ -6,13 +6,20 @@ package com.icerockdev.mpp import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import com.icerockdev.library.TestRes +import com.icerockdev.library.MR +import com.icerockdev.library.MRandroidMain +import com.icerockdev.library.android_name +import com.icerockdev.library.common_name class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + println(MR.strings.common_name) + println(MRandroidMain.strings.android_name) + MR.strings.values().forEach { + println("DBG: $it ${it.getString(this)}") - TestRes.test() + } } } diff --git a/samples/android-mpp-app/app/src/androidMain/moko-resources/base/strings.xml b/samples/android-mpp-app/app/src/androidMain/moko-resources/base/strings.xml new file mode 100644 index 000000000..23223c55e --- /dev/null +++ b/samples/android-mpp-app/app/src/androidMain/moko-resources/base/strings.xml @@ -0,0 +1,4 @@ + + + Test Project + \ No newline at end of file diff --git a/samples/android-mpp-app/app/src/commonMain/kotlin/com/icerockdev/library/TestRes.kt b/samples/android-mpp-app/app/src/commonMain/kotlin/com/icerockdev/library/TestRes.kt index 07b1de217..ef95ca4b0 100644 --- a/samples/android-mpp-app/app/src/commonMain/kotlin/com/icerockdev/library/TestRes.kt +++ b/samples/android-mpp-app/app/src/commonMain/kotlin/com/icerockdev/library/TestRes.kt @@ -7,5 +7,9 @@ package com.icerockdev.library object TestRes { fun test() { println(MR.strings.common_name) + println(MR.strings.common_name1) + println(MR.strings.common_name10) + println(MR.strings.common_name20) + println(MR.strings.common_name22) } } diff --git a/samples/android-mpp-app/app/src/commonMain/moko-resources/base/strings.xml b/samples/android-mpp-app/app/src/commonMain/moko-resources/base/strings.xml index c4c177224..9387846a3 100644 --- a/samples/android-mpp-app/app/src/commonMain/moko-resources/base/strings.xml +++ b/samples/android-mpp-app/app/src/commonMain/moko-resources/base/strings.xml @@ -1,4 +1,26 @@ Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project + Test Project \ No newline at end of file diff --git a/samples/compose-resources-gallery/gradle.properties b/samples/compose-resources-gallery/gradle.properties index 792e28e1c..3553881c4 100644 --- a/samples/compose-resources-gallery/gradle.properties +++ b/samples/compose-resources-gallery/gradle.properties @@ -19,6 +19,8 @@ org.jetbrains.compose.experimental.uikit.enabled=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.mpp.androidGradlePluginCompatibility.nowarn=true +moko.resources.disableStaticFrameworkWarning=true + # update to future versions after fix of https://youtrack.jetbrains.com/issue/CMP-7207 kotlin.version=2.1.0 agp.version=8.4.0 diff --git a/samples/compose-resources-gallery/macosApp/src/commonMain/kotlin/Main.macos.kt b/samples/compose-resources-gallery/macosApp/src/commonMain/kotlin/Main.macos.kt index 2a1c746aa..68236dc95 100644 --- a/samples/compose-resources-gallery/macosApp/src/commonMain/kotlin/Main.macos.kt +++ b/samples/compose-resources-gallery/macosApp/src/commonMain/kotlin/Main.macos.kt @@ -1,5 +1,6 @@ import androidx.compose.ui.window.Window import com.icerockdev.library.MR +import com.icerockdev.library.hello_world import dev.icerock.moko.resources.desc.desc import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.staticCFunction diff --git a/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt b/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt index beeeac34d..dc975ba6f 100644 --- a/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt +++ b/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt @@ -23,6 +23,20 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.icerockdev.library.MR +import com.icerockdev.library.car_black +import com.icerockdev.library.chars_count +import com.icerockdev.library.cormorant_italic +import com.icerockdev.library.cr +import com.icerockdev.library.font_style_text +import com.icerockdev.library.hello_world +import com.icerockdev.library.innerFile_txt +import com.icerockdev.library.innerText_txt +import com.icerockdev.library.moko_logo +import com.icerockdev.library.new_line_test +import com.icerockdev.library.second_inner_text_file_txt +import com.icerockdev.library.some_asset_txt +import com.icerockdev.library.symbols_text +import com.icerockdev.library.textColor import dev.icerock.moko.resources.compose.colorResource import dev.icerock.moko.resources.compose.fontFamilyResource import dev.icerock.moko.resources.compose.painterResource @@ -103,7 +117,7 @@ internal fun App() { color = MaterialTheme.colors.onBackground, ) - val fileContent: String? by MR.files.some_file_txt.readTextAsState() + val fileContent: String? by MR.files.innerDirWithSingleFile.innerFile_txt.readTextAsState() Text( modifier = Modifier.padding(top = 16.dp), text = fileContent.orEmpty(), From 70d4d2321b9c37e1670f30942381b81b9b211fa1 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 11 Jun 2026 23:56:48 +0700 Subject: [PATCH 05/26] reformat --- .../gradle/generator/CodeGenerators.kt | 169 +----------------- .../gradle/generator/ResourceTypeGenerator.kt | 45 ++++- .../string/AppleStringResourceGenerator.kt | 1 - 3 files changed, 39 insertions(+), 176 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index 834300fd2..7d27fe754 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -6,8 +6,8 @@ package dev.icerock.gradle.generator -import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.AnnotationSpec +import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec @@ -16,36 +16,12 @@ import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.STRING import com.squareup.kotlinpoet.TypeSpec -import dev.icerock.gradle.generator.Constants.Apple import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.platform.js.JsFilePathMode import dev.icerock.gradle.metadata.resource.HierarchyMetadata import dev.icerock.gradle.metadata.resource.ResourceMetadata import org.gradle.api.GradleException -import kotlin.DeprecationLevel - -internal fun TypeSpec.Builder.addAppleResourcesBundleProperty(bundleIdentifier: String) { - val bundleProperty: PropertySpec = PropertySpec.builder( - Apple.resourcesBundlePropertyName, - Apple.nsBundleName, - KModifier.PRIVATE - ).delegate(CodeBlock.of("lazy { NSBundle.loadableBundle(%S) }", bundleIdentifier)) - .build() - - addProperty(bundleProperty) -} - -internal fun FileSpec.Builder.addAppleResourcesBundleProperty(bundleIdentifier: String) { - addProperty( - PropertySpec.builder( - Apple.resourcesBundlePropertyName, - Apple.nsBundleName, - KModifier.PRIVATE - ).delegate(CodeBlock.of("lazy { NSBundle.loadableBundle(%S) }", bundleIdentifier)) - .build() - ) -} internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { val bundleProperty: PropertySpec = @@ -65,45 +41,6 @@ internal fun TypeSpec.Builder.addAppleContainerBundleInitializerProperty( ) } -internal fun TypeSpec.Builder.addAppleBatchedBundleInitializerProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of( - "${PlatformDetails.platformDetailsClass}(${Apple.resourcesBundlePropertyName})" - ) - ) -} - -internal fun FileSpec.Builder.addAppleBatchedBundleInitializerProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of( - "${PlatformDetails.platformDetailsClass}(${Apple.resourcesBundlePropertyName})" - ) - ) -} - -internal fun TypeSpec.Builder.addJvmClassLoaderProperty(resourcesClassName: String) { - val property: PropertySpec = PropertySpec.builder( - Jvm.resourcesClassLoaderPropertyName, - Jvm.classLoaderName, - KModifier.PRIVATE - ).initializer(CodeBlock.of("$resourcesClassName::class.java.classLoader")) - .build() - - addProperty(property) -} - -internal fun FileSpec.Builder.addJvmClassLoaderProperty(resourcesClassName: String) { - addImport("kotlin.jvm", "java") - addProperty( - PropertySpec.builder( - Jvm.resourcesClassLoaderPropertyName, - Jvm.classLoaderName, - KModifier.PRIVATE - ).initializer(CodeBlock.of("$resourcesClassName::class.java.classLoader")) - .build() - ) -} - internal fun TypeSpec.Builder.addJvmPlatformResourceClassLoaderProperty( modifier: KModifier? = null, ) { @@ -113,22 +50,6 @@ internal fun TypeSpec.Builder.addJvmPlatformResourceClassLoaderProperty( ) } -internal fun TypeSpec.Builder.addJvmBatchedPlatformResourceClassLoaderProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of( - "${PlatformDetails.platformDetailsClass}(${Jvm.resourcesClassLoaderPropertyName})" - ) - ) -} - -internal fun FileSpec.Builder.addJvmBatchedPlatformResourceClassLoaderProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of( - "${PlatformDetails.platformDetailsClass}(${Jvm.resourcesClassLoaderPropertyName})" - ) - ) -} - internal fun TypeSpec.Builder.addJvmPlatformResourceBundleProperty( bundlePropertyName: String, bundlePath: String @@ -166,18 +87,6 @@ internal fun TypeSpec.Builder.addEmptyPlatformResourceProperty( ) } -internal fun TypeSpec.Builder.addEmptyBatchedPlatformResourceProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of("${PlatformDetails.platformDetailsClass}()") - ) -} - -internal fun FileSpec.Builder.addEmptyBatchedPlatformResourceProperty() { - addBatchedPlatformDetailsProperty( - initializer = CodeBlock.of("${PlatformDetails.platformDetailsClass}()") - ) -} - internal fun TypeSpec.Builder.addValuesFunction( metadata: List, classType: ClassName, @@ -195,36 +104,7 @@ internal fun TypeSpec.Builder.addValuesFunction( ) } -internal fun TypeSpec.Builder.addPlainValuesFunction( - metadata: List, - classType: ClassName, - modifier: KModifier? = null, - memberModifier: KModifier? = null, - isExpect: Boolean = false, -) { - addResourceValuesFunction( - metadata = metadata, - classType = classType, - modifier = modifier, - memberModifier = memberModifier, - isOverride = false, - isExpect = isExpect - ) -} - -internal fun TypeSpec.Builder.addAbstractValuesFunction( - classType: ClassName, -): TypeSpec.Builder { - val valuesFun: FunSpec = FunSpec.builder("values") - .returns( - ClassName(packageName = "kotlin.collections", "List") - .parameterizedBy(classType) - ) - .build() - - return addFunction(valuesFun) -} - +@Suppress("LongMethod", "LongParameterList") private fun TypeSpec.Builder.addResourceValuesFunction( metadata: List, classType: ClassName, @@ -486,21 +366,6 @@ internal fun TypeSpec.Builder.addJsContainerStringsLoaderProperty() { addProperty(property) } -internal fun TypeSpec.Builder.addJsBatchedStringsLoaderProperty() { - val property = PropertySpec.builder( - Constants.Js.stringsLoaderPropertyName, - Constants.Js.stringLoaderName, - KModifier.PRIVATE - ).initializer( - CodeBlock.of( - "${Constants.Js.remoteStringLoaderClassName}.Impl(supportedLocales = %N, fallbackFileUri = %N)", - Constants.Js.supportedLocalesPropertyName, - Constants.Js.fallbackFilePropertyName - ) - ).build() - addProperty(property) -} - internal fun FileSpec.Builder.addJsBatchedStringsLoaderProperty() { addProperty( PropertySpec.builder( @@ -538,33 +403,3 @@ private fun TypeSpec.Builder.addContainerPlatformDetailsProperty( addProperty(resourcePlatformDetailsPropertySpec) } - -private fun TypeSpec.Builder.addBatchedPlatformDetailsProperty( - initializer: CodeBlock, -) { - val resourcePlatformDetailsPropertySpec = PropertySpec - .builder( - PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName, - KModifier.PRIVATE - ) - .initializer(initializer) - .build() - - addProperty(resourcePlatformDetailsPropertySpec) -} - -private fun FileSpec.Builder.addBatchedPlatformDetailsProperty( - initializer: CodeBlock, -) { - addProperty( - PropertySpec - .builder( - PlatformDetails.platformDetailsPropertyName, - Constants.resourcePlatformDetailsName, - KModifier.PRIVATE - ) - .initializer(initializer) - .build() - ) -} diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 179e94ed2..6946466bc 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -264,6 +264,7 @@ internal class ResourceTypeGenerator( } } + @Suppress("LongMethod") private fun createBatchFileSpecs( parentObjectName: String, objectName: String, @@ -349,8 +350,18 @@ internal class ResourceTypeGenerator( ) { resources.forEach { resource -> fileSpec.addProperty( - PropertySpec.builder(resource.key, resourceClass) - .receiver(getReceiverClassName(parentObjectName, objectName, resource.pathSegments())) + PropertySpec + .builder( + name = resource.key, + type = resourceClass + ) + .receiver( + receiverType = getReceiverClassName( + parentObjectName = parentObjectName, + objectName = objectName, + path = resource.pathSegments() + ) + ) .addModifiers(visibilityModifier, KModifier.EXPECT) .build() ) @@ -368,8 +379,18 @@ internal class ResourceTypeGenerator( resources.forEach { resource -> val resourcePath: List = resource.metadata.pathSegments() fileSpec.addProperty( - PropertySpec.builder(resource.metadata.key, resourceClass) - .receiver(getReceiverClassName(parentObjectName, objectName, resourcePath)) + PropertySpec + .builder( + name = resource.metadata.key, + type = resourceClass + ) + .receiver( + receiverType = getReceiverClassName( + parentObjectName = parentObjectName, + objectName = objectName, + path = resourcePath + ) + ) .addModifiers(visibilityModifier) .also { property -> if (actualModifier != null) { @@ -395,7 +416,10 @@ internal class ResourceTypeGenerator( fileName = fileName ).also { fileSpec -> platformResourceGenerator.imports().forEach { import -> - fileSpec.addImport(import.packageName, import.simpleNames) + fileSpec.addImport( + packageName = import.packageName, + names = import.simpleNames + ) } } } @@ -405,17 +429,22 @@ internal class ResourceTypeGenerator( objectName: String, path: List = emptyList(), ): ClassName { - val simpleNames: Array = arrayOf(parentObjectName, objectName, *path.toTypedArray()) return ClassName( packageName = requireResourcesPackageName(), - *simpleNames + simpleNames = listOf( + parentObjectName, + objectName + ) + path ) } private fun buildBatchedResources(resources: List): List> { if (!isHierarchyPropertiesStrategy()) { return resources.map { resource -> - BatchedResource(metadata = resource, internalName = resource.key) + BatchedResource( + metadata = resource, + internalName = resource.key + ) } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt index 5fdf29265..15033a5f5 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt @@ -97,5 +97,4 @@ internal class AppleStringResourceGenerator( regionFile.writeText(content) } } - } From 8edf172f1bb37d950705b3ef9f8ac40973d6a337 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 00:46:36 +0700 Subject: [PATCH 06/26] fixed gradle cache problems --- .../main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt | 2 +- .../icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index 7d27fe754..7f0bcf40b 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -25,7 +25,7 @@ import org.gradle.api.GradleException internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { val bundleProperty: PropertySpec = - PropertySpec.builder("contentHash", STRING, KModifier.PRIVATE) + PropertySpec.builder("contentHash", STRING, KModifier.PUBLIC, KModifier.CONST) .initializer("%S", hash) .build() diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt index 8829cb8b8..0dc29e1f1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt @@ -36,6 +36,7 @@ import org.gradle.api.provider.Property import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile @@ -61,7 +62,7 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { @get:PathSensitive(PathSensitivity.RELATIVE) abstract val ownResources: ConfigurableFileCollection - @get:Input + @get:Internal abstract val upperSourceSets: MapProperty @get:Optional From 518cb969f4f122ec0eb195d49b72989ac1e60a4f Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 01:25:09 +0700 Subject: [PATCH 07/26] rollback hidden platformDetails --- .../dev/icerock/gradle/generator/CodeGenerators.kt | 10 ---------- .../dev/icerock/moko/resources/ResourceContainer.kt | 4 ---- 2 files changed, 14 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index 7f0bcf40b..a1aa999aa 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -6,7 +6,6 @@ package dev.icerock.gradle.generator -import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec @@ -228,7 +227,6 @@ internal fun TypeSpec.Builder.addOverridePlatformProperty(): TypeSpec.Builder { Constants.resourcePlatformDetailsName, KModifier.OVERRIDE ) - .addAnnotation(hiddenInternalApiAnnotation()) .build() return addProperty(resourcePlatformDetailsPropertySpec) @@ -248,13 +246,6 @@ internal fun TypeSpec.Builder.addOverrideAbstractValuesFunction( return addFunction(valuesFun) } -private fun hiddenInternalApiAnnotation(): AnnotationSpec { - return AnnotationSpec.builder(Deprecated::class) - .addMember("message = %S", "Internal resource container detail") - .addMember("level = %T.HIDDEN", DeprecationLevel::class) - .build() -} - internal fun TypeSpec.Builder.addJsFallbackProperty( fallbackFilePath: String, filePathMode: JsFilePathMode @@ -391,7 +382,6 @@ private fun TypeSpec.Builder.addContainerPlatformDetailsProperty( PlatformDetails.platformDetailsPropertyName, Constants.resourcePlatformDetailsName ) - .addAnnotation(hiddenInternalApiAnnotation()) .also { if (modifier != null) { it.addModifiers(modifier) diff --git a/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt b/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt index ccc5b188c..b77b406a7 100644 --- a/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt +++ b/resources/src/commonMain/kotlin/dev/icerock/moko/resources/ResourceContainer.kt @@ -9,10 +9,6 @@ expect fun ResourceContainer.getAssetByFilePath(filePath: String) interface ResourceContainer { @Suppress("VariableNaming") - @Deprecated( - message = "Internal resource container detail", - level = DeprecationLevel.HIDDEN - ) val __platformDetails: ResourcePlatformDetails fun values(): List } From 3213e3940a9abac9161b6f7009fd20b03bb7cbba Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 01:29:25 +0700 Subject: [PATCH 08/26] #731 fixed apple svg image color with opacity --- .../image/AppleImageResourceGenerator.kt | 11 +- .../resources/image/SvgColorTransformer.kt | 117 ++++++++++++++++++ .../image/SvgColorTransformerTest.kt | 76 ++++++++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt create mode 100644 resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt index dd7daf23f..115e1ccee 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt @@ -62,7 +62,16 @@ internal class AppleImageResourceGenerator( resourceIsValidOrError(validItems, imageMetadata) - validItems.forEach { it.filePath.copyTo(File(assetDir, it.filePath.name)) } + validItems.forEach { item -> + val targetFile = File(assetDir, item.filePath.name) + if (item.filePath.extension.equals("svg", ignoreCase = true)) { + val content = item.filePath.readText() + val processedContent = SvgColorTransformer.transform(content) + targetFile.writeText(processedContent) + } else { + item.filePath.copyTo(targetFile) + } + } val imagesContent: JsonArray = getImagesContent(validItems, imageMetadata) val content: String = prepareContentInfo(imagesContent, validItems) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt new file mode 100644 index 000000000..6e70f69b2 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt @@ -0,0 +1,117 @@ +/* + * Copyright 2026 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.resources.image + +import java.util.Locale + +internal object SvgColorTransformer { + private const val HEX_8_LENGTH = 8 + private const val HEX_4_LENGTH = 4 + + fun transform(content: String): String { + val attrNamesPattern = ColorAttribute.allNames.joinToString("|") + val attrRegex = Regex("""($attrNamesPattern)\s*=\s*(['"])#([0-9a-fA-F]+)\2""") + + var result = attrRegex.replace(content) { matchResult -> + val attrName = matchResult.groupValues[1] + val quote = matchResult.groupValues[2] + val hex = matchResult.groupValues[3] + val colorAttr = ColorAttribute.findByName(attrName) + + when (hex.length) { + HEX_8_LENGTH -> { + val rgb = hex.substring(0, 6) + val alpha = hex.substring(6, 8) + val alphaStr = hexToAlpha(alpha) + val opacityAttr = colorAttr?.opacityAttrName + + if (opacityAttr != null) { + """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" + } else { + """$attrName=$quote#$rgb$quote""" + } + } + HEX_4_LENGTH -> { + val rgbShort = hex.substring(0, 3) + val alpha = hex.substring(3, 4) + val rgb = rgbShort.map { "$it$it" }.joinToString("") + val alphaStr = hexToAlpha("$alpha$alpha") + val opacityAttr = colorAttr?.opacityAttrName + + if (opacityAttr != null) { + """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" + } else { + """$attrName=$quote#$rgb$quote""" + } + } + else -> matchResult.value + } + } + + val styleAttrRegex = Regex("""style\s*=\s*(['"])([^"']*)\1""") + result = styleAttrRegex.replace(result) { matchResult -> + val quote = matchResult.groupValues[1] + val styleContent = matchResult.groupValues[2] + + val colorRegex = Regex("""($attrNamesPattern)\s*:\s*#([0-9a-fA-F]+)""") + val transformedStyle = colorRegex.replace(styleContent) { colorMatch -> + val attrName = colorMatch.groupValues[1] + val hex = colorMatch.groupValues[2] + val colorAttr = ColorAttribute.findByName(attrName) + + when (hex.length) { + HEX_8_LENGTH -> { + val rgb = hex.substring(0, 6) + val alpha = hex.substring(6, 8) + val alphaStr = hexToAlpha(alpha) + val opacityAttr = colorAttr?.opacityAttrName + + if (opacityAttr != null) { + """$attrName:#$rgb;$opacityAttr:$alphaStr""" + } else { + """$attrName:#$rgb""" + } + } + HEX_4_LENGTH -> { + val rgbShort = hex.substring(0, 3) + val alpha = hex.substring(3, 4) + val rgb = rgbShort.map { "$it$it" }.joinToString("") + val alphaStr = hexToAlpha("$alpha$alpha") + val opacityAttr = colorAttr?.opacityAttrName + + if (opacityAttr != null) { + """$attrName:#$rgb;$opacityAttr:$alphaStr""" + } else { + """$attrName:#$rgb""" + } + } + else -> colorMatch.value + } + } + """style=$quote$transformedStyle$quote""" + } + + return result + } + + private fun hexToAlpha(hex: String): String { + val alphaInt = hex.toInt(16) + val alphaFloat = alphaInt / 255.0 + return "%.2f".format(Locale.US, alphaFloat) + } +} + +private enum class ColorAttribute(val attrName: String, val opacityAttrName: String?) { + FILL(attrName = "fill", opacityAttrName = "fill-opacity"), + STROKE(attrName = "stroke", opacityAttrName = "stroke-opacity"), + STOP_COLOR(attrName = "stop-color", opacityAttrName = "stop-opacity"), + FLOOD_COLOR(attrName = "flood-color", opacityAttrName = "flood-opacity"), + COLOR(attrName = "color", opacityAttrName = null); + + companion object { + val allNames: List = entries.map { it.attrName } + fun findByName(name: String): ColorAttribute? = entries.find { it.attrName == name } + } +} diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt new file mode 100644 index 000000000..f3fc7c988 --- /dev/null +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2024 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.resources.image + +import org.junit.Test +import kotlin.test.assertEquals + +class SvgColorTransformerTest { + + @Test + fun `test transform fill attribute 8-digit`() { + val input = """""" + val expected = """""" + assertEquals(expected, SvgColorTransformer.transform(input)) + } + + @Test + fun `test transform fill attribute 4-digit`() { + val input = """""" + val expected = """""" + assertEquals(expected, SvgColorTransformer.transform(input)) + } + + @Test + fun `test transform color attribute 8-digit`() { + // color attribute doesn't have a corresponding color-opacity attribute in SVG + val input = """""" + val expected = """""" + assertEquals(expected, SvgColorTransformer.transform(input)) + } + + @Test + fun `test transform style attribute 8-digit`() { + val input = """""" + val expected = """""" + assertEquals(expected, SvgColorTransformer.transform(input)) + } + + @Test + fun `test transform style attribute 4-digit`() { + val input = """""" + val expected = """""" + assertEquals(expected, SvgColorTransformer.transform(input)) + } + + @Test + fun `test user provided sample`() { + val input = """ + + + + """.trimIndent() + val expected = """ + + + + """.trimIndent() + assertEquals(expected, SvgColorTransformer.transform(input)) + } +} From 253a34abbe8899d3e8097867c91eb30c3f53a78e Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 01:34:07 +0700 Subject: [PATCH 09/26] #731 added svg with color with opacity, fixed run on ios simulator --- .../iosApp/iosApp/Info.plist | 2 ++ .../shared/src/commonMain/kotlin/App.kt | 12 +++++++++++ .../images/opacity_test_image.svg | 20 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 samples/compose-resources-gallery/shared/src/commonMain/moko-resources/images/opacity_test_image.svg diff --git a/samples/compose-resources-gallery/iosApp/iosApp/Info.plist b/samples/compose-resources-gallery/iosApp/iosApp/Info.plist index 9a269f5ea..709e3eca6 100644 --- a/samples/compose-resources-gallery/iosApp/iosApp/Info.plist +++ b/samples/compose-resources-gallery/iosApp/iosApp/Info.plist @@ -44,5 +44,7 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + CADisableMinimumFrameDurationOnPhone + diff --git a/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt b/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt index dc975ba6f..5e78644be 100644 --- a/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt +++ b/samples/compose-resources-gallery/shared/src/commonMain/kotlin/App.kt @@ -1,6 +1,7 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -21,6 +22,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.icerockdev.library.MR import com.icerockdev.library.car_black @@ -33,6 +35,7 @@ import com.icerockdev.library.innerFile_txt import com.icerockdev.library.innerText_txt import com.icerockdev.library.moko_logo import com.icerockdev.library.new_line_test +import com.icerockdev.library.opacity_test_image import com.icerockdev.library.second_inner_text_file_txt import com.icerockdev.library.some_asset_txt import com.icerockdev.library.symbols_text @@ -99,6 +102,15 @@ internal fun App() { Text(text = stringResource(MR.strings.hello_world)) } + Box( + modifier = Modifier.background(Color.Red) + ){ + Image( + painter = painterResource(MR.images.opacity_test_image), + contentDescription = null + ) + } + Text( modifier = Modifier.padding(vertical = 8.dp), text = stringResource(MR.strings.new_line_test), diff --git a/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/images/opacity_test_image.svg b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/images/opacity_test_image.svg new file mode 100644 index 000000000..4526861c2 --- /dev/null +++ b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/images/opacity_test_image.svg @@ -0,0 +1,20 @@ + + + + + + + From f1f8fccac1d47ec7abdc2829915682b3591443c3 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 01:51:33 +0700 Subject: [PATCH 10/26] muted MagicNumber for object --- .../gradle/generator/resources/image/SvgColorTransformer.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt index 6e70f69b2..6dbd704a1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt @@ -6,6 +6,7 @@ package dev.icerock.gradle.generator.resources.image import java.util.Locale +@Suppress("MagicNumber") internal object SvgColorTransformer { private const val HEX_8_LENGTH = 8 private const val HEX_4_LENGTH = 4 From 3e184d02113e730de1c8b1799a4790d8d1e194fa Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 02:12:17 +0700 Subject: [PATCH 11/26] reformat --- .../generator/resources/image/SvgColorTransformer.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt index 6dbd704a1..b40f4090e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt @@ -11,10 +11,11 @@ internal object SvgColorTransformer { private const val HEX_8_LENGTH = 8 private const val HEX_4_LENGTH = 4 + @Suppress("LongMethod") fun transform(content: String): String { val attrNamesPattern = ColorAttribute.allNames.joinToString("|") val attrRegex = Regex("""($attrNamesPattern)\s*=\s*(['"])#([0-9a-fA-F]+)\2""") - + var result = attrRegex.replace(content) { matchResult -> val attrName = matchResult.groupValues[1] val quote = matchResult.groupValues[2] @@ -27,7 +28,7 @@ internal object SvgColorTransformer { val alpha = hex.substring(6, 8) val alphaStr = hexToAlpha(alpha) val opacityAttr = colorAttr?.opacityAttrName - + if (opacityAttr != null) { """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" } else { @@ -40,7 +41,7 @@ internal object SvgColorTransformer { val rgb = rgbShort.map { "$it$it" }.joinToString("") val alphaStr = hexToAlpha("$alpha$alpha") val opacityAttr = colorAttr?.opacityAttrName - + if (opacityAttr != null) { """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" } else { @@ -68,7 +69,7 @@ internal object SvgColorTransformer { val alpha = hex.substring(6, 8) val alphaStr = hexToAlpha(alpha) val opacityAttr = colorAttr?.opacityAttrName - + if (opacityAttr != null) { """$attrName:#$rgb;$opacityAttr:$alphaStr""" } else { @@ -81,7 +82,7 @@ internal object SvgColorTransformer { val rgb = rgbShort.map { "$it$it" }.joinToString("") val alphaStr = hexToAlpha("$alpha$alpha") val opacityAttr = colorAttr?.opacityAttrName - + if (opacityAttr != null) { """$attrName:#$rgb;$opacityAttr:$alphaStr""" } else { From 42652ada79a02c3ef6efb5d040b522abcfe70ff5 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Fri, 12 Jun 2026 03:27:29 +0700 Subject: [PATCH 12/26] samples update --- .../kotlin/com/icerockdev/mpp/MainActivity.kt | 5 +---- .../kotlin/me/amikhailov/common/App.kt | 1 + .../kotlin/me/amikhailov/common/Main.kt | 1 + .../shared/src/commonMain/kotlin/App.kt | 2 ++ .../kotlin/com/icerockdev/library/Testing.kt | 17 ++--------------- .../kotlin/com/icerockdev/desktop/Main.kt | 5 ++++- .../jsMain/kotlin/com/icerockdev/web/Main.kt | 1 + 7 files changed, 12 insertions(+), 20 deletions(-) diff --git a/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt b/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt index b25dfce64..abd9e25c1 100755 --- a/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt +++ b/samples/android-mpp-app/app/src/androidMain/kotlin/com/icerockdev/mpp/MainActivity.kt @@ -7,6 +7,7 @@ package com.icerockdev.mpp import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.icerockdev.library.MR +import com.icerockdev.library.MR.strings import com.icerockdev.library.MRandroidMain import com.icerockdev.library.android_name import com.icerockdev.library.common_name @@ -17,9 +18,5 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) println(MR.strings.common_name) println(MRandroidMain.strings.android_name) - MR.strings.values().forEach { - println("DBG: $it ${it.getString(this)}") - - } } } diff --git a/samples/compose-jvm-app/common/src/commonMain/kotlin/me/amikhailov/common/App.kt b/samples/compose-jvm-app/common/src/commonMain/kotlin/me/amikhailov/common/App.kt index bb170ee08..1d0ee0aea 100644 --- a/samples/compose-jvm-app/common/src/commonMain/kotlin/me/amikhailov/common/App.kt +++ b/samples/compose-jvm-app/common/src/commonMain/kotlin/me/amikhailov/common/App.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import com.icerockdev.app.MR +import com.icerockdev.app.hello_world @Composable fun App() { diff --git a/samples/compose-jvm-app/common/src/desktopMain/kotlin/me/amikhailov/common/Main.kt b/samples/compose-jvm-app/common/src/desktopMain/kotlin/me/amikhailov/common/Main.kt index ed978ade1..ebc76eb04 100644 --- a/samples/compose-jvm-app/common/src/desktopMain/kotlin/me/amikhailov/common/Main.kt +++ b/samples/compose-jvm-app/common/src/desktopMain/kotlin/me/amikhailov/common/Main.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.WindowState import androidx.compose.ui.window.singleWindowApplication import com.icerockdev.app.MRdesktopMain +import com.icerockdev.app.title fun main() { singleWindowApplication( diff --git a/samples/ios-cocoapods-static-framework/shared/src/commonMain/kotlin/App.kt b/samples/ios-cocoapods-static-framework/shared/src/commonMain/kotlin/App.kt index c32803090..1dafa2177 100644 --- a/samples/ios-cocoapods-static-framework/shared/src/commonMain/kotlin/App.kt +++ b/samples/ios-cocoapods-static-framework/shared/src/commonMain/kotlin/App.kt @@ -13,6 +13,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.share.resources.module.MR +import com.share.resources.module.action_back_white +import com.share.resources.module.hello_world import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource diff --git a/samples/kotlin-ios-app/mpp-library/src/appleMain/kotlin/com/icerockdev/library/Testing.kt b/samples/kotlin-ios-app/mpp-library/src/appleMain/kotlin/com/icerockdev/library/Testing.kt index 571cecc22..40c567f7f 100644 --- a/samples/kotlin-ios-app/mpp-library/src/appleMain/kotlin/com/icerockdev/library/Testing.kt +++ b/samples/kotlin-ios-app/mpp-library/src/appleMain/kotlin/com/icerockdev/library/Testing.kt @@ -4,23 +4,10 @@ package com.icerockdev.library -import dev.icerock.moko.resources.AssetResource -import dev.icerock.moko.resources.ColorResource -import dev.icerock.moko.resources.FileResource -import dev.icerock.moko.resources.FontResource -import dev.icerock.moko.resources.ImageResource -import dev.icerock.moko.resources.desc.Plural -import dev.icerock.moko.resources.desc.PluralFormatted -import dev.icerock.moko.resources.desc.Raw -import dev.icerock.moko.resources.desc.Resource -import dev.icerock.moko.resources.desc.ResourceFormatted import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc -import dev.icerock.moko.resources.desc.joinToStringDesc -import dev.icerock.moko.resources.desc.plus -import dev.icerock.moko.resources.format -import dev.icerock.moko.resources.getAssetByFilePath -import dev.icerock.moko.resources.getImageByFileName +import com.icerockdev.library.MR +import com.icerockdev.library.hello_world object Testing { diff --git a/samples/resources-gallery/jvm-app/src/jvmMain/kotlin/com/icerockdev/desktop/Main.kt b/samples/resources-gallery/jvm-app/src/jvmMain/kotlin/com/icerockdev/desktop/Main.kt index 808164746..ed6bca83b 100644 --- a/samples/resources-gallery/jvm-app/src/jvmMain/kotlin/com/icerockdev/desktop/Main.kt +++ b/samples/resources-gallery/jvm-app/src/jvmMain/kotlin/com/icerockdev/desktop/Main.kt @@ -21,8 +21,11 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.WindowState import androidx.compose.ui.window.singleWindowApplication +import com.icerockdev.app.AppMR +import com.icerockdev.app.customHelloWorld import com.icerockdev.library.MR import com.icerockdev.library.Testing +import com.icerockdev.library.textColor fun main() { val testing = Testing @@ -43,7 +46,7 @@ fun main() { modifier = Modifier.size(56.dp) ) - Text(text = com.icerockdev.app.AppMR.strings.customHelloWorld.localized()) + Text(text = AppMR.strings.customHelloWorld.localized()) val image by produceState (null){ try { diff --git a/samples/resources-gallery/web-app/src/jsMain/kotlin/com/icerockdev/web/Main.kt b/samples/resources-gallery/web-app/src/jsMain/kotlin/com/icerockdev/web/Main.kt index dae268c33..591521cfc 100644 --- a/samples/resources-gallery/web-app/src/jsMain/kotlin/com/icerockdev/web/Main.kt +++ b/samples/resources-gallery/web-app/src/jsMain/kotlin/com/icerockdev/web/Main.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import com.icerockdev.library.MR import com.icerockdev.library.Testing +import com.icerockdev.library.some_json import kotlinx.browser.window import org.jetbrains.compose.web.css.DisplayStyle import org.jetbrains.compose.web.css.FlexDirection From 76b421a565aeac1317d6e795a05954682cca900a Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Sun, 14 Jun 2026 21:42:30 +0700 Subject: [PATCH 13/26] updated last samples --- .../src/commonMain/kotlin/com/icerock/cm/sample/app/App.kt | 5 ++++- .../src/commonMain/kotlin/com/gradle9sample/Greeting.kt | 1 + .../src/commonMain/kotlin/app/kotlin2sample/Greeting.kt | 1 + .../src/commonMain/kotlin/app/kotlin2sample/Greeting.kt | 1 + .../commonTest/kotlin/testutils/GeneratedResourcesTest.kt | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/samples/cm-resources-sample/composeApp/src/commonMain/kotlin/com/icerock/cm/sample/app/App.kt b/samples/cm-resources-sample/composeApp/src/commonMain/kotlin/com/icerock/cm/sample/app/App.kt index e6f652938..1f83a7ed8 100644 --- a/samples/cm-resources-sample/composeApp/src/commonMain/kotlin/com/icerock/cm/sample/app/App.kt +++ b/samples/cm-resources-sample/composeApp/src/commonMain/kotlin/com/icerock/cm/sample/app/App.kt @@ -52,6 +52,9 @@ import org.jetbrains.compose.resources.Font import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.resources.vectorResource import com.icerock.cm.sample.library.MokoRes +import com.icerock.cm.sample.library.hello_world +import com.icerock.cm.sample.library.moko_logo +import dev.icerock.moko.resources.compose.stringResource as mokoStringResource @Composable internal fun App() = AppTheme { @@ -127,7 +130,7 @@ internal fun App() = AppTheme { } Text("Moko resources:") Text( - text = dev.icerock.moko.resources.compose.stringResource(MokoRes.strings.hello_world) + text = mokoStringResource(MokoRes.strings.hello_world) ) Image( modifier = Modifier diff --git a/samples/gradle-agp-9-sample/shared/src/commonMain/kotlin/com/gradle9sample/Greeting.kt b/samples/gradle-agp-9-sample/shared/src/commonMain/kotlin/com/gradle9sample/Greeting.kt index 7a51c2844..072bc3af5 100644 --- a/samples/gradle-agp-9-sample/shared/src/commonMain/kotlin/com/gradle9sample/Greeting.kt +++ b/samples/gradle-agp-9-sample/shared/src/commonMain/kotlin/com/gradle9sample/Greeting.kt @@ -1,6 +1,7 @@ package com.gradle9sample import app.gradle9sample.library.MR +import app.gradle9sample.library.hello_world import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc diff --git a/samples/kotlin-2-dynamic-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt b/samples/kotlin-2-dynamic-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt index e2428e433..0b79e8f93 100644 --- a/samples/kotlin-2-dynamic-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt +++ b/samples/kotlin-2-dynamic-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt @@ -1,6 +1,7 @@ package app.kotlin2sample import app.kotlin2sample.library.MR +import app.kotlin2sample.library.hello_world import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc diff --git a/samples/kotlin-2-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt b/samples/kotlin-2-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt index e2428e433..0b79e8f93 100644 --- a/samples/kotlin-2-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt +++ b/samples/kotlin-2-sample/shared/src/commonMain/kotlin/app/kotlin2sample/Greeting.kt @@ -1,6 +1,7 @@ package app.kotlin2sample import app.kotlin2sample.library.MR +import app.kotlin2sample.library.hello_world import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc diff --git a/samples/kotlin-2-tests/shared/src/commonTest/kotlin/testutils/GeneratedResourcesTest.kt b/samples/kotlin-2-tests/shared/src/commonTest/kotlin/testutils/GeneratedResourcesTest.kt index 3c4389dd8..fd7a8116c 100644 --- a/samples/kotlin-2-tests/shared/src/commonTest/kotlin/testutils/GeneratedResourcesTest.kt +++ b/samples/kotlin-2-tests/shared/src/commonTest/kotlin/testutils/GeneratedResourcesTest.kt @@ -7,6 +7,7 @@ package testutils import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import template.composemultiplatform.shared.SharedRes +import template.composemultiplatform.shared.appName import kotlin.test.Test class GeneratedResourcesTest : MultiPlatformTest() { From 222d776638c4e791cd7806d839875ecad54bc070 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Sun, 14 Jun 2026 22:45:36 +0700 Subject: [PATCH 14/26] fix: gradle 9 sample --- .../kotlin/com/icerock/library/PluralResourceEnTests.kt | 2 ++ .../kotlin/com/icerock/library/PluralResourceRuTests.kt | 2 ++ .../kotlin/com/icerock/library/StringResourceEnTests.kt | 1 + .../kotlin/com/icerock/library/StringResourceRuTests.kt | 1 + 4 files changed, 6 insertions(+) diff --git a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt index 371c2b701..d6cf32387 100644 --- a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt +++ b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt @@ -5,6 +5,8 @@ package com.icerock.library import app.gradle9sample.library.MR +import app.gradle9sample.library.test_plural +import app.gradle9sample.library.test_plural_fallback import dev.icerock.moko.resources.desc.desc import kotlin.test.Ignore import kotlin.test.Test diff --git a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt index 861a51ff0..9aff5543a 100644 --- a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt +++ b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt @@ -5,6 +5,8 @@ package com.icerock.library import app.gradle9sample.library.MR +import app.gradle9sample.library.test_plural +import app.gradle9sample.library.test_plural_fallback import dev.icerock.moko.resources.desc.desc import kotlin.test.Ignore import kotlin.test.Test diff --git a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt index 9c430d651..3362acf12 100644 --- a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt +++ b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt @@ -5,6 +5,7 @@ package com.icerock.library import app.gradle9sample.library.MR +import app.gradle9sample.library.test import dev.icerock.moko.resources.desc.desc import kotlin.test.Test diff --git a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt index 960113674..2b0a862e1 100644 --- a/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt +++ b/samples/gradle-agp-9-sample/shared/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt @@ -5,6 +5,7 @@ package com.icerock.library import app.gradle9sample.library.MR +import app.gradle9sample.library.test import dev.icerock.moko.resources.desc.desc import kotlin.test.Test From a9c3821d5fe1505add2eff88935817d27c353bbc Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Sun, 14 Jun 2026 23:11:36 +0700 Subject: [PATCH 15/26] updated generator api, removed unused code --- .../gradle/generator/CodeGenerators.kt | 92 +------ .../generator/PlatformResourceGenerator.kt | 24 +- .../gradle/generator/ResourceTypeGenerator.kt | 80 +++--- .../factory/StringGeneratorFactory.kt | 2 +- .../asset/AndroidAssetResourceGenerator.kt | 16 +- .../asset/AppleAssetResourceGenerator.kt | 19 +- .../asset/JsAssetResourceGenerator.kt | 16 +- .../asset/JvmAssetResourceGenerator.kt | 19 +- .../color/AndroidColorResourceGenerator.kt | 16 +- .../color/AppleColorResourceGenerator.kt | 19 +- .../color/JsColorResourceGenerator.kt | 28 +- .../color/JvmColorResourceGenerator.kt | 15 +- .../file/AndroidFileResourceGenerator.kt | 16 +- .../file/AppleFileResourceGenerator.kt | 19 +- .../resources/file/JsFileResourceGenerator.kt | 16 +- .../file/JvmFileResourceGenerator.kt | 19 +- .../font/AndroidFontResourceGenerator.kt | 15 +- .../font/AppleFontResourceGenerator.kt | 19 +- .../resources/font/JsFontResourceGenerator.kt | 24 +- .../font/JvmFontResourceGenerator.kt | 19 +- .../image/AndroidImageResourceGenerator.kt | 16 +- .../image/AppleImageResourceGenerator.kt | 19 +- .../image/JsImageResourceGenerator.kt | 29 +- .../image/JvmImageResourceGenerator.kt | 19 +- .../plural/AndroidPluralResourceGenerator.kt | 16 +- .../plural/ApplePluralResourceGenerator.kt | 19 +- .../plural/JsPluralResourceGenerator.kt | 34 +-- .../plural/JvmPluralResourceGenerator.kt | 19 +- .../string/AndroidStringResourceGenerator.kt | 16 +- .../string/AppleStringResourceGenerator.kt | 19 +- .../string/JsStringResourceGenerator.kt | 34 +-- .../string/JvmStringResourceGenerator.kt | 20 +- .../gradle/generator/StringBatchingTest.kt | 253 ------------------ 33 files changed, 129 insertions(+), 877 deletions(-) delete mode 100644 resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index a1aa999aa..8b185ced8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -18,9 +18,7 @@ import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.platform.js.JsFilePathMode -import dev.icerock.gradle.metadata.resource.HierarchyMetadata import dev.icerock.gradle.metadata.resource.ResourceMetadata -import org.gradle.api.GradleException internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { val bundleProperty: PropertySpec = @@ -86,81 +84,9 @@ internal fun TypeSpec.Builder.addEmptyPlatformResourceProperty( ) } -internal fun TypeSpec.Builder.addValuesFunction( - metadata: List, - classType: ClassName, - modifier: KModifier? = null, - memberModifier: KModifier? = null, - isExpect: Boolean = false, -) { - addResourceValuesFunction( - metadata = metadata, - classType = classType, - modifier = modifier, - memberModifier = memberModifier, - isOverride = true, - isExpect = isExpect - ) -} - -@Suppress("LongMethod", "LongParameterList") -private fun TypeSpec.Builder.addResourceValuesFunction( - metadata: List, - classType: ClassName, - modifier: KModifier?, - memberModifier: KModifier?, - isOverride: Boolean, - isExpect: Boolean = false, -) { - // Find metadata type - val resourceMetadata: T = metadata.first() - val languageKeysList: String = - if (resourceMetadata is HierarchyMetadata) { - // For Assets and Files need create key considering File path - val hierarchyMetadata: List = metadata - .filterIsInstance() - .takeIf { - it.size == metadata.size - } ?: throw GradleException("Invalid ResourceMetadata type for Assets or Files") - - hierarchyMetadata.joinToString { meta -> - meta.path.joinToString(separator = ".") + - (".".takeIf { meta.path.isNotEmpty() } ?: "") + - meta.key - } - } else { - // Create simple resource key - metadata.joinToString { it.key } - } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (memberModifier != null) { - it.addModifiers(memberModifier) - } - if (modifier != null) { - it.addModifiers(modifier) - } - if (isOverride) { - it.addModifiers(KModifier.OVERRIDE) - } - } - .apply { - if (!isExpect) { - addStatement("return listOf($languageKeysList)") - } - } - .returns( - ClassName(packageName = "kotlin.collections", "List") - .parameterizedBy(classType) - ) - .build() - - addFunction(valuesFun) -} -internal fun TypeSpec.Builder.addBatchValuesFunction( - groupNames: List, +internal fun TypeSpec.Builder.addValuesFunctionFromAccessors( + accessorObjectNames: List, classType: ClassName, modifier: KModifier? = null, ) { @@ -174,14 +100,14 @@ internal fun TypeSpec.Builder.addBatchValuesFunction( .addCode( CodeBlock.builder() .apply { - if (groupNames.isEmpty()) { + if (accessorObjectNames.isEmpty()) { addStatement("return emptyList()") - } else if (groupNames.size == 1) { - addStatement("return %N.values()", groupNames.single()) + } else if (accessorObjectNames.size == 1) { + addStatement("return %N.values()", accessorObjectNames.single()) } else { add("return listOf(\n") - groupNames.forEach { groupName -> - add("%N.values(),\n", groupName) + accessorObjectNames.forEach { accessorObjectName -> + add("%N.values(),\n", accessorObjectName) } add(").flatten()\n") } @@ -197,7 +123,7 @@ internal fun TypeSpec.Builder.addBatchValuesFunction( addFunction(valuesFun) } -internal fun TypeSpec.Builder.addReferencedValuesFunction( +internal fun TypeSpec.Builder.addAccessorValuesFunction( propertyReferences: List, classType: ClassName, memberModifier: KModifier? = null, @@ -357,7 +283,7 @@ internal fun TypeSpec.Builder.addJsContainerStringsLoaderProperty() { addProperty(property) } -internal fun FileSpec.Builder.addJsBatchedStringsLoaderProperty() { +internal fun FileSpec.Builder.addJsAccessorFileStringsLoaderProperty() { addProperty( PropertySpec.builder( Constants.Js.stringsLoaderPropertyName, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt index fd7d1cd66..5708f9ccb 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt @@ -14,32 +14,32 @@ import dev.icerock.gradle.metadata.resource.ResourceMetadata internal interface PlatformResourceGenerator { fun imports(): List - fun generateBeforeProperties( + fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier? = null, ) = Unit - fun generateBeforeBatchedFile( - builder: FileSpec.Builder, + fun generateContainerMembers( + builder: Builder, metadata: List, - objectName: String, + modifier: KModifier? = null, ) = Unit - fun generateAfterProperties( - builder: Builder, + fun generateAccessorFilePreamble( + builder: FileSpec.Builder, metadata: List, - modifier: KModifier? = null, + objectName: String, ) = Unit - fun generateBatchedInitializer(metadata: T): CodeBlock = generateInitializer(metadata) + fun generateAccessorInitializer(metadata: T): CodeBlock = generateInitializer(metadata) - fun generateBatchedInitializer( + fun generateAccessorInitializer( metadata: T, - batchObjectName: String, - ): CodeBlock = generateBatchedInitializer(metadata) + accessorObjectName: String, + ): CodeBlock = generateAccessorInitializer(metadata) - fun generateAdditionalBatchedFiles(packageName: String): List = emptyList() + fun generateAdditionalAccessorFiles(packageName: String): List = emptyList() fun generateInitializer(metadata: T): CodeBlock fun generateResourceFiles(data: List) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 6946466bc..7edbbfa4c 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -114,7 +114,7 @@ internal class ResourceTypeGenerator( // implement ResourceType<**Resource> for extensions .addSuperinterface(Constants.resourceContainerName.parameterizedBy(resourceClass)) .also { builder -> - platformResourceGenerator.generateBeforeProperties( + platformResourceGenerator.generateContainerProperties( builder = builder, metadata = typeResources, modifier = KModifier.ACTUAL, @@ -131,8 +131,8 @@ internal class ResourceTypeGenerator( } ) } - builder.addBatchValuesFunction( - groupNames = getBatchGroupNames( + builder.addValuesFunctionFromAccessors( + accessorObjectNames = getAccessorObjectNames( sourceSetName = typeObject.sourceSetName ?: sourceSetName, objectName = typeObject.name, resources = typeResources @@ -140,16 +140,21 @@ internal class ResourceTypeGenerator( classType = resourceClass, modifier = KModifier.ACTUAL ) + platformResourceGenerator.generateContainerMembers( + builder = builder, + metadata = typeResources, + modifier = KModifier.ACTUAL, + ) } - val fileSpecs: List = createBatchFileSpecs( + val fileSpecs: List = createAccessorFileSpecs( parentObjectName = parentObjectName, objectName = typeObject.name, resourceSourceSetName = typeObject.sourceSetName ?: sourceSetName, targetSourceSetName = sourceSetName, resources = typeResources, actualModifier = KModifier.ACTUAL - ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) + ) + platformResourceGenerator.generateAdditionalAccessorFiles(requireResourcesPackageName()) return GenerationResult( typeSpec = objectBuilder.build(), @@ -184,7 +189,7 @@ internal class ResourceTypeGenerator( .addSuperinterface(Constants.resourceContainerName.parameterizedBy(resourceClass)) // implement interfaces for generated expect object .also { builder -> - platformResourceGenerator.generateBeforeProperties( + platformResourceGenerator.generateContainerProperties( builder = builder, metadata = typeResources, ) @@ -200,24 +205,28 @@ internal class ResourceTypeGenerator( } ) } - builder.addBatchValuesFunction( - groupNames = getBatchGroupNames( + builder.addValuesFunctionFromAccessors( + accessorObjectNames = getAccessorObjectNames( sourceSetName = sourceSetName, objectName = objectName, resources = typeResources ), classType = resourceClass ) + platformResourceGenerator.generateContainerMembers( + builder = builder, + metadata = typeResources, + ) } - val fileSpecs: List = createBatchFileSpecs( + val fileSpecs: List = createAccessorFileSpecs( parentObjectName = parentObjectName, objectName = objectName, resourceSourceSetName = sourceSetName, targetSourceSetName = sourceSetName, resources = typeResources, actualModifier = null - ) + platformResourceGenerator.generateAdditionalBatchedFiles(requireResourcesPackageName()) + ) + platformResourceGenerator.generateAdditionalAccessorFiles(requireResourcesPackageName()) return GenerationResult( typeSpec = objectBuilder.build(), @@ -245,13 +254,13 @@ internal class ResourceTypeGenerator( resources: List, ): List { return resources.chunked(batchSize).mapIndexed { index, batch -> - val groupName: String = getBatchGroupName( + val accessorObjectName: String = getAccessorObjectName( sourceSetName = sourceSetName, objectName = objectName, index = index ) - createExtensionFileSpecBuilder("$groupName.$sourceSetName") + createExtensionFileSpecBuilder("$accessorObjectName.$sourceSetName") .also { fileSpec -> addExpectExtensionAccessors( fileSpec = fileSpec, @@ -265,7 +274,7 @@ internal class ResourceTypeGenerator( } @Suppress("LongMethod") - private fun createBatchFileSpecs( + private fun createAccessorFileSpecs( parentObjectName: String, objectName: String, resourceSourceSetName: String, @@ -274,26 +283,26 @@ internal class ResourceTypeGenerator( actualModifier: KModifier?, ): List { return resources.chunked(batchSize).mapIndexed { index, batch -> - val groupName: String = getBatchGroupName( + val accessorObjectName: String = getAccessorObjectName( sourceSetName = resourceSourceSetName, objectName = objectName, index = index ) - val batchedResources: List> = buildBatchedResources(batch) + val accessorResources: List> = buildAccessorResources(batch) val fileSpec = createExtensionFileSpecBuilder( - fileName = "$groupName.$targetSourceSetName" + fileName = "$accessorObjectName.$targetSourceSetName" ) - platformResourceGenerator.generateBeforeBatchedFile( + platformResourceGenerator.generateAccessorFilePreamble( builder = fileSpec, metadata = batch, - objectName = groupName + objectName = accessorObjectName ) - val groupObject = TypeSpec.objectBuilder(groupName) + val groupObject = TypeSpec.objectBuilder(accessorObjectName) .addModifiers(KModifier.INTERNAL) .also { builder -> - batchedResources.forEach { resource -> + accessorResources.forEach { resource -> builder.addProperty( PropertySpec.builder(resource.internalName, resourceClass) .addModifiers(KModifier.INTERNAL) @@ -306,8 +315,8 @@ internal class ResourceTypeGenerator( .build() ) } - builder.addReferencedValuesFunction( - propertyReferences = batchedResources.map { it.internalName }, + builder.addAccessorValuesFunction( + propertyReferences = accessorResources.map { it.internalName }, classType = resourceClass, memberModifier = KModifier.INTERNAL ) @@ -316,14 +325,17 @@ internal class ResourceTypeGenerator( fileSpec.addType(groupObject) - batchedResources.forEach { resource -> + accessorResources.forEach { resource -> fileSpec.addFunction( FunSpec.builder(initFunctionName(resource.internalName)) .addModifiers(KModifier.PRIVATE) .returns(resourceClass) .addStatement( "return %L", - platformResourceGenerator.generateBatchedInitializer(resource.metadata) + platformResourceGenerator.generateAccessorInitializer( + metadata = resource.metadata, + accessorObjectName = accessorObjectName + ) ) .build() ) @@ -333,8 +345,8 @@ internal class ResourceTypeGenerator( fileSpec = fileSpec, parentObjectName = parentObjectName, objectName = objectName, - groupName = groupName, - resources = batchedResources, + groupName = accessorObjectName, + resources = accessorResources, actualModifier = actualModifier ) @@ -373,7 +385,7 @@ internal class ResourceTypeGenerator( parentObjectName: String, objectName: String, groupName: String, - resources: List>, + resources: List>, actualModifier: KModifier?, ) { resources.forEach { resource -> @@ -438,10 +450,10 @@ internal class ResourceTypeGenerator( ) } - private fun buildBatchedResources(resources: List): List> { + private fun buildAccessorResources(resources: List): List> { if (!isHierarchyPropertiesStrategy()) { return resources.map { resource -> - BatchedResource( + AccessorResource( metadata = resource, internalName = resource.key ) @@ -462,7 +474,7 @@ internal class ResourceTypeGenerator( "${resource.key}__${duplicateGroup.indexOf(resource)}" } - BatchedResource(metadata = resource, internalName = internalName) + AccessorResource(metadata = resource, internalName = internalName) } } @@ -474,13 +486,13 @@ internal class ResourceTypeGenerator( return it.pathSegments().joinToString(separator = "/") + "/${it.key}" } - private fun getBatchGroupNames( + private fun getAccessorObjectNames( sourceSetName: String, objectName: String, resources: List, ): List { return resources.chunked(batchSize).indices.map { index -> - getBatchGroupName( + getAccessorObjectName( sourceSetName = sourceSetName, objectName = objectName, index = index @@ -488,7 +500,7 @@ internal class ResourceTypeGenerator( } } - private fun getBatchGroupName( + private fun getAccessorObjectName( sourceSetName: String, objectName: String, index: Int, @@ -525,7 +537,7 @@ internal class ResourceTypeGenerator( const val DEFAULT_BATCH_SIZE = 50 } - private data class BatchedResource( + private data class AccessorResource( val metadata: T, val internalName: String, ) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt index 86070be05..e7e9bd4d0 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/factory/StringGeneratorFactory.kt @@ -34,7 +34,7 @@ internal class StringGeneratorFactory( private val kotlinPlatformType: KotlinPlatformType, private val kotlinKonanTarget: () -> KonanTarget, private val androidRClassPackage: () -> String, - private val iosBaseLocalizationRegion: () -> String, + private val iosBaseLocalizationRegion: () -> String ) { fun create(): ResourceTypeGenerator { return ResourceTypeGenerator( diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt index 5d2e44de1..6048e48ae 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.AssetMetadata import java.io.File @@ -30,7 +28,7 @@ internal class AndroidAssetResourceGenerator( ) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier? @@ -38,18 +36,6 @@ internal class AndroidAssetResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier? - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.assetResourceName - ) - } - override fun generateResourceFiles(data: List) { data.forEach { metadata -> metadata.filePath.copyTo(File(assetsGenerationDir, metadata.pathRelativeToBase.path)) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt index 510b50334..fb4a6cb30 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.AssetMetadata import java.io.File @@ -34,7 +33,7 @@ internal class AppleAssetResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: AssetMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: AssetMetadata): CodeBlock { return CodeBlock.of( "AssetResource(originalPath = %S, fileName = %S, extension = %S, bundle = %L)", metadata.pathRelativeToBase.invariantSeparatorsPath, @@ -56,7 +55,7 @@ internal class AppleAssetResourceGenerator( .replace('/', PATH_DELIMITER) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -64,24 +63,12 @@ internal class AppleAssetResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.assetResourceName - ) - } - private companion object { const val PATH_DELIMITER = '+' } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt index bd7b471b5..42823a6d1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.platform.js.JsFilePathMode import dev.icerock.gradle.metadata.resource.AssetMetadata import java.io.File @@ -35,7 +33,7 @@ internal class JsAssetResourceGenerator( ) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -52,18 +50,6 @@ internal class JsAssetResourceGenerator( } } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.assetResourceName - ) - } - private companion object { const val ASSETS_DIR = "assets" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt index 8facec5c1..dc733a8d0 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt @@ -14,7 +14,6 @@ import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.AssetMetadata import java.io.File @@ -32,7 +31,7 @@ internal class JvmAssetResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: AssetMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: AssetMetadata): CodeBlock { return CodeBlock.of( "AssetResource(resourcesClassLoader = %L, originalPath = %S, path = %S)", Jvm.providerClassLoaderReference, @@ -47,7 +46,7 @@ internal class JvmAssetResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -55,24 +54,12 @@ internal class JvmAssetResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.assetResourceName - ) - } - private fun buildAssetPath(metadata: AssetMetadata): String { return File(ASSETS_DIR, metadata.pathRelativeToBase.path).path .replace('\\', '/') diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt index 1d529f2b2..2866c2ddf 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ColorMetadata import java.io.File @@ -27,7 +25,7 @@ internal class AndroidColorResourceGenerator( return CodeBlock.of("ColorResource(R.color.%L)", metadata.key) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -35,18 +33,6 @@ internal class AndroidColorResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.colorResourceName - ) - } - override fun generateResourceFiles(data: List) { val valuesDir = File(resourcesGenerationDir, "values") val defaultStringsFile = File(valuesDir, COLORS_XML_FILE_NAME) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt index 64c6ddf69..7c689b5af 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ColorMetadata import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonObject @@ -37,7 +36,7 @@ internal class AppleColorResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: ColorMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: ColorMetadata): CodeBlock { return CodeBlock.of( "ColorResource(name = %S, bundle = %L)", metadata.key, @@ -99,7 +98,7 @@ internal class AppleColorResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -107,24 +106,12 @@ internal class AppleColorResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.colorResourceName - ) - } - private fun buildAppearancesIdiomJson( valueTag: String, color: ColorMetadata.Color, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt index 2998ef5a0..38f03f605 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt @@ -6,9 +6,7 @@ package dev.icerock.gradle.generator.resources.color import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock -import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -24,35 +22,11 @@ internal class JsColorResourceGenerator : PlatformResourceGenerator) = Unit - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, ) { builder.addEmptyPlatformResourceProperty(modifier) } - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - val languageKeysList: String = metadata.joinToString { it.key } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") - .returns( - ClassName("kotlin.collections", "List") - .parameterizedBy(Constants.colorResourceName) - ) - .build() - - builder.addFunction(valuesFun) - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt index e855902b5..301d879de 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt @@ -11,7 +11,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ColorMetadata internal class JvmColorResourceGenerator : PlatformResourceGenerator { @@ -23,23 +22,11 @@ internal class JvmColorResourceGenerator : PlatformResourceGenerator) = Unit - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, ) { builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.colorResourceName - ) - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt index 2d6272bf1..ff8b3705f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FileMetadata import java.io.File import java.util.Locale @@ -28,7 +26,7 @@ internal class AndroidFileResourceGenerator( return CodeBlock.of("FileResource(R.raw.%L)", keyToResourceId(metadata.key)) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -36,18 +34,6 @@ internal class AndroidFileResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fileResourceName - ) - } - override fun generateResourceFiles(data: List) { val targetDir = File(resourcesGenerationDir, "raw") targetDir.mkdirs() diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt index 72d12c626..a5e391092 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FileMetadata import java.io.File @@ -33,7 +32,7 @@ internal class AppleFileResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: FileMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: FileMetadata): CodeBlock { return CodeBlock.of( "FileResource(fileName = %S, extension = %S, bundle = %L)", metadata.filePath.nameWithoutExtension, @@ -51,7 +50,7 @@ internal class AppleFileResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -59,21 +58,9 @@ internal class AppleFileResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fileResourceName - ) - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt index a98b202ae..300bc7f09 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.platform.js.JsFilePathMode import dev.icerock.gradle.metadata.resource.FileMetadata import java.io.File @@ -40,7 +38,7 @@ internal class JsFileResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -48,18 +46,6 @@ internal class JsFileResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier? - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fileResourceName - ) - } - private companion object { const val FILES_DIR = "files" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt index d658f9923..90b59e633 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt @@ -14,7 +14,6 @@ import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FileMetadata import java.io.File @@ -31,7 +30,7 @@ internal class JvmFileResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: FileMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: FileMetadata): CodeBlock { return CodeBlock.of( "FileResource(resourcesClassLoader = %L, filePath = %S)", Jvm.providerClassLoaderReference, @@ -48,7 +47,7 @@ internal class JvmFileResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -56,24 +55,12 @@ internal class JvmFileResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fileResourceName - ) - } - private companion object { const val FILES_DIR = "files" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt index 9ccc77b3e..057239878 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FontMetadata import java.io.File @@ -27,7 +25,7 @@ internal class AndroidFontResourceGenerator( return CodeBlock.of("FontResource(R.font.%L)", metadata.key) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -45,15 +43,4 @@ internal class AndroidFontResourceGenerator( } } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fontResourceName - ) - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt index 9bedb66d3..c62b338cf 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FontMetadata import java.io.File @@ -32,7 +31,7 @@ internal class AppleFontResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: FontMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: FontMetadata): CodeBlock { return CodeBlock.of( "FontResource(fontName = %S, bundle = %L)", metadata.filePath.name, @@ -46,7 +45,7 @@ internal class AppleFontResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -54,21 +53,9 @@ internal class AppleFontResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fontResourceName - ) - } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt index e377bffa3..d684272a7 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt @@ -8,9 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -63,7 +61,7 @@ internal class JsFontResourceGenerator( cssDeclarationsFile.writeText(declarations) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -71,29 +69,11 @@ internal class JsFontResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( + override fun generateContainerMembers( builder: Builder, metadata: List, modifier: KModifier? ) { - val languageKeysList: String = metadata.joinToString { it.key } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") - .returns( - ClassName("kotlin.collections", "List") - .parameterizedBy(Constants.fontResourceName) - ) - .build() - - builder.addFunction(valuesFun) - val addFontsFun: FunSpec = FunSpec.builder("addFontsToPage") .addCode( filePathMode.format, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt index 3f5b31ac0..cd4f1571a 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt @@ -14,7 +14,6 @@ import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.FontMetadata import java.io.File @@ -31,7 +30,7 @@ internal class JvmFontResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: FontMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: FontMetadata): CodeBlock { return CodeBlock.of( "FontResource(resourcesClassLoader = %L, filePath = %S)", Jvm.providerClassLoaderReference, @@ -48,7 +47,7 @@ internal class JvmFontResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -56,24 +55,12 @@ internal class JvmFontResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.fontResourceName - ) - } - private companion object { const val FONTS_DIR = "fonts" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt index b5418a9fd..6c3e3ead9 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt @@ -9,10 +9,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ImageMetadata import org.slf4j.Logger import java.io.File @@ -35,7 +33,7 @@ internal class AndroidImageResourceGenerator( return CodeBlock.of("ImageResource(R.drawable.%L)", processKey(metadata.key)) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -43,18 +41,6 @@ internal class AndroidImageResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - metadata = metadata, - classType = Constants.imageResourceName, - modifier = modifier - ) - } - override fun generateResourceFiles(data: List) { data.flatMap { imageMetadata -> imageMetadata.values.map { imageMetadata.key to it } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt index 115e1ccee..18b57c696 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ImageMetadata import dev.icerock.gradle.metadata.resource.ImageMetadata.ImageItem import kotlinx.serialization.json.JsonArray @@ -38,7 +37,7 @@ internal class AppleImageResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: ImageMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: ImageMetadata): CodeBlock { return CodeBlock.of( "ImageResource(assetImageName = %S, bundle = %L)", metadata.key, @@ -80,7 +79,7 @@ internal class AppleImageResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -88,24 +87,12 @@ internal class AppleImageResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - metadata = metadata, - classType = Constants.imageResourceName, - modifier = modifier - ) - } - private fun getImagesContent( validItems: List, imageMetadata: ImageMetadata, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt index f07ef5234..ebb76fd26 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt @@ -6,11 +6,8 @@ package dev.icerock.gradle.generator.resources.image import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock -import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -59,7 +56,7 @@ internal class JsImageResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -75,30 +72,6 @@ internal class JsImageResourceGenerator( ) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - val languageKeysList: String = metadata.joinToString { it.key } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") - .returns( - ClassName("kotlin.collections", "List") - .parameterizedBy(Constants.imageResourceName) - ) - .build() - - builder.addFunction(valuesFun) - } - private companion object { const val IMAGES_DIR = "images" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt index 05737e61c..30dc489f7 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt @@ -14,7 +14,6 @@ import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.metadata.resource.ImageMetadata import dev.icerock.gradle.metadata.resource.ImageMetadata.Appearance import java.io.File @@ -51,7 +50,7 @@ internal class JvmImageResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: ImageMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: ImageMetadata): CodeBlock { var fileName: String = "" var darkFileName: String? = null @@ -86,7 +85,7 @@ internal class JvmImageResourceGenerator( ) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -94,24 +93,12 @@ internal class JvmImageResourceGenerator( builder.addJvmPlatformResourceClassLoaderProperty(modifier = modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.imageResourceName - ) - } - private companion object { const val IMAGES_DIR = "images" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt index 1bc5994dc..19c68c6f8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.PluralMetadata import dev.icerock.gradle.utils.convertXmlStringToAndroidLocalization @@ -29,7 +27,7 @@ internal class AndroidPluralResourceGenerator( return CodeBlock.of("PluralsResource(R.plurals.%L)", metadata.key) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -46,18 +44,6 @@ internal class AndroidPluralResourceGenerator( } } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.pluralsResourceName - ) - } - private fun generateLanguageFile( language: LanguageType, strings: Map>, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt index 03549ab5c..3649f6a37 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.PluralMetadata import dev.icerock.gradle.utils.convertXmlStringToApplePluralLocalization @@ -35,7 +34,7 @@ internal class ApplePluralResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: PluralMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: PluralMetadata): CodeBlock { return CodeBlock.of( "PluralsResource(resourceId = %S, bundle = %L)", metadata.key, @@ -52,7 +51,7 @@ internal class ApplePluralResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -60,24 +59,12 @@ internal class ApplePluralResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.pluralsResourceName - ) - } - private fun generateLanguageFile( language: LanguageType, strings: Map>, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt index 97ef2a7dd..08494bc3d 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt @@ -7,14 +7,12 @@ package dev.icerock.gradle.generator.resources.plural import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec -import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addJsBatchedStringsLoaderProperty +import dev.icerock.gradle.generator.addJsAccessorFileStringsLoaderProperty import dev.icerock.gradle.generator.addJsContainerStringsLoaderProperty import dev.icerock.gradle.generator.addJsFallbackProperty import dev.icerock.gradle.generator.addJsSupportedLocalesProperty @@ -53,7 +51,7 @@ internal class JsPluralResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier? @@ -81,7 +79,7 @@ internal class JsPluralResourceGenerator( builder.addJsContainerStringsLoaderProperty() } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, @@ -102,31 +100,7 @@ internal class JsPluralResourceGenerator( }.toList(), filePathMode = filePathMode ) - builder.addJsBatchedStringsLoaderProperty() - } - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier? - ) { - val languageKeysList: String = metadata.joinToString { it.key } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") - .returns( - ClassName("kotlin.collections", "List") - .parameterizedBy(Constants.pluralsResourceName) - ) - .build() - - builder.addFunction(valuesFun) + builder.addJsAccessorFileStringsLoaderProperty() } private fun generateLanguageFile( diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt index c280b2b64..da8846d63 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt @@ -15,7 +15,6 @@ import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceBundleProperty import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.PluralMetadata import dev.icerock.gradle.utils.convertXmlStringToLocalization @@ -36,7 +35,7 @@ internal class JvmPluralResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: PluralMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: PluralMetadata): CodeBlock { return CodeBlock.of( "PluralsResource(resourcesClassLoader = %L, bundleName = %L, key = %S)", Jvm.providerClassLoaderReference, @@ -54,7 +53,7 @@ internal class JvmPluralResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -67,7 +66,7 @@ internal class JvmPluralResourceGenerator( ) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, @@ -78,18 +77,6 @@ internal class JvmPluralResourceGenerator( ) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.pluralsResourceName - ) - } - private fun generateLanguageFile( language: LanguageType, strings: Map>, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt index ee9a1652f..bfd9948d6 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt @@ -8,10 +8,8 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata import dev.icerock.gradle.utils.convertXmlStringToAndroidLocalization @@ -29,7 +27,7 @@ internal class AndroidStringResourceGenerator( return CodeBlock.of("StringResource(R.string.%L)", metadata.key) } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -37,18 +35,6 @@ internal class AndroidStringResourceGenerator( builder.addEmptyPlatformResourceProperty(modifier) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.stringResourceName - ) - } - override fun generateResourceFiles(data: List) { data.processLanguages().forEach { (lang, strings) -> generateLanguageFile( diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt index 15033a5f5..b36fec45f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt @@ -12,7 +12,6 @@ import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata import dev.icerock.gradle.utils.convertXmlStringToLocalization @@ -35,7 +34,7 @@ internal class AppleStringResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: StringMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: StringMetadata): CodeBlock { return CodeBlock.of( "StringResource(resourceId = %S, bundle = %L)", metadata.key, @@ -52,7 +51,7 @@ internal class AppleStringResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -60,24 +59,12 @@ internal class AppleStringResourceGenerator( builder.addAppleContainerBundleInitializerProperty(modifier) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, ) = Unit - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.stringResourceName - ) - } - private fun generateLanguageFile(language: LanguageType, strings: Map) { val resDir = File(resourcesGenerationDir, language.appleResourcesDir) val localizableFile = File(resDir, "Localizable.strings") diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt index 31c187d58..7c8349334 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt @@ -7,14 +7,12 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec -import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.TypeSpec.Builder import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty -import dev.icerock.gradle.generator.addJsBatchedStringsLoaderProperty +import dev.icerock.gradle.generator.addJsAccessorFileStringsLoaderProperty import dev.icerock.gradle.generator.addJsContainerStringsLoaderProperty import dev.icerock.gradle.generator.addJsFallbackProperty import dev.icerock.gradle.generator.addJsSupportedLocalesProperty @@ -53,7 +51,7 @@ internal class JsStringResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier? @@ -81,7 +79,7 @@ internal class JsStringResourceGenerator( builder.addJsContainerStringsLoaderProperty() } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, @@ -102,31 +100,7 @@ internal class JsStringResourceGenerator( }.toList(), filePathMode = filePathMode ) - builder.addJsBatchedStringsLoaderProperty() - } - - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier? - ) { - val languageKeysList: String = metadata.joinToString { it.key } - - val valuesFun: FunSpec = FunSpec.builder("values") - .also { - if (modifier != null) { - it.addModifiers(modifier) - } - } - .addModifiers(KModifier.OVERRIDE) - .addStatement("return listOf($languageKeysList)") - .returns( - ClassName("kotlin.collections", "List") - .parameterizedBy(Constants.stringResourceName) - ) - .build() - - builder.addFunction(valuesFun) + builder.addJsAccessorFileStringsLoaderProperty() } private fun generateLanguageFile(language: LanguageType, strings: Map) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt index dee912da0..267e0d946 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt @@ -9,13 +9,11 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceBundleProperty import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty -import dev.icerock.gradle.generator.addValuesFunction import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata import dev.icerock.gradle.utils.convertXmlStringToLocalization @@ -36,7 +34,7 @@ internal class JvmStringResourceGenerator( ) } - override fun generateBatchedInitializer(metadata: StringMetadata): CodeBlock { + override fun generateAccessorInitializer(metadata: StringMetadata): CodeBlock { return CodeBlock.of( "StringResource(resourcesClassLoader = %L, bundleName = %L, key = %S)", Jvm.providerClassLoaderReference, @@ -54,7 +52,7 @@ internal class JvmStringResourceGenerator( } } - override fun generateBeforeProperties( + override fun generateContainerProperties( builder: Builder, metadata: List, modifier: KModifier?, @@ -67,7 +65,7 @@ internal class JvmStringResourceGenerator( ) } - override fun generateBeforeBatchedFile( + override fun generateAccessorFilePreamble( builder: FileSpec.Builder, metadata: List, objectName: String, @@ -78,18 +76,6 @@ internal class JvmStringResourceGenerator( ) } - override fun generateAfterProperties( - builder: Builder, - metadata: List, - modifier: KModifier?, - ) { - builder.addValuesFunction( - modifier = modifier, - metadata = metadata, - classType = Constants.stringResourceName - ) - } - private fun generateLanguageFile(language: LanguageType, strings: Map) { val fileDirName = "${getBundlePath()}${language.jvmResourcesSuffix}" diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt deleted file mode 100644 index becd35a5a..000000000 --- a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/StringBatchingTest.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2026 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.icerock.gradle.generator - -import com.squareup.kotlinpoet.ClassName -import com.squareup.kotlinpoet.CodeBlock -import com.squareup.kotlinpoet.KModifier -import dev.icerock.gradle.generator.resources.string.AndroidStringResourceGenerator -import dev.icerock.gradle.generator.resources.string.AppleStringResourceGenerator -import dev.icerock.gradle.generator.resources.string.StringResourceGenerator -import dev.icerock.gradle.metadata.container.ResourceType -import dev.icerock.gradle.metadata.resource.StringMetadata -import java.io.File -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class StringBatchingTest { - @Test - fun commonStringsAreGeneratedAsExtensionAccessors() { - val result = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 1), - sourceSetName = COMMON_SOURCE_SET - )!! - - val containerSource = result.typeSpec.toString() - assertFalse(containerSource.contains("val key_000: StringResource"), containerSource) - assertTrue( - result.typeSpec.propertySpecs.any { it.name == "__platformDetails" }, - containerSource - ) - assertTrue( - containerSource.contains("public override val __platformDetails"), - containerSource - ) - assertTrue( - result.typeSpec.funSpecs.any { it.name == "values" }, - containerSource - ) - - assertEquals(expected = 1, actual = result.fileSpecs.size) - assertEquals(expected = "CommonMainStrings0.commonMain", actual = result.fileSpecs.single().name) - - val accessorSource = result.fileSpecs.single().toString() - assertTrue( - accessorSource.contains("public expect val MR.strings.key_000: StringResource"), - accessorSource - ) - assertFalse(accessorSource.contains("CommonMainStrings0"), accessorSource) - } - - @Test - fun commonStringsAreSplitIntoFiftyItemBatches() { - val oneHundredResult = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 100), - sourceSetName = COMMON_SOURCE_SET - )!! - val oneHundredOneResult = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 101), - sourceSetName = COMMON_SOURCE_SET - )!! - val largeResult = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 1_000), - sourceSetName = COMMON_SOURCE_SET - )!! - - assertEquals(expected = 2, actual = oneHundredResult.fileSpecs.size) - assertEquals( - expected = listOf( - "CommonMainStrings0.commonMain", - "CommonMainStrings1.commonMain", - "CommonMainStrings2.commonMain" - ), - actual = oneHundredOneResult.fileSpecs.map { it.name } - ) - assertEquals(expected = 20, actual = largeResult.fileSpecs.size) - assertEquals(expected = "CommonMainStrings0.commonMain", actual = largeResult.fileSpecs.first().name) - assertEquals(expected = "CommonMainStrings19.commonMain", actual = largeResult.fileSpecs.last().name) - } - - @Test - fun androidActualStringsUseInternalBatchesAndAggregatedValues() { - val commonResult = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 101), - sourceSetName = COMMON_SOURCE_SET - )!! - val androidResult = createAndroidGenerator().generateActualObject( - parentObjectName = MR_CLASS_NAME, - objects = listOf(commonResult.metadata), - sourceSetName = ANDROID_SOURCE_SET - )!! - - val containerSource = androidResult.typeSpec.toString() - assertFalse(containerSource.contains("val key_000: StringResource"), containerSource) - assertTrue(containerSource.contains("CommonMainStrings0.values()"), containerSource) - assertTrue(containerSource.contains("CommonMainStrings1.values()"), containerSource) - assertTrue(containerSource.contains("CommonMainStrings2.values()"), containerSource) - - val firstBatchSource = androidResult.fileSpecs - .single { it.name == "CommonMainStrings0.androidMain" } - .toString() - assertTrue( - firstBatchSource.contains("internal object CommonMainStrings0"), - firstBatchSource - ) - assertTrue( - firstBatchSource.contains("internal val key_000: StringResource by"), - firstBatchSource - ) - assertTrue(firstBatchSource.contains("private fun init_key_000(): StringResource"), firstBatchSource) - assertTrue(firstBatchSource.contains("StringResource(R.string.key_000)"), firstBatchSource) - assertTrue( - firstBatchSource.contains("public actual val MR.strings.key_000: StringResource"), - firstBatchSource - ) - - val secondBatchSource = androidResult.fileSpecs - .single { it.name == "CommonMainStrings2.androidMain" } - .toString() - assertTrue(secondBatchSource.contains("StringResource(R.string.key_100)"), secondBatchSource) - } - - @Test - fun appleActualStringsUseSharedPlatformDetailsProvider() { - val commonResult = createCommonGenerator().generateExpectObject( - parentObjectName = MR_CLASS_NAME, - resources = createStrings(count = 1), - sourceSetName = COMMON_SOURCE_SET - )!! - val appleResult = createAppleGenerator().generateActualObject( - parentObjectName = MR_CLASS_NAME, - objects = listOf(commonResult.metadata), - sourceSetName = IOS_SOURCE_SET - )!! - - val containerSource = appleResult.typeSpec.toString() - assertTrue(containerSource.contains("public actual override val __platformDetails"), containerSource) - assertTrue(containerSource.contains("PlatformDetailsProvider.details"), containerSource) - - val batchSource = appleResult.fileSpecs - .single { it.name == "CommonMainStrings0.iosMain" } - .toString() - assertTrue( - batchSource.contains("internal object CommonMainStrings0"), - batchSource - ) - assertTrue(batchSource.contains("internal val key_000: StringResource by"), batchSource) - assertTrue( - batchSource.contains("resourceId = \"key_000\""), - batchSource - ) - assertTrue( - batchSource.contains("PlatformDetailsProvider.details.nsBundle"), - batchSource - ) - assertFalse(batchSource.contains("private val bundle"), batchSource) - assertFalse(batchSource.contains("private val __platformDetails"), batchSource) - assertTrue(batchSource.contains("public actual val MR.strings.key_000: StringResource"), batchSource) - } - - @Test - fun targetSpecificStringsUseCorrectVisibility() { - val result = createAndroidGenerator().generateObject( - parentObjectName = "MRandroidMain", - resources = createStrings(count = 1), - sourceSetName = ANDROID_SOURCE_SET - )!! - - val batchSource = result.fileSpecs - .single { it.name == "AndroidMainStrings0.androidMain" } - .toString() - - // Batch object should be public (visibilityModifier) - assertTrue(batchSource.contains("internal object AndroidMainStrings0"), batchSource) - // Extension property should be public - assertTrue(batchSource.contains("public val MRandroidMain.strings.key_000: StringResource"), batchSource) - } - - private fun createCommonGenerator(): ResourceTypeGenerator { - return createGenerator(platformResourceGenerator = EmptyStringPlatformResourceGenerator()) - } - - private fun createAndroidGenerator(): ResourceTypeGenerator { - return createGenerator( - platformResourceGenerator = AndroidStringResourceGenerator( - androidRClassPackage = "com.example", - resourcesGenerationDir = File(".") - ) - ) - } - - private fun createAppleGenerator(): ResourceTypeGenerator { - return createGenerator( - platformResourceGenerator = AppleStringResourceGenerator( - baseLocalizationRegion = "en", - resourcesGenerationDir = File(".") - ) - ) - } - - private fun createGenerator( - platformResourceGenerator: PlatformResourceGenerator, - ): ResourceTypeGenerator { - return ResourceTypeGenerator( - propertiesGenerationStrategy = FlatPropertiesGenerationStrategy(), - resourceClass = Constants.stringResourceName, - resourceType = ResourceType.STRINGS, - metadataClass = StringMetadata::class, - visibilityModifier = KModifier.PUBLIC, - generator = StringResourceGenerator(strictLineBreaks = false), - platformResourceGenerator = platformResourceGenerator, - filter = {}, - resourcesPackageName = PACKAGE_NAME - ) - } - - private fun createStrings(count: Int): List { - return (0 until count).map { index -> - val key = "key_${index.toString().padStart(length = 3, padChar = '0')}" - StringMetadata( - key = key, - values = listOf( - StringMetadata.LocaleItem( - locale = "", - value = key - ) - ) - ) - } - } - - private class EmptyStringPlatformResourceGenerator : PlatformResourceGenerator { - override fun imports(): List = emptyList() - override fun generateInitializer(metadata: StringMetadata): CodeBlock = CodeBlock.of("") - override fun generateResourceFiles(data: List) = Unit - } - - private companion object { - const val PACKAGE_NAME = "com.example.generated" - const val MR_CLASS_NAME = "MR" - const val COMMON_SOURCE_SET = "commonMain" - const val ANDROID_SOURCE_SET = "androidMain" - const val IOS_SOURCE_SET = "iosMain" - } -} From a01adac7a77d4c22124fd4350a4a591c0b6e8d2e Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Sun, 14 Jun 2026 23:19:29 +0700 Subject: [PATCH 16/26] reformat --- .../main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt | 2 -- .../dev/icerock/gradle/generator/ResourceTypeGenerator.kt | 2 ++ .../generator/resources/asset/JvmAssetResourceGenerator.kt | 1 - .../gradle/generator/resources/file/JvmFileResourceGenerator.kt | 1 - .../generator/resources/font/AndroidFontResourceGenerator.kt | 1 - .../gradle/generator/resources/font/JvmFontResourceGenerator.kt | 1 - .../generator/resources/image/JvmImageResourceGenerator.kt | 1 - 7 files changed, 2 insertions(+), 7 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt index 8b185ced8..2e20ea85f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/CodeGenerators.kt @@ -18,7 +18,6 @@ import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.platform.js.JsFilePathMode -import dev.icerock.gradle.metadata.resource.ResourceMetadata internal fun TypeSpec.Builder.addContentHashProperty(hash: String) { val bundleProperty: PropertySpec = @@ -84,7 +83,6 @@ internal fun TypeSpec.Builder.addEmptyPlatformResourceProperty( ) } - internal fun TypeSpec.Builder.addValuesFunctionFromAccessors( accessorObjectNames: List, classType: ClassName, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 7edbbfa4c..df5576a63 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -95,6 +95,7 @@ internal class ResourceTypeGenerator( ) } + @Suppress("LongMethod") fun generateActualObject( parentObjectName: String, objects: List, @@ -169,6 +170,7 @@ internal class ResourceTypeGenerator( ) } + @Suppress("LongMethod") fun generateObject( parentObjectName: String, resources: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt index dc733a8d0..3ab80db58 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt @@ -9,7 +9,6 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt index 90b59e633..aa46d3f37 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt @@ -9,7 +9,6 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt index 057239878..79bd2c50c 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt @@ -42,5 +42,4 @@ internal class AndroidFontResourceGenerator( metadata.filePath.copyTo(File(fontResDir, fileName)) } } - } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt index cd4f1571a..e1fc21f70 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt @@ -9,7 +9,6 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt index 30dc489f7..5de6f79d2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt @@ -9,7 +9,6 @@ import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec.Builder -import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator From ce9bc41ede6b8c42aaa5cdeb182875984f341ce7 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 18 Jun 2026 17:28:13 +0700 Subject: [PATCH 17/26] fixed sample resource-gallery commonTest imports --- .../src/commonTest/kotlin/com/icerock/library/AssetsTests.kt | 1 + .../kotlin/com/icerock/library/PluralResourceEnTests.kt | 2 ++ .../kotlin/com/icerock/library/PluralResourceRuTests.kt | 2 ++ .../kotlin/com/icerock/library/StringResourceEnTests.kt | 3 +++ .../kotlin/com/icerock/library/StringResourceRuTests.kt | 3 +++ .../kotlin/com/icerock/library/StringResourceTests.kt | 3 +++ 6 files changed, 14 insertions(+) diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/AssetsTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/AssetsTests.kt index 28fb1178f..f368a9620 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/AssetsTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/AssetsTests.kt @@ -6,6 +6,7 @@ package com.icerock.library import BaseUnitTest import com.icerockdev.library.MR +import com.icerockdev.library.test2_txt import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import readTextContent diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt index 934d5436b..971b63eef 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceEnTests.kt @@ -6,6 +6,8 @@ package com.icerock.library import com.icerockdev.library.MR import com.icerockdev.library.Testing +import com.icerockdev.library.test_plural +import com.icerockdev.library.test_plural_fallback import dev.icerock.moko.resources.desc.desc import kotlin.test.Ignore import kotlin.test.Test diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt index 27c8d15b1..836813075 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/PluralResourceRuTests.kt @@ -6,6 +6,8 @@ package com.icerock.library import com.icerockdev.library.MR import com.icerockdev.library.Testing +import com.icerockdev.library.test_plural +import com.icerockdev.library.test_plural_fallback import dev.icerock.moko.resources.desc.desc import kotlin.test.Ignore import kotlin.test.Test diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt index b6149821e..4d3280e98 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceEnTests.kt @@ -5,6 +5,9 @@ package com.icerock.library import com.icerockdev.library.MR +import com.icerockdev.library.format +import com.icerockdev.library.common_name +import com.icerockdev.library.hello_formatted_string import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.resources.format import kotlin.test.Test diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt index fbda1d678..f7eb668a2 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceRuTests.kt @@ -5,6 +5,9 @@ package com.icerock.library import com.icerockdev.library.MR +import com.icerockdev.library.format +import com.icerockdev.library.common_name +import com.icerockdev.library.hello_formatted_string import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.resources.format import kotlin.test.Test diff --git a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceTests.kt b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceTests.kt index e7bc8055a..b47fe875d 100644 --- a/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceTests.kt +++ b/samples/resources-gallery/mpp-library/src/commonTest/kotlin/com/icerock/library/StringResourceTests.kt @@ -7,6 +7,9 @@ package com.icerock.library import BaseUnitTest import com.icerockdev.library.MR import com.icerockdev.library.Testing +import com.icerockdev.library.format +import com.icerockdev.library.test_dialect +import com.icerockdev.library.test_simple import dev.icerock.moko.resources.desc.StringDesc import dev.icerock.moko.resources.desc.desc import dev.icerock.moko.resources.format From 89aefbffb737ffd751dad42b00c94e6f90927ad7 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Mon, 10 Aug 2026 11:58:02 +0700 Subject: [PATCH 18/26] #870 Add watchosDeviceArm64 target support --- .../multiplatform-library-extended-convention.gradle.kts | 5 ++++- samples/kotlin-ios-app/mpp-library/build.gradle.kts | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/resources-build-logic/src/main/kotlin/multiplatform-library-extended-convention.gradle.kts b/resources-build-logic/src/main/kotlin/multiplatform-library-extended-convention.gradle.kts index 593b56354..553e51dbb 100644 --- a/resources-build-logic/src/main/kotlin/multiplatform-library-extended-convention.gradle.kts +++ b/resources-build-logic/src/main/kotlin/multiplatform-library-extended-convention.gradle.kts @@ -10,6 +10,7 @@ kotlin { watchosX64() watchosArm32() watchosArm64() + watchosDeviceArm64() watchosSimulatorArm64() sourceSets { @@ -27,9 +28,11 @@ kotlin { val watchosArm64Main by getting{ dependsOn(watchosMain) } + val watchosDeviceArm64Main by getting { + dependsOn(watchosMain) + } val watchosSimulatorArm64Main by getting{ dependsOn(watchosMain) } } } - diff --git a/samples/kotlin-ios-app/mpp-library/build.gradle.kts b/samples/kotlin-ios-app/mpp-library/build.gradle.kts index 8e3bb9642..1d59efe83 100644 --- a/samples/kotlin-ios-app/mpp-library/build.gradle.kts +++ b/samples/kotlin-ios-app/mpp-library/build.gradle.kts @@ -16,9 +16,10 @@ kotlin { val watchosX64 = watchosX64() val watchosArm64 = watchosArm64() + val watchosDeviceArm64 = watchosDeviceArm64() val watchosSimulatorArm64 = watchosSimulatorArm64() - configure(listOf(watchosX64, watchosArm64, watchosSimulatorArm64)) { + configure(listOf(watchosX64, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64)) { binaries { framework { baseName = "MppLibrary" From 7c7bd827060d310fca5bbe98faa6b4e2cbcedca7 Mon Sep 17 00:00:00 2001 From: Brian Witt Date: Tue, 7 Jul 2026 20:04:17 -0700 Subject: [PATCH 19/26] ensure deterministic output Signed-off-by: Brian Witt --- .../gradle/generator/ResourceTypeGenerator.kt | 7 +- .../metadata/resource/ResourceMetadata.kt | 4 +- .../GenerateMultiplatformResourcesTask.kt | 9 ++- .../dev/icerock/gradle/utils/calcHash.kt | 3 + .../generator/DeterministicOutputTest.kt | 80 +++++++++++++++++++ 5 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 resources-generator/src/test/kotlin/dev/icerock/gradle/generator/DeterministicOutputTest.kt diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt index 4b50f1a09..d0ffd2bd3 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourceTypeGenerator.kt @@ -14,6 +14,7 @@ import dev.icerock.gradle.metadata.container.ResourceType import dev.icerock.gradle.metadata.resource.ResourceMetadata import dev.icerock.gradle.utils.filterClass import org.gradle.api.tasks.util.PatternFilterable +import java.io.File import kotlin.reflect.KClass @Suppress("LongParameterList", "TooManyFunctions", "UnusedPrivateMember") @@ -28,7 +29,11 @@ internal class ResourceTypeGenerator( private val filter: PatternFilterable.() -> Unit, ) { fun generateMetadata(files: ResourcesFiles): List { - return generator.generateMetadata(files.matching(filter).ownSourceSet.fileTree.files) + // Sort for deterministic output; FileTree.files iteration is filesystem-dependent. + val sortedFiles: Set = files.matching(filter).ownSourceSet.fileTree.files + .sortedBy { it.absolutePath } + .toCollection(LinkedHashSet()) + return generator.generateMetadata(sortedFiles) } fun getImports(): List = platformResourceGenerator.imports() diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt index 06bf63e16..fdc59a890 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/metadata/resource/ResourceMetadata.kt @@ -61,7 +61,7 @@ internal data class StringMetadata( ) @Suppress("MagicNumber") - override fun contentHash(): String = values.hashCode().toString(16) + override fun contentHash(): String = values.toString().hashCode().toString(16) } @Serializable @@ -94,7 +94,7 @@ internal data class PluralMetadata( } @Suppress("MagicNumber") - override fun contentHash(): String = values.hashCode().toString(16) + override fun contentHash(): String = values.toString().hashCode().toString(16) } @Serializable diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt index edbdc11f5..7f5ff2b1a 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/tasks/GenerateMultiplatformResourcesTask.kt @@ -155,9 +155,12 @@ abstract class GenerateMultiplatformResourcesTask : DefaultTask() { ) val serializer: KSerializer> = ListSerializer(ContainerMetadata.serializer()) - val inputMetadata: List = inputMetadataFiles.files.flatMap { file -> - json.decodeFromString(serializer, file.readText()) - } + // Sort for deterministic output. + val inputMetadata: List = inputMetadataFiles.files + .sortedBy { it.absolutePath } + .flatMap { file -> + json.decodeFromString(serializer, file.readText()) + } val outputMetadata: List = if (kotlinPlatformType.isCommon) { generator.generateCommonKotlin(files, inputMetadata) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/calcHash.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/calcHash.kt index 5df62d2a9..b0d2351dc 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/calcHash.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/calcHash.kt @@ -12,8 +12,11 @@ import java.io.InputStream import java.io.SequenceInputStream internal fun File.calculateResourcesHash(): String { + val root: File = this + // Sort for deterministic output; walkTopDown() order is filesystem-dependent. val inputStreams: List = walkTopDown() .filterNot { it.isDirectory } + .sortedBy { it.relativeTo(root).path } .map { it.inputStream() }.toList() val singleInputStream: InputStream = SequenceInputStream(inputStreams.toEnumeration()) diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/DeterministicOutputTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/DeterministicOutputTest.kt new file mode 100644 index 000000000..592acc114 --- /dev/null +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/DeterministicOutputTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2026 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator + +import dev.icerock.gradle.metadata.resource.PluralMetadata +import dev.icerock.gradle.metadata.resource.PluralMetadata.PluralItem +import dev.icerock.gradle.metadata.resource.PluralMetadata.PluralItem.Quantity +import dev.icerock.gradle.metadata.resource.StringMetadata +import dev.icerock.gradle.utils.calculateResourcesHash +import java.io.File +import java.nio.file.Files +import kotlin.test.Test +import kotlin.test.assertEquals + +class DeterministicOutputTest { + + private val plural = PluralMetadata( + key = "apples", + values = listOf( + PluralMetadata.LocaleItem( + locale = "base", + values = listOf( + PluralItem(Quantity.ONE, "one apple"), + PluralItem(Quantity.OTHER, "%d apples"), + ), + ), + PluralMetadata.LocaleItem( + locale = "ru", + values = listOf( + PluralItem(Quantity.ONE, "яблоко"), + PluralItem(Quantity.FEW, "яблока"), + PluralItem(Quantity.MANY, "яблок"), + ), + ), + ), + ) + + private val string = StringMetadata( + key = "hello", + values = listOf( + StringMetadata.LocaleItem(locale = "base", value = "Hello, world"), + StringMetadata.LocaleItem(locale = "ru", value = "Привет, мир"), + ), + ) + + @Test + fun pluralContentHashIsStable() { + assertEquals(expected = "-9167ca0", actual = plural.contentHash()) + } + + @Test + fun stringContentHashIsStable() { + assertEquals(expected = "367b4e74", actual = string.contentHash()) + } + + @Test + fun equivalentMetadataProduceEqualContentHash() { + assertEquals(expected = plural.contentHash(), actual = plural.copy().contentHash()) + } + + @Test + fun directoryHashIgnoresFilesystemOrder() { + val forward = createTree(listOf("a.txt" to "A", "b.txt" to "B", "c.txt" to "C")) + val reverse = createTree(listOf("c.txt" to "C", "b.txt" to "B", "a.txt" to "A")) + try { + assertEquals(expected = forward.calculateResourcesHash(), actual = reverse.calculateResourcesHash()) + } finally { + forward.deleteRecursively() + reverse.deleteRecursively() + } + } + + private fun createTree(entries: List>): File { + val dir = Files.createTempDirectory("moko-hash-test").toFile() + entries.forEach { (name, content) -> File(dir, name).writeText(content) } + return dir + } +} From dd610ba83ee007caa28bf0aaefaf49c49cdd7db5 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Tue, 1 Sep 2026 16:04:18 +0700 Subject: [PATCH 20/26] Fix SVG alpha color handling --- README.md | 2 +- gradle/libs.versions.toml | 4 +- .../resources/image/SvgColorTransformer.kt | 131 ++++++++---------- .../image/SvgColorTransformerTest.kt | 4 +- 4 files changed, 66 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index d11c483be..ad8ced9df 100755 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ should [add `export` declarations](https://kotlinlang.org/docs/multiplatform-bui ``` framework { export("dev.icerock.moko:resources:0.26.4") - export("dev.icerock.moko:graphics:0.10.0") // toUIColor here + export("dev.icerock.moko:graphics:0.10.2") // toUIColor here } ``` diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f00b8ee30..538188616 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,7 +38,7 @@ commonsCodecVersion = "1.15" batikVersion = "1.17" # moko -mokoGraphicsVersion = "0.10.0" +mokoGraphicsVersion = "0.10.2" mokoTestVersion = "0.6.1" mokoMultiplatformPluginVersion = "0.14.2" @@ -81,4 +81,4 @@ composeJetBrainsPlugin = { module = "org.jetbrains.compose:compose-gradle-plugin nexusPublishing = { module = "io.github.gradle-nexus:publish-plugin", version = "2.0.0" } [plugins] -composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinVersion" } \ No newline at end of file +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinVersion" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt index b40f4090e..485f39ef4 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformer.kt @@ -8,10 +8,10 @@ import java.util.Locale @Suppress("MagicNumber") internal object SvgColorTransformer { - private const val HEX_8_LENGTH = 8 - private const val HEX_4_LENGTH = 4 + private const val LONG_HEX_WITH_ALPHA_LENGTH = 8 + private const val SHORT_HEX_WITH_ALPHA_LENGTH = 4 + private const val MAX_ALPHA_CHANNEL_VALUE = 255.0 - @Suppress("LongMethod") fun transform(content: String): String { val attrNamesPattern = ColorAttribute.allNames.joinToString("|") val attrRegex = Regex("""($attrNamesPattern)\s*=\s*(['"])#([0-9a-fA-F]+)\2""") @@ -20,36 +20,9 @@ internal object SvgColorTransformer { val attrName = matchResult.groupValues[1] val quote = matchResult.groupValues[2] val hex = matchResult.groupValues[3] - val colorAttr = ColorAttribute.findByName(attrName) - - when (hex.length) { - HEX_8_LENGTH -> { - val rgb = hex.substring(0, 6) - val alpha = hex.substring(6, 8) - val alphaStr = hexToAlpha(alpha) - val opacityAttr = colorAttr?.opacityAttrName - - if (opacityAttr != null) { - """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" - } else { - """$attrName=$quote#$rgb$quote""" - } - } - HEX_4_LENGTH -> { - val rgbShort = hex.substring(0, 3) - val alpha = hex.substring(3, 4) - val rgb = rgbShort.map { "$it$it" }.joinToString("") - val alphaStr = hexToAlpha("$alpha$alpha") - val opacityAttr = colorAttr?.opacityAttrName - - if (opacityAttr != null) { - """$attrName=$quote#$rgb$quote $opacityAttr=$quote$alphaStr$quote""" - } else { - """$attrName=$quote#$rgb$quote""" - } - } - else -> matchResult.value - } + + val color = parseColorWithAlpha(hex) ?: return@replace matchResult.value + formatXmlAttribute(attrName = attrName, quote = quote, color = color) } val styleAttrRegex = Regex("""style\s*=\s*(['"])([^"']*)\1""") @@ -61,36 +34,9 @@ internal object SvgColorTransformer { val transformedStyle = colorRegex.replace(styleContent) { colorMatch -> val attrName = colorMatch.groupValues[1] val hex = colorMatch.groupValues[2] - val colorAttr = ColorAttribute.findByName(attrName) - - when (hex.length) { - HEX_8_LENGTH -> { - val rgb = hex.substring(0, 6) - val alpha = hex.substring(6, 8) - val alphaStr = hexToAlpha(alpha) - val opacityAttr = colorAttr?.opacityAttrName - - if (opacityAttr != null) { - """$attrName:#$rgb;$opacityAttr:$alphaStr""" - } else { - """$attrName:#$rgb""" - } - } - HEX_4_LENGTH -> { - val rgbShort = hex.substring(0, 3) - val alpha = hex.substring(3, 4) - val rgb = rgbShort.map { "$it$it" }.joinToString("") - val alphaStr = hexToAlpha("$alpha$alpha") - val opacityAttr = colorAttr?.opacityAttrName - - if (opacityAttr != null) { - """$attrName:#$rgb;$opacityAttr:$alphaStr""" - } else { - """$attrName:#$rgb""" - } - } - else -> colorMatch.value - } + + val color = parseColorWithAlpha(hex) ?: return@replace colorMatch.value + formatStyleProperty(attrName = attrName, color = color) } """style=$quote$transformedStyle$quote""" } @@ -98,22 +44,67 @@ internal object SvgColorTransformer { return result } - private fun hexToAlpha(hex: String): String { - val alphaInt = hex.toInt(16) - val alphaFloat = alphaInt / 255.0 + private fun formatXmlAttribute( + attrName: String, + quote: String, + color: SvgColorWithAlpha, + ): String { + val opacityAttrName = ColorAttribute.findByName(attrName).opacityAttrName + + return """$attrName=$quote#${color.rgb}$quote $opacityAttrName=$quote${color.alpha}$quote""" + } + + private fun formatStyleProperty( + attrName: String, + color: SvgColorWithAlpha, + ): String { + val opacityAttrName = ColorAttribute.findByName(attrName).opacityAttrName + + return "$attrName:#${color.rgb};$opacityAttrName:${color.alpha}" + } + + private fun parseColorWithAlpha(hex: String): SvgColorWithAlpha? { + return when (hex.length) { + LONG_HEX_WITH_ALPHA_LENGTH -> { + SvgColorWithAlpha( + rgb = hex.substring(0, 6), + alpha = formatAlpha(hex.substring(6, 8)) + ) + } + + SHORT_HEX_WITH_ALPHA_LENGTH -> { + val rgb = hex.take(3).map { "$it$it" }.joinToString(separator = "") + val alpha = hex.last().let { "$it$it" } + + SvgColorWithAlpha( + rgb = rgb, + alpha = formatAlpha(alpha) + ) + } + + else -> null + } + } + + private fun formatAlpha(hex: String): String { + val alphaFloat = hex.toInt(16) / MAX_ALPHA_CHANNEL_VALUE return "%.2f".format(Locale.US, alphaFloat) } + + private data class SvgColorWithAlpha( + val rgb: String, + val alpha: String, + ) } -private enum class ColorAttribute(val attrName: String, val opacityAttrName: String?) { +private enum class ColorAttribute(val attrName: String, val opacityAttrName: String) { FILL(attrName = "fill", opacityAttrName = "fill-opacity"), STROKE(attrName = "stroke", opacityAttrName = "stroke-opacity"), STOP_COLOR(attrName = "stop-color", opacityAttrName = "stop-opacity"), - FLOOD_COLOR(attrName = "flood-color", opacityAttrName = "flood-opacity"), - COLOR(attrName = "color", opacityAttrName = null); + FLOOD_COLOR(attrName = "flood-color", opacityAttrName = "flood-opacity"); companion object { val allNames: List = entries.map { it.attrName } - fun findByName(name: String): ColorAttribute? = entries.find { it.attrName == name } + fun findByName(name: String): ColorAttribute = entries.first { it.attrName == name } } } diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt index f3fc7c988..5b2630f5d 100644 --- a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/resources/image/SvgColorTransformerTest.kt @@ -24,10 +24,10 @@ class SvgColorTransformerTest { } @Test - fun `test transform color attribute 8-digit`() { + fun `test keep color attribute 8-digit unchanged`() { // color attribute doesn't have a corresponding color-opacity attribute in SVG val input = """""" - val expected = """""" + val expected = input assertEquals(expected, SvgColorTransformer.transform(input)) } From f799be283a249b6476ed3de6a20f386ce1bf545d Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Tue, 1 Sep 2026 21:50:22 +0700 Subject: [PATCH 21/26] fixed moko.graphics version --- gradle/moko.versions.toml | 2 ++ samples/ios-cocoapods-static-framework/shared/build.gradle.kts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/gradle/moko.versions.toml b/gradle/moko.versions.toml index e3ad299dd..b278a38fc 100644 --- a/gradle/moko.versions.toml +++ b/gradle/moko.versions.toml @@ -1,7 +1,9 @@ [versions] +graphicsVersion = "0.10.2" resourcesVersion = "0.27.0" [libraries] +graphics = { module = "dev.icerock.moko:graphics", version.ref = "graphicsVersion" } resources = { module = "dev.icerock.moko:resources", version.ref = "resourcesVersion" } resourcesCompose = { module = "dev.icerock.moko:resources-compose", version.ref = "resourcesVersion" } resourcesTest = { module = "dev.icerock.moko:resources-test", version.ref = "resourcesVersion" } diff --git a/samples/ios-cocoapods-static-framework/shared/build.gradle.kts b/samples/ios-cocoapods-static-framework/shared/build.gradle.kts index c21165d45..a78b2a223 100644 --- a/samples/ios-cocoapods-static-framework/shared/build.gradle.kts +++ b/samples/ios-cocoapods-static-framework/shared/build.gradle.kts @@ -23,7 +23,7 @@ kotlin { isStatic = true export(moko.resources) - export("dev.icerock.moko:graphics:0.10.0") + export(moko.graphics) } } @@ -39,6 +39,7 @@ kotlin { implementation(compose.material) @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) + api(moko.graphics) api(moko.resources) api(moko.resourcesCompose) } From f1825402abf926332825bddf9a199b728b36d8f8 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Wed, 2 Sep 2026 11:42:36 +0700 Subject: [PATCH 22/26] fixed Builder imports --- .../icerock/gradle/generator/PlatformResourceGenerator.kt | 6 +++--- .../dev/icerock/gradle/generator/ResourcesGenerator.kt | 5 ++--- .../resources/asset/AndroidAssetResourceGenerator.kt | 4 ++-- .../resources/asset/AppleAssetResourceGenerator.kt | 4 ++-- .../generator/resources/asset/JsAssetResourceGenerator.kt | 4 ++-- .../generator/resources/asset/JvmAssetResourceGenerator.kt | 4 ++-- .../resources/color/AndroidColorResourceGenerator.kt | 4 ++-- .../resources/color/AppleColorResourceGenerator.kt | 4 ++-- .../generator/resources/color/JsColorResourceGenerator.kt | 4 ++-- .../generator/resources/color/JvmColorResourceGenerator.kt | 4 ++-- .../resources/file/AndroidFileResourceGenerator.kt | 4 ++-- .../generator/resources/file/AppleFileResourceGenerator.kt | 4 ++-- .../generator/resources/file/JsFileResourceGenerator.kt | 4 ++-- .../generator/resources/file/JvmFileResourceGenerator.kt | 4 ++-- .../resources/font/AndroidFontResourceGenerator.kt | 4 ++-- .../generator/resources/font/AppleFontResourceGenerator.kt | 4 ++-- .../generator/resources/font/JsFontResourceGenerator.kt | 6 +++--- .../generator/resources/font/JvmFontResourceGenerator.kt | 4 ++-- .../resources/image/AndroidImageResourceGenerator.kt | 4 ++-- .../resources/image/AppleImageResourceGenerator.kt | 4 ++-- .../generator/resources/image/JsImageResourceGenerator.kt | 4 ++-- .../generator/resources/image/JvmImageResourceGenerator.kt | 4 ++-- .../resources/plural/AndroidPluralResourceGenerator.kt | 4 ++-- .../resources/plural/ApplePluralResourceGenerator.kt | 4 ++-- .../generator/resources/plural/JsPluralResourceGenerator.kt | 4 ++-- .../resources/plural/JvmPluralResourceGenerator.kt | 4 ++-- .../resources/string/AndroidStringResourceGenerator.kt | 4 ++-- .../resources/string/AppleStringResourceGenerator.kt | 4 ++-- .../generator/resources/string/JsStringResourceGenerator.kt | 4 ++-- .../resources/string/JvmStringResourceGenerator.kt | 4 ++-- 30 files changed, 62 insertions(+), 63 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt index 5708f9ccb..63ec91c02 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/PlatformResourceGenerator.kt @@ -8,20 +8,20 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.metadata.resource.ResourceMetadata internal interface PlatformResourceGenerator { fun imports(): List fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? = null, ) = Unit fun generateContainerMembers( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? = null, ) = Unit diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt index f360b2245..ed1be332d 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ResourcesGenerator.kt @@ -5,7 +5,6 @@ package dev.icerock.gradle.generator import com.squareup.kotlinpoet.FileSpec -import com.squareup.kotlinpoet.FileSpec.Builder import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.metadata.container.ContainerMetadata @@ -121,7 +120,7 @@ internal class ResourcesGenerator( ownMetadata: List, parentObjectName: String, outputMetadata: MutableList, - fileSpec: Builder, + fileSpec: FileSpec.Builder, inputMetadata: List, additionalFileSpecs: MutableList, ) { @@ -218,7 +217,7 @@ internal class ResourcesGenerator( private fun finalizeObjectSpec( objectName: String, - fileSpec: Builder, + fileSpec: FileSpec.Builder, objectSpec: TypeSpec.Builder, generatedObjects: List, inputMetadata: List, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt index 6048e48ae..5fcb8c8f5 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AndroidAssetResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.asset import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.metadata.resource.AssetMetadata @@ -29,7 +29,7 @@ internal class AndroidAssetResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt index fb4a6cb30..c082654d9 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/AppleAssetResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -56,7 +56,7 @@ internal class AppleAssetResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt index 42823a6d1..002bd1ce2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JsAssetResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.asset import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -34,7 +34,7 @@ internal class JsAssetResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt index 3ab80db58..276913b0a 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/asset/JvmAssetResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -46,7 +46,7 @@ internal class JvmAssetResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt index 2866c2ddf..96d16c7d8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AndroidColorResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.color import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.metadata.resource.ColorMetadata @@ -26,7 +26,7 @@ internal class AndroidColorResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt index 7c689b5af..539c79a53 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/AppleColorResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -99,7 +99,7 @@ internal class AppleColorResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt index 38f03f605..f6b86df69 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JsColorResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.color import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty @@ -23,7 +23,7 @@ internal class JsColorResourceGenerator : PlatformResourceGenerator) = Unit override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt index 301d879de..760b062c5 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/color/JvmColorResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.color import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addJvmPlatformResourceClassLoaderProperty @@ -23,7 +23,7 @@ internal class JvmColorResourceGenerator : PlatformResourceGenerator) = Unit override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt index ff8b3705f..ce4926bc4 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AndroidFileResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.file import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.metadata.resource.FileMetadata @@ -27,7 +27,7 @@ internal class AndroidFileResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt index a5e391092..5a4326091 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/AppleFileResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -51,7 +51,7 @@ internal class AppleFileResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt index 300bc7f09..58ec44f19 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JsFileResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.file import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -39,7 +39,7 @@ internal class JsFileResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt index aa46d3f37..ea5cfafad 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/file/JvmFileResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -47,7 +47,7 @@ internal class JvmFileResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt index 79bd2c50c..13014304e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AndroidFontResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.font import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.metadata.resource.FontMetadata @@ -26,7 +26,7 @@ internal class AndroidFontResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt index c62b338cf..3e147755c 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/AppleFontResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -46,7 +46,7 @@ internal class AppleFontResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt index d684272a7..0e1e01df2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JsFontResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -62,7 +62,7 @@ internal class JsFontResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { @@ -70,7 +70,7 @@ internal class JsFontResourceGenerator( } override fun generateContainerMembers( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt index e1fc21f70..33ec4772f 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/font/JvmFontResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -47,7 +47,7 @@ internal class JvmFontResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt index 6c3e3ead9..06a8d750e 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AndroidImageResourceGenerator.kt @@ -8,7 +8,7 @@ import com.android.ide.common.vectordrawable.Svg2Vector import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.metadata.resource.ImageMetadata @@ -34,7 +34,7 @@ internal class AndroidImageResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt index 18b57c696..a77bf8dc7 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/AppleImageResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -80,7 +80,7 @@ internal class AppleImageResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt index ebb76fd26..f3c776cb2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JsImageResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.image import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.platform.js.JsFilePathMode @@ -57,7 +57,7 @@ internal class JsImageResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt index 5de6f79d2..a2178ef73 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/image/JvmImageResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -85,7 +85,7 @@ internal class JvmImageResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt index 19c68c6f8..a703e4fa8 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/AndroidPluralResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.plural import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.localization.LanguageType @@ -28,7 +28,7 @@ internal class AndroidPluralResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt index 3649f6a37..0351a9166 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/ApplePluralResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -52,7 +52,7 @@ internal class ApplePluralResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt index 08494bc3d..48c33a5c2 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JsPluralResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty @@ -52,7 +52,7 @@ internal class JsPluralResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt index da8846d63..0c68c9229 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/JvmPluralResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails @@ -54,7 +54,7 @@ internal class JvmPluralResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt index bfd9948d6..8bfe51296 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AndroidStringResourceGenerator.kt @@ -7,7 +7,7 @@ package dev.icerock.gradle.generator.resources.string import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty import dev.icerock.gradle.generator.localization.LanguageType @@ -28,7 +28,7 @@ internal class AndroidStringResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt index b36fec45f..5b5301e57 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/AppleStringResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addAppleContainerBundleInitializerProperty @@ -52,7 +52,7 @@ internal class AppleStringResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt index 7c8349334..fddb61092 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JsStringResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants import dev.icerock.gradle.generator.PlatformResourceGenerator import dev.icerock.gradle.generator.addEmptyPlatformResourceProperty @@ -52,7 +52,7 @@ internal class JsStringResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier? ) { diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt index 267e0d946..6df397cb1 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/JvmStringResourceGenerator.kt @@ -8,7 +8,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeSpec.Builder +import com.squareup.kotlinpoet.TypeSpec import dev.icerock.gradle.generator.Constants.Jvm import dev.icerock.gradle.generator.Constants.PlatformDetails import dev.icerock.gradle.generator.PlatformResourceGenerator @@ -53,7 +53,7 @@ internal class JvmStringResourceGenerator( } override fun generateContainerProperties( - builder: Builder, + builder: TypeSpec.Builder, metadata: List, modifier: KModifier?, ) { From 3d10bd0614c84fff8627adabcc312e2c0a7813e0 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Wed, 2 Sep 2026 11:57:08 +0700 Subject: [PATCH 23/26] #758 register generated Android resources for Paparazzi --- .../android/AddAndroidGeneratedSources.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt index f6639b9f3..ffa3d9202 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/platform/android/AddAndroidGeneratedSources.kt @@ -9,11 +9,11 @@ import dev.icerock.gradle.tasks.GenerateMultiplatformResourcesTask import org.gradle.api.tasks.TaskProvider /** - * Registers generated Kotlin sources and assets for Android variants when using the + * Registers generated Kotlin sources, resources and assets for Android variants when using the * classic AGP plugin (`com.android.library`). * - * The generated resource directory (`res`) is not attached here; it is added later during - * source set configuration, as required by the legacy AGP source set wiring model. + * Resources are also registered through the legacy source set API for IDE indexing. Registering + * them here exposes the task-backed generated directory to variant consumers such as Paparazzi. * * Use this function only with the traditional Android plugin. */ @@ -25,13 +25,10 @@ internal fun Sources.addLegacyAndroidGeneratedSources( wiredWith = GenerateMultiplatformResourcesTask::outputSourcesDir ) - // Resources doesn't add in android variants for IDE indexing - // Resource directory set here: - // dev.icerock.gradle.MultiplatformResourcesPlugin.setupSourceSets - // res?.addGeneratedSourceDirectory( - // taskProvider = provider, - // wiredWith = GenerateMultiplatformResourcesTask::outputResourcesDir - // ) + res?.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = GenerateMultiplatformResourcesTask::outputResourcesDir + ) // Assets add here, for correct compilation assets?.addGeneratedSourceDirectory( From a26a364383386b86038991cf85aaf06cbe55be41 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Wed, 2 Sep 2026 12:12:58 +0700 Subject: [PATCH 24/26] added info about default resource catalog in README --- README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d11c483be..270b762c2 100755 --- a/README.md +++ b/README.md @@ -98,6 +98,37 @@ multiplatformResources { } ``` +#### Default resource source sets + +By default, resources for each Kotlin source set must be placed in +`src//moko-resources`. No additional `resourcesSourceSets` configuration is required. +For example, common resources belong in `src/commonMain/moko-resources`, Android-only resources in +`src/androidMain/moko-resources`, and common test resources in `src/commonTest/moko-resources`. + +The default common resource directory has the following structure: + +``` +projectDirectory +└── src + └── commonMain + └── moko-resources + ├── base + │ ├── strings.xml + │ └── plurals.xml + ├── + │ ├── strings.xml + │ └── plurals.xml + ├── images + ├── fonts + ├── files + └── assets +``` + +This directory layout was introduced in moko-resources 0.24.0. When upgrading from 0.23.x, move +resources from `src/commonMain/resources/MR` to `src/commonMain/moko-resources`; the directory +structure inside the resource root remains unchanged. See the +[0.24.0 changelog and migration guide](https://github.com/icerockdev/moko-resources/discussions/730). + #### Custom resource sourceSet If you need custom path for source of resources, you need add in plugin configuration resourcesSourceSets option: @@ -121,7 +152,7 @@ On next step, you must create inside of project directory folder with name: `cus -- customResources --- assets --- base ---- image +--- images ``` Example of custom sourceSet in: `resources-gallery` sample, inside `jvm-app` From 626915759ac8cc7dd770a05fa983c60f25bc7ea5 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Wed, 2 Sep 2026 16:43:41 +0700 Subject: [PATCH 25/26] #885 fix usage of LocalSystemTheme on compose 1.12+ --- .../dev/icerock/moko/resources/compose/ImageResource.kt | 7 ++----- .../dev/icerock/moko/resources/compose/ImageResource.kt | 8 ++++---- .../dev/icerock/moko/resources/compose/ImageResource.kt | 7 ++----- .../dev/icerock/moko/resources/compose/ImageResource.kt | 8 ++++---- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/resources-compose/src/commonJsMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt b/resources-compose/src/commonJsMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt index df90ce28b..074a505c2 100644 --- a/resources-compose/src/commonJsMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt +++ b/resources-compose/src/commonJsMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt @@ -4,12 +4,10 @@ package dev.icerock.moko.resources.compose +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.InternalComposeUiApi -import androidx.compose.ui.LocalSystemTheme -import androidx.compose.ui.SystemTheme import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.painter.BitmapPainter @@ -25,10 +23,9 @@ import org.jetbrains.skia.Data import org.jetbrains.skia.Image import org.jetbrains.skia.svg.SVGDOM -@OptIn(InternalComposeUiApi::class) @Composable actual fun painterResource(imageResource: ImageResource): Painter { - val fileUrl: String = if (LocalSystemTheme.current == SystemTheme.Dark) { + val fileUrl: String = if (isSystemInDarkTheme()) { imageResource.darkFileUrl ?: imageResource.fileUrl } else { imageResource.fileUrl diff --git a/resources-compose/src/iosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt b/resources-compose/src/iosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt index da8b3ae98..588db0d39 100644 --- a/resources-compose/src/iosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt +++ b/resources-compose/src/iosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt @@ -4,10 +4,9 @@ package dev.icerock.moko.resources.compose +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.compose.ui.InternalComposeUiApi -import androidx.compose.ui.LocalSystemTheme import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.toComposeImageBitmap @@ -18,10 +17,11 @@ import org.jetbrains.skia.Image import platform.CoreGraphics.CGImageRef import platform.UIKit.UIImage -@OptIn(ExperimentalForeignApi::class, InternalComposeUiApi::class) +@OptIn(ExperimentalForeignApi::class) @Composable actual fun painterResource(imageResource: ImageResource): Painter { - return remember(LocalSystemTheme.current, imageResource) { + val isDarkTheme: Boolean = isSystemInDarkTheme() + return remember(isDarkTheme, imageResource) { val uiImage: UIImage = imageResource.toUIImage() ?: throw IllegalArgumentException("can't read UIImage of $imageResource") diff --git a/resources-compose/src/jvmMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt b/resources-compose/src/jvmMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt index c55b420cb..740344d96 100644 --- a/resources-compose/src/jvmMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt +++ b/resources-compose/src/jvmMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt @@ -4,18 +4,15 @@ package dev.icerock.moko.resources.compose +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.InternalComposeUiApi -import androidx.compose.ui.LocalSystemTheme -import androidx.compose.ui.SystemTheme import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import dev.icerock.moko.resources.ImageResource -@OptIn(InternalComposeUiApi::class) @Composable actual fun painterResource(imageResource: ImageResource): Painter { - val filePath: String = if (LocalSystemTheme.current == SystemTheme.Dark) { + val filePath: String = if (isSystemInDarkTheme()) { imageResource.darkFilePath ?: imageResource.filePath } else { imageResource.filePath diff --git a/resources-compose/src/macosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt b/resources-compose/src/macosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt index 7e1d0efd2..bb62cf637 100644 --- a/resources-compose/src/macosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt +++ b/resources-compose/src/macosMain/kotlin/dev/icerock/moko/resources/compose/ImageResource.kt @@ -4,10 +4,9 @@ package dev.icerock.moko.resources.compose +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.compose.ui.InternalComposeUiApi -import androidx.compose.ui.LocalSystemTheme import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.toComposeImageBitmap @@ -19,10 +18,11 @@ import platform.AppKit.NSImage import platform.CoreGraphics.CGImageRef import platform.CoreGraphics.CGImageRelease -@OptIn(ExperimentalForeignApi::class, InternalComposeUiApi::class) +@OptIn(ExperimentalForeignApi::class) @Composable actual fun painterResource(imageResource: ImageResource): Painter { - return remember(LocalSystemTheme.current, imageResource) { + val isDarkTheme: Boolean = isSystemInDarkTheme() + return remember(isDarkTheme, imageResource) { val nsImage: NSImage = imageResource.toNSImage() ?: throw IllegalArgumentException("can't read NSImage of $imageResource") From 248c170dc70cd6997c7ed07d0629734eb90b2ae6 Mon Sep 17 00:00:00 2001 From: Kolchurin Konstantin Date: Thu, 3 Sep 2026 15:41:22 +0700 Subject: [PATCH 26/26] added paparazzi test case --- .../build.gradle.kts | 1 + .../compose-resources-gallery/local-check.sh | 3 +-- .../shared/build.gradle.kts | 1 + .../common/MokoResourcesPaparazziTest.kt | 25 ++++++++++++++++++ ...zziTest_rendersGeneratedStringResource.png | Bin 0 -> 6346 bytes 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 samples/compose-resources-gallery/shared/src/androidUnitTest/kotlin/com/myapplication/common/MokoResourcesPaparazziTest.kt create mode 100644 samples/compose-resources-gallery/shared/src/test/snapshots/images/com.myapplication.common_MokoResourcesPaparazziTest_rendersGeneratedStringResource.png diff --git a/samples/compose-resources-gallery/build.gradle.kts b/samples/compose-resources-gallery/build.gradle.kts index 8a93d4641..f90798c8e 100644 --- a/samples/compose-resources-gallery/build.gradle.kts +++ b/samples/compose-resources-gallery/build.gradle.kts @@ -6,6 +6,7 @@ plugins { kotlin("android") apply false id("com.android.application") apply false id("com.android.library") apply false + id("app.cash.paparazzi") version "1.3.5" apply false id("org.jetbrains.compose") apply false } diff --git a/samples/compose-resources-gallery/local-check.sh b/samples/compose-resources-gallery/local-check.sh index 7c3a3412f..033b40ec4 100755 --- a/samples/compose-resources-gallery/local-check.sh +++ b/samples/compose-resources-gallery/local-check.sh @@ -8,7 +8,7 @@ log() { echo "\033[0;32m> $1\033[0m" } -./gradlew clean assembleDebug +./gradlew clean assembleDebug verifyPaparazziDebug log "compose-resources-gallery android success" ./gradlew clean jvmJar @@ -39,4 +39,3 @@ else ) log "compose-resources-gallery ios xcode success" fi - diff --git a/samples/compose-resources-gallery/shared/build.gradle.kts b/samples/compose-resources-gallery/shared/build.gradle.kts index 80275c6bd..0bea65ac7 100644 --- a/samples/compose-resources-gallery/shared/build.gradle.kts +++ b/samples/compose-resources-gallery/shared/build.gradle.kts @@ -7,6 +7,7 @@ plugins { kotlin("multiplatform") kotlin("native.cocoapods") id("com.android.library") + id("app.cash.paparazzi") id("org.jetbrains.compose") id("org.jetbrains.kotlin.plugin.compose") id("dev.icerock.mobile.multiplatform-resources") diff --git a/samples/compose-resources-gallery/shared/src/androidUnitTest/kotlin/com/myapplication/common/MokoResourcesPaparazziTest.kt b/samples/compose-resources-gallery/shared/src/androidUnitTest/kotlin/com/myapplication/common/MokoResourcesPaparazziTest.kt new file mode 100644 index 000000000..3a293fdb0 --- /dev/null +++ b/samples/compose-resources-gallery/shared/src/androidUnitTest/kotlin/com/myapplication/common/MokoResourcesPaparazziTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2026 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package com.myapplication.common + +import androidx.compose.material.Text +import app.cash.paparazzi.Paparazzi +import com.icerockdev.library.MR +import com.icerockdev.library.hello_world +import dev.icerock.moko.resources.compose.stringResource +import org.junit.Rule +import org.junit.Test + +class MokoResourcesPaparazziTest { + @get:Rule + val paparazzi = Paparazzi() + + @Test + fun rendersGeneratedStringResource() { + paparazzi.snapshot { + Text(text = stringResource(MR.strings.hello_world)) + } + } +} diff --git a/samples/compose-resources-gallery/shared/src/test/snapshots/images/com.myapplication.common_MokoResourcesPaparazziTest_rendersGeneratedStringResource.png b/samples/compose-resources-gallery/shared/src/test/snapshots/images/com.myapplication.common_MokoResourcesPaparazziTest_rendersGeneratedStringResource.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c3b600af5fca8e0e02d434e6814bcc9b61a3a3 GIT binary patch literal 6346 zcmeHMeOQv`8pkY~<;Pm<7>1g&RhFp-KT1U~`(T#SbzEARQj3qw&`1qI!JISKhoHGK zGIh(6m0y)9r2>_uGm z{k!kydQW~405@G=xc~qFnEHLT`5yql954W2*!zLe^pl6yA723gmS*~G-uPwwbA?cL zbQye3>JAUt3K?icXp2V21~DA3mtGeN7W?cDUq>QeI{UdvvY$`V1>kY*vJK-}WU{3L$9f_KklG5F+Z z1bM9IW$M5{Y=X5nF*ZgiV&-Ir6Z@QCNiR|@9AWIpwWE5inC-w@FHSs=rpr$A&GRCd zVTF@zfiSEnZ@EaPU!|^F7QI)~R<50D4?%<#PK~q$Vi8?QHelG~sHA60-?@-*e(vat z+O+IG5m|?|wL{){FyAKe2;ZDF?O2bZj6FF%NIok=M+H9l00@|VKMF_bFtB)8F8(}2 zHkKh!irH+4WtJc>X>yG2p5$xvA=q~-=Y~B!{gzG5cz@AUTxfn$rtCgwv0m7@5(&sV z%IRjYCdcJD^UbXtoaWYGITJ5y&9im-!D?k`RlxGLnXpmKAIm&bK%&51#f}?VxOQz; zLcGkrvC1tl!8U8`RJ)R*qD7PnZ;a(SZaVL+qQ$YR-0i5D^`2E4do5obgU+k#V{~8` z-2R&hg3)T#h|s7AOG7najgt!q`bnMAsZA;_&|hmC#A@4>C>zA1&jP)A4*E~#GJ>em z!&_=;3UC<%Qg=s0@m*#(=LP}OVC8N@)sGEsRvIJxrF_3&C8I?q#|CRu@O-sv@0`x5!ddOI4F<4+nr>i5$L6vluaZ zc9(79VD-hc(bJ)+{-Pmiss}?&R(&Pzjn@kCfocA9ZX(Khm~x9svyeI@ggaNe!$m^Ws3L2@S6dH!(x_!@Q=VQ|rvT!um3-HgWz_lm-z z9=E3K6XI{GGQVz--6)ZmC2ZL6P=j6k-W4;+#8j1D(C+0=90Y|F>L^EbLl@UhyoMqWUl=klba zl2EAd(hbFK)n*n8O6si+DE)lV(Ef~lqN=h|!Nbim*rK!gD5zB%VcS4+W4ql_)oqO9 z!!YK4js~ceJUrHslu{&5BC}jq9=(DiUz#{NNk??HKd1w2oCsksJ#X^cSV|O#=!9F>T`1Jc1=X6cPUCl8@0+Uk`Znag2 z&Emm*o~3Pq6aLbOJl00$p3K2i+1;=m4np= zXOpiQIQM($hb(E#jl>FOFg(?=fDb$R@hZ4^C5wxMp1pah0_V)ca*CmKmwGO0i`IG1 z%Q8r;uqF!q3Rdg3X9T`ezAdDtihDx5LA7@nZt^2d^l zzH6@ed*%#|xPkS%51_Z3_vM??SjV|(6(P!P+R|lXUYn#%@N3JAbLo>UiOmfii?U0S z3+YzGL(2_=K8b!>FfYN@#hT9-gsULvd)vNK?aTb zFzzlz^MVjMSdy}odK(#DepvFTj8GE^-6OVhG){JGOeB4N`Eui>B$?uwx<;Mr+S*1o zEo1`rruu7tDADhDRsZ9Dr(G;WBI&nH{g%gv@Dx_4Bm$JlKV1}l31WT$I58a0q^zX7 z2eZA*o|jt-J;#snm>GT81UOmKebeO#zN_(Qx-B8rD)2zBAC*%aV6S-~bZKn03rr9U zA7pPkOto-Fs7T=5Nlf%X=#mb7u}*d!HD$3h9TyFs9h!GY#tmnYC3~Y1Tq)%+q$I=RBAw-B14C7KTD5PCgM_0?)vox3}YI!J~%&7UIFzry0chp=R)qccOnx0 ze#T#X|1um{I%Z9?Hh7FBoDoHrl|S>kJ?ZL;2CV?!P?s&iILm#UZ8koyDlIf@9Yr0I z!0)*D#1axR)%^RztC3)KI@jb1=@JOnE71y$cy-}{o>;17cO~wKa{V)RvL~qkNn!jQ zP>&j{Z!R;Y;qD$~exY2e+flF&^1PiY#*h~aa><=_s)_&)W;UVswmw+I4Ej3M=Bf=( z6?`}ftHOC>ge`LHWXlhNZ~UDgQN_m)TJLEVETj#&-itRt%}*K1n5YmB2sS3N#B*y~ z?a$K}fmJ@PSR7n%)N%God##)as4OzFCx z`dnd^+<41Vt*h-H z@?ZpWN(5rd&uR;*LQ>0A^iVF@|{k;;>GI} zyp@R$!NGIhrps))enXepbp7#k|MyP*nl8WKKLDYzNm(rT)ByWq{JN4szX};0V*Uk6WvHlZf^nKU-)Ai$>tbgA%XD7+ouKU(N z`N#F+kLu4m@c)wu=Y46uFU@~*4I5prGk0itT8nZTzdHSo0^qkLU~{SOzOVlUB#8>+ literal 0 HcmV?d00001