Skip to content

Commit 15b42b3

Browse files
terrakokOmico
authored andcommitted
Gradle Plugin DSL to change the generated Res class name (#5296)
Gradle Plugin DSL to change the generated Res class name: ```kotlin compose.resources { nameOfResClass = "MyRes" } ``` Fixes [CMP-7341](https://youtrack.jetbrains.com/issue/CMP-7341) Support generating custom resource class name ## Testing Integration tests. ## Release Notes ### Features - Resources - Gradle Plugin DSL to change the generated Res class name Co-authored-by: Omico <[email protected]> (cherry picked from commit 3c531dd)
1 parent e6b29f8 commit 15b42b3

File tree

17 files changed

+115
-57
lines changed

17 files changed

+115
-57
lines changed

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ComposeResourcesGeneration.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ internal fun Project.configureComposeResourcesGeneration(
4444
}
4545
}
4646
val packageName = config.getResourcePackage(project)
47+
val resClassName = config.map { it.nameOfResClass }
4748
val makeAccessorsPublic = config.map { it.publicResClass }
4849
val packagingDir = config.getModuleResourcesDir(project)
4950

@@ -53,6 +54,7 @@ internal fun Project.configureComposeResourcesGeneration(
5354
sourceSet,
5455
shouldGenerateCode,
5556
packageName,
57+
resClassName,
5658
makeAccessorsPublic,
5759
packagingDir,
5860
generateModulePath
@@ -67,13 +69,20 @@ internal fun Project.configureComposeResourcesGeneration(
6769
preparedResources,
6870
shouldGenerateCode,
6971
packageName,
72+
resClassName,
7073
makeAccessorsPublic,
7174
packagingDir,
7275
generateModulePath
7376
)
7477
}
7578

76-
configureResourceCollectorsGeneration(kotlinExtension, shouldGenerateCode, packageName, makeAccessorsPublic)
79+
configureResourceCollectorsGeneration(
80+
kotlinExtension,
81+
shouldGenerateCode,
82+
packageName,
83+
resClassName,
84+
makeAccessorsPublic
85+
)
7786

7887
//setup task execution during IDE import
7988
tasks.configureEach { importTask ->
@@ -87,6 +96,7 @@ private fun Project.configureResClassGeneration(
8796
resClassSourceSet: KotlinSourceSet,
8897
shouldGenerateCode: Provider<Boolean>,
8998
packageName: Provider<String>,
99+
resClassName: Provider<String>,
90100
makeAccessorsPublic: Provider<Boolean>,
91101
packagingDir: Provider<File>,
92102
generateModulePath: Boolean
@@ -98,6 +108,7 @@ private fun Project.configureResClassGeneration(
98108
GenerateResClassTask::class.java
99109
) { task ->
100110
task.packageName.set(packageName)
111+
task.resClassName.set(resClassName)
101112
task.makeAccessorsPublic.set(makeAccessorsPublic)
102113
task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/commonResClass"))
103114

@@ -120,6 +131,7 @@ private fun Project.configureResourceAccessorsGeneration(
120131
resourcesDir: Provider<File>,
121132
shouldGenerateCode: Provider<Boolean>,
122133
packageName: Provider<String>,
134+
resClassName: Provider<String>,
123135
makeAccessorsPublic: Provider<Boolean>,
124136
packagingDir: Provider<File>,
125137
generateModulePath: Boolean
@@ -131,6 +143,7 @@ private fun Project.configureResourceAccessorsGeneration(
131143
GenerateResourceAccessorsTask::class.java
132144
) { task ->
133145
task.packageName.set(packageName)
146+
task.resClassName.set(resClassName)
134147
task.sourceSetName.set(sourceSet.name)
135148
task.makeAccessorsPublic.set(makeAccessorsPublic)
136149
task.resDir.set(resourcesDir)
@@ -159,6 +172,7 @@ private fun Project.configureResourceCollectorsGeneration(
159172
kotlinExtension: KotlinProjectExtension,
160173
shouldGenerateCode: Provider<Boolean>,
161174
packageName: Provider<String>,
175+
resClassName: Provider<String>,
162176
makeAccessorsPublic: Provider<Boolean>
163177
) {
164178
if (kotlinExtension is KotlinMultiplatformExtension) {
@@ -169,6 +183,7 @@ private fun Project.configureResourceCollectorsGeneration(
169183
commonMainSourceSet,
170184
shouldGenerateCode,
171185
packageName,
186+
resClassName,
172187
makeAccessorsPublic
173188
)
174189
}
@@ -180,6 +195,7 @@ private fun Project.configureResourceCollectorsGeneration(
180195
androidMain,
181196
shouldGenerateCode,
182197
packageName,
198+
resClassName,
183199
makeAccessorsPublic,
184200
true
185201
)
@@ -190,6 +206,7 @@ private fun Project.configureResourceCollectorsGeneration(
190206
compilation.defaultSourceSet,
191207
shouldGenerateCode,
192208
packageName,
209+
resClassName,
193210
makeAccessorsPublic,
194211
true
195212
)
@@ -205,6 +222,7 @@ private fun Project.configureResourceCollectorsGeneration(
205222
compilation.defaultSourceSet,
206223
shouldGenerateCode,
207224
packageName,
225+
resClassName,
208226
makeAccessorsPublic,
209227
false
210228
)
@@ -217,6 +235,7 @@ private fun Project.configureExpectResourceCollectorsGeneration(
217235
sourceSet: KotlinSourceSet,
218236
shouldGenerateCode: Provider<Boolean>,
219237
packageName: Provider<String>,
238+
resClassName: Provider<String>,
220239
makeAccessorsPublic: Provider<Boolean>
221240
) {
222241
logger.info("Configure expect resource collectors generation for ${sourceSet.name}")
@@ -227,6 +246,7 @@ private fun Project.configureExpectResourceCollectorsGeneration(
227246
GenerateExpectResourceCollectorsTask::class.java
228247
) { task ->
229248
task.packageName.set(packageName)
249+
task.resClassName.set(resClassName)
230250
task.makeAccessorsPublic.set(makeAccessorsPublic)
231251
task.codeDir.set(layout.buildDirectory.dir("$RES_GEN_DIR/kotlin/${sourceSet.name}ResourceCollectors"))
232252
task.onlyIf { shouldGenerateCode.get() }
@@ -244,6 +264,7 @@ private fun Project.configureActualResourceCollectorsGeneration(
244264
sourceSet: KotlinSourceSet,
245265
shouldGenerateCode: Provider<Boolean>,
246266
packageName: Provider<String>,
267+
resClassName: Provider<String>,
247268
makeAccessorsPublic: Provider<Boolean>,
248269
useActualModifier: Boolean
249270
) {
@@ -269,6 +290,7 @@ private fun Project.configureActualResourceCollectorsGeneration(
269290
GenerateActualResourceCollectorsTask::class.java
270291
) { task ->
271292
task.packageName.set(packageName)
293+
task.resClassName.set(resClassName)
272294
task.makeAccessorsPublic.set(makeAccessorsPublic)
273295
task.useActualModifier.set(useActualModifier)
274296
task.resourceAccessorDirs.from(accessorDirs)

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResClassTask.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ import org.jetbrains.compose.internal.IdeaImportTask
99
import java.io.File
1010

1111
internal abstract class GenerateResClassTask : IdeaImportTask() {
12-
companion object {
13-
private const val RES_FILE_NAME = "Res"
14-
}
15-
1612
@get:Input
1713
abstract val packageName: Property<String>
1814

15+
@get:Input
16+
abstract val resClassName: Property<String>
17+
1918
@get:Input
2019
@get:Optional
2120
abstract val packagingDir: Property<File>
@@ -31,11 +30,12 @@ internal abstract class GenerateResClassTask : IdeaImportTask() {
3130
dir.deleteRecursively()
3231
dir.mkdirs()
3332

34-
logger.info("Generate $RES_FILE_NAME.kt")
33+
val resClassName = resClassName.get()
34+
logger.info("Generate $resClassName.kt")
3535

3636
val pkgName = packageName.get()
3737
val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: ""
3838
val isPublic = makeAccessorsPublic.get()
39-
getResFileSpec(pkgName, RES_FILE_NAME, moduleDirectory, isPublic).writeTo(dir)
39+
getResFileSpec(pkgName, resClassName, moduleDirectory, isPublic).writeTo(dir)
4040
}
4141
}

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceAccessorsTask.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ internal abstract class GenerateResourceAccessorsTask : IdeaImportTask() {
1818
@get:Input
1919
abstract val packageName: Property<String>
2020

21+
@get:Input
22+
abstract val resClassName: Property<String>
23+
2124
@get:Input
2225
abstract val sourceSetName: Property<String>
2326

@@ -68,9 +71,15 @@ internal abstract class GenerateResourceAccessorsTask : IdeaImportTask() {
6871

6972
val pkgName = packageName.get()
7073
val moduleDirectory = packagingDir.getOrNull()?.let { it.invariantSeparatorsPath + "/" } ?: ""
74+
val resClassName = resClassName.get()
7175
val isPublic = makeAccessorsPublic.get()
7276
getAccessorsSpecs(
73-
resources, pkgName, sourceSet, moduleDirectory, isPublic
77+
resources,
78+
pkgName,
79+
sourceSet,
80+
moduleDirectory,
81+
resClassName,
82+
isPublic
7483
).forEach { it.writeTo(kotlinDir) }
7584
}
7685

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GenerateResourceCollectorsTask.kt

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ internal abstract class GenerateExpectResourceCollectorsTask : IdeaImportTask()
1515
@get:Input
1616
abstract val packageName: Property<String>
1717

18+
@get:Input
19+
abstract val resClassName: Property<String>
20+
1821
@get:Input
1922
abstract val makeAccessorsPublic: Property<Boolean>
2023

@@ -31,8 +34,14 @@ internal abstract class GenerateExpectResourceCollectorsTask : IdeaImportTask()
3134
logger.info("Generate expect ResourceCollectors for $kotlinDir")
3235

3336
val pkgName = packageName.get()
37+
val resClassName = resClassName.get()
3438
val isPublic = makeAccessorsPublic.get()
35-
val spec = getExpectResourceCollectorsFileSpec(pkgName, "ExpectResourceCollectors", isPublic)
39+
val spec = getExpectResourceCollectorsFileSpec(
40+
packageName = pkgName,
41+
fileName = "ExpectResourceCollectors",
42+
resClassName = resClassName,
43+
isPublic = isPublic
44+
)
3645
spec.writeTo(kotlinDir)
3746
}
3847
}
@@ -41,6 +50,9 @@ internal abstract class GenerateActualResourceCollectorsTask : IdeaImportTask()
4150
@get:Input
4251
abstract val packageName: Property<String>
4352

53+
@get:Input
54+
abstract val resClassName: Property<String>
55+
4456
@get:Input
4557
abstract val makeAccessorsPublic: Property<Boolean>
4658

@@ -89,14 +101,16 @@ internal abstract class GenerateActualResourceCollectorsTask : IdeaImportTask()
89101
}.groupBy({ it.first }, { it.second })
90102

91103
val pkgName = packageName.get()
104+
val resClassName = resClassName.get()
92105
val isPublic = makeAccessorsPublic.get()
93106
val useActual = useActualModifier.get()
94107
val spec = getActualResourceCollectorsFileSpec(
95-
pkgName,
96-
"ActualResourceCollectors",
97-
isPublic,
98-
useActual,
99-
funNames
108+
packageName = pkgName,
109+
fileName = "ActualResourceCollectors",
110+
resClassName = resClassName,
111+
isPublic = isPublic,
112+
useActualModifier = useActual,
113+
typeToCollectorFunctions = funNames
100114
)
101115
spec.writeTo(kotlinDir)
102116
}

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/GeneratedResClassSpec.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ private fun CodeBlock.Builder.addQualifiers(resourceItem: ResourceItem): CodeBlo
125125

126126
internal fun getResFileSpec(
127127
packageName: String,
128-
fileName: String,
128+
className: String,
129129
moduleDir: String,
130130
isPublic: Boolean
131131
): FileSpec {
132132
val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL
133-
return FileSpec.builder(packageName, fileName).also { file ->
133+
return FileSpec.builder(packageName, className).also { file ->
134134
file.addAnnotation(
135135
AnnotationSpec.builder(ClassName("kotlin", "OptIn"))
136136
.addMember("%T::class", internalAnnotationClass)
@@ -142,7 +142,7 @@ internal fun getResFileSpec(
142142
.addMember("%S", "REDUNDANT_VISIBILITY_MODIFIER")
143143
.build()
144144
)
145-
file.addType(TypeSpec.objectBuilder("Res").also { resObject ->
145+
file.addType(TypeSpec.objectBuilder(className).also { resObject ->
146146
resObject.addModifiers(resModifier)
147147

148148
//readFileBytes
@@ -153,7 +153,7 @@ internal fun getResFileSpec(
153153
"""
154154
Reads the content of the resource file at the specified path and returns it as a byte array.
155155
156-
Example: `val bytes = Res.readBytes("files/key.bin")`
156+
Example: `val bytes = ${className}.readBytes("files/key.bin")`
157157
158158
@param path The path of the file to read in the compose resource's directory.
159159
@return The content of the file as a byte array.
@@ -174,7 +174,7 @@ internal fun getResFileSpec(
174174
"""
175175
Returns the URI string of the resource file at the specified path.
176176
177-
Example: `val uri = Res.getUri("files/key.bin")`
177+
Example: `val uri = ${className}.getUri("files/key.bin")`
178178
179179
@param path The path of the file in the compose resource's directory.
180180
@return The URI string of the file.
@@ -208,6 +208,7 @@ internal fun getAccessorsSpecs(
208208
packageName: String,
209209
sourceSetName: String,
210210
moduleDir: String,
211+
resClassName: String,
211212
isPublic: Boolean
212213
): List<FileSpec> {
213214
val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL
@@ -225,6 +226,7 @@ internal fun getAccessorsSpecs(
225226
sourceSetName.uppercaseFirstChar() + type.accessorName.uppercaseFirstChar() + index,
226227
packageName,
227228
moduleDir,
229+
resClassName,
228230
resModifier,
229231
idToResources.subMap(ids.first(), true, ids.last(), true)
230232
)
@@ -241,6 +243,7 @@ private fun getChunkFileSpec(
241243
chunkClassName: String,
242244
packageName: String,
243245
moduleDir: String,
246+
resClassName: String,
244247
resModifier: KModifier,
245248
idToResources: Map<String, List<ResourceItem>>
246249
): FileSpec {
@@ -281,7 +284,7 @@ private fun getChunkFileSpec(
281284
.build()
282285

283286
val accessor = PropertySpec.builder(resName, type.getClassName(), resModifier)
284-
.receiver(ClassName(packageName, "Res", type.accessorName))
287+
.receiver(ClassName(packageName, resClassName, type.accessorName))
285288
.delegate(initializer)
286289
.build()
287290
chunkFile.addProperty(accessor)
@@ -309,6 +312,7 @@ private fun getChunkFileSpec(
309312
internal fun getExpectResourceCollectorsFileSpec(
310313
packageName: String,
311314
fileName: String,
315+
resClassName: String,
312316
isPublic: Boolean
313317
): FileSpec {
314318
val resModifier = if (isPublic) KModifier.PUBLIC else KModifier.INTERNAL
@@ -323,7 +327,7 @@ internal fun getExpectResourceCollectorsFileSpec(
323327
KModifier.EXPECT,
324328
resModifier
325329
)
326-
.receiver(ClassName(packageName, "Res"))
330+
.receiver(ClassName(packageName, resClassName))
327331
.build()
328332
)
329333
}
@@ -333,6 +337,7 @@ internal fun getExpectResourceCollectorsFileSpec(
333337
internal fun getActualResourceCollectorsFileSpec(
334338
packageName: String,
335339
fileName: String,
340+
resClassName: String,
336341
isPublic: Boolean,
337342
useActualModifier: Boolean, //e.g. java only project doesn't need actual modifiers
338343
typeToCollectorFunctions: Map<ResourceType, List<String>>
@@ -370,7 +375,7 @@ internal fun getActualResourceCollectorsFileSpec(
370375
MAP.parameterizedBy(String::class.asClassName(), typeClassName),
371376
mods
372377
)
373-
.receiver(ClassName(packageName, "Res"))
378+
.receiver(ClassName(packageName, resClassName))
374379
.delegate(initBlock)
375380
.build()
376381
file.addProperty(property)

gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/resources/ResourcesDSL.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ abstract class ResourcesExtension {
2222
*/
2323
var packageOfResClass: String = ""
2424

25+
/**
26+
* The name of the generated resources accessors class.
27+
*
28+
* The default is "Res".
29+
*/
30+
var nameOfResClass: String = "Res"
31+
2532
enum class ResourceClassGeneration { Auto, Always, Never }
2633

2734
//to support groovy DSL

gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/ResourcesTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ class ResourcesTest : GradlePluginTestBase() {
229229
compose.resources {
230230
publicResClass = true
231231
packageOfResClass = "my.lib.res"
232+
nameOfResClass = "MyRes"
232233
}
233234
""".trimIndent()
234235
}

gradle-plugins/compose/src/test/test-projects/misc/commonResources/expected-open-res/androidMainResourceAccessors/my/lib/res/String0.androidMain.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.jetbrains.compose.resources.StringResource
1111

1212
private const val MD: String = "composeResources/my.lib.res/"
1313

14-
public val Res.string.android_str: StringResource by lazy {
14+
public val MyRes.string.android_str: StringResource by lazy {
1515
StringResource("string:android_str", "android_str", setOf(
1616
ResourceItem(setOf(), "${MD}values/strings.androidMain.cvr", 10, 39),
1717
))

0 commit comments

Comments
 (0)