Skip to content

Commit fc19b61

Browse files
author
Wojciech Liberda
committed
Throw IllegalArgumentException with meaningful message for missing format arguments
1 parent 3ea093f commit fc19b61

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResourcesUtils.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ internal fun String.replaceWithArgs(args: List<String>): String {
1919
)
2020
}
2121
}
22-
args[index]
22+
args.getOrElse(index) {
23+
throw IllegalArgumentException(
24+
"Formatting failed: Placeholder '${match.value}' at position ${index + 1} is out of bounds. Only ${args.size} argument(s) provided for format string \"$this\""
25+
)
26+
}
2327
}
2428
}
2529

@@ -37,7 +41,7 @@ internal fun dropStringItemsCache() {
3741

3842
internal suspend fun getStringItem(
3943
resourceItem: ResourceItem,
40-
resourceReader: ResourceReader
44+
resourceReader: ResourceReader,
4145
): StringItem = stringItemsCache.getOrLoad(
4246
key = "${resourceItem.path}/${resourceItem.offset}-${resourceItem.size}"
4347
) {

components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/StringFormatTest.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ class StringFormatTest {
5252
val template = "Hello %1\$s, %2\$s!"
5353
val args = listOf("Alice")
5454

55-
assertFailsWith<IndexOutOfBoundsException> {
55+
val exception = assertFailsWith<IllegalArgumentException> {
5656
template.replaceWithArgs(args)
5757
}
58+
assertEquals(
59+
"Formatting failed: Placeholder '%2\$s' at position 2 is out of bounds. Only 1 argument(s) provided for format string \"Hello %1\$s, %2\$s!\"",
60+
exception.message
61+
)
5862
}
5963

6064
@Test
@@ -72,9 +76,13 @@ class StringFormatTest {
7276
val template = "Hello %1\$s, you have %3\$s messages"
7377
val args = listOf("Alice")
7478

75-
assertFailsWith<IndexOutOfBoundsException> {
79+
val exception = assertFailsWith<IllegalArgumentException> {
7680
template.replaceWithArgs(args)
7781
}
82+
assertEquals(
83+
"Formatting failed: Placeholder '%3\$s' at position 3 is out of bounds. Only 1 argument(s) provided for format string \"Hello %1\$s, you have %3\$s messages\"",
84+
exception.message
85+
)
7886
}
7987

8088
@Test
@@ -142,9 +150,13 @@ class StringFormatTest {
142150
val args = listOf("Alice")
143151

144152
// An exception should be thrown because the second argument (%2$d) is missing
145-
assertFailsWith<IndexOutOfBoundsException> {
153+
val exception = assertFailsWith<IllegalArgumentException> {
146154
template.replaceWithArgs(args)
147155
}
156+
assertEquals(
157+
"Formatting failed: Placeholder '%2\$d' at position 2 is out of bounds. Only 1 argument(s) provided for format string \"Hello %1\$s, you have %2\$d messages!\"",
158+
exception.message
159+
)
148160
}
149161

150162
@Test
@@ -154,9 +166,13 @@ class StringFormatTest {
154166
val args = listOf("Alice", "1")
155167

156168
// The template has a %3$s placeholder, but there is no third argument
157-
assertFailsWith<IndexOutOfBoundsException> {
169+
val exception = assertFailsWith<IllegalArgumentException> {
158170
template.replaceWithArgs(args)
159171
}
172+
assertEquals(
173+
"Formatting failed: Placeholder '%3\$s' at position 3 is out of bounds. Only 2 argument(s) provided for format string \"Hello %1\$s, your rank is %3\$s\"",
174+
exception.message
175+
)
160176
}
161177

162178
@Test

0 commit comments

Comments
 (0)