Skip to content

Commit b5f40cd

Browse files
committed
Document the thrown exceptions better; forbid parsing equal names
1 parent 420a034 commit b5f40cd

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

core/common/src/format/DateTimeFormatBuilder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ public sealed interface DateTimeFormatBuilder {
130130
* [am] is used for the AM marker (0-11 hours), [pm] is used for the PM marker (12-23 hours).
131131
*
132132
* Empty strings can not be used as markers.
133+
* [IllegalArgumentException] is thrown if either [am] or [pm] is empty or if they are equal.
133134
*
134135
* @see [amPmHour]
135136
*/

core/common/src/format/LocalDateFormat.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import kotlinx.datetime.internal.format.parser.Copyable
1313
/**
1414
* A description of how month names are formatted.
1515
*
16-
* An empty string can not be a month name.
16+
* An [IllegalArgumentException] will be thrown if some month name is empty or there are duplicate names.
1717
*/
1818
public class MonthNames(
1919
/**
@@ -23,7 +23,14 @@ public class MonthNames(
2323
) {
2424
init {
2525
require(names.size == 12) { "Month names must contain exactly 12 elements" }
26-
names.forEach { require(it.isNotEmpty()) { "A month name can not be empty" } }
26+
names.indices.forEach { ix ->
27+
require(names[ix].isNotEmpty()) { "A month name can not be empty" }
28+
for (ix2 in 0 until ix) {
29+
require(names[ix] != names[ix2]) {
30+
"Month names must be unique, but '${names[ix]}' was repeated"
31+
}
32+
}
33+
}
2734
}
2835

2936
/**
@@ -67,7 +74,7 @@ internal fun MonthNames.toKotlinCode(): String = when (this.names) {
6774
/**
6875
* A description of how day of week names are formatted.
6976
*
70-
* An empty string can not be a day-of-week name.
77+
* An [IllegalArgumentException] will be thrown if some day-of-week name is empty or there are duplicate names.
7178
*/
7279
public class DayOfWeekNames(
7380
/**
@@ -77,7 +84,14 @@ public class DayOfWeekNames(
7784
) {
7885
init {
7986
require(names.size == 7) { "Day of week names must contain exactly 7 elements" }
80-
names.forEach { require(it.isNotEmpty()) { "A month name can not be empty" } }
87+
names.indices.forEach { ix ->
88+
require(names[ix].isNotEmpty()) { "A day-of-week name can not be empty" }
89+
for (ix2 in 0 until ix) {
90+
require(names[ix] != names[ix2]) {
91+
"Day-of-week names must be unique, but '${names[ix]}' was repeated"
92+
}
93+
}
94+
}
8195
}
8296

8397
/**

core/common/src/internal/format/parser/ParserOperation.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ internal class StringSetParserOperation<Output>(
167167
node.children[searchResult].second
168168
}
169169
}
170+
require(!node.isTerminal) { "The string '$string' was passed several times" }
170171
node.isTerminal = true
171172
}
172173
fun reduceTrie(trie: TrieNode) {

core/common/test/format/LocalDateFormatTest.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,38 @@ class LocalDateFormatTest {
221221
assertEquals("2020 Jan 05", format.format(LocalDate(2020, 1, 5)))
222222
}
223223

224+
@Test
225+
fun testEmptyMonthNames() {
226+
val names = MonthNames.ENGLISH_FULL.names
227+
for (i in 0 until 12) {
228+
val newNames = (0 until 12).map { if (it == i) "" else names[it] }
229+
assertFailsWith<IllegalArgumentException> { MonthNames(newNames) }
230+
}
231+
}
232+
233+
@Test
234+
fun testEmptyDayOfWeekNames() {
235+
val names = DayOfWeekNames.ENGLISH_FULL.names
236+
for (i in 0 until 7) {
237+
val newNames = (0 until 7).map { if (it == i) "" else names[it] }
238+
assertFailsWith<IllegalArgumentException> { DayOfWeekNames(newNames) }
239+
}
240+
}
241+
242+
@Test
243+
fun testIdenticalMonthNames() {
244+
assertFailsWith<IllegalArgumentException> {
245+
MonthNames("Jan", "Jan", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
246+
}
247+
}
248+
249+
@Test
250+
fun testIdenticalDayOfWeekNames() {
251+
assertFailsWith<IllegalArgumentException> {
252+
DayOfWeekNames("Mon", "Tue", "Tue", "Thu", "Fri", "Sat", "Sun")
253+
}
254+
}
255+
224256
private fun test(strings: Map<LocalDate, Pair<String, Set<String>>>, format: DateTimeFormat<LocalDate>) {
225257
for ((date, stringsForDate) in strings) {
226258
val (canonicalString, otherStrings) = stringsForDate

core/common/test/format/LocalTimeFormatTest.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,24 @@ class LocalTimeFormatTest {
216216
}
217217
}
218218

219+
@Test
220+
fun testEmptyAmPmMarkers() {
221+
assertFailsWith<IllegalArgumentException> {
222+
LocalTime.Format {
223+
amPmMarker("", "pm")
224+
}
225+
}
226+
}
227+
228+
@Test
229+
fun testIdenticalAmPmMarkers() {
230+
assertFailsWith<IllegalArgumentException> {
231+
LocalTime.Format {
232+
amPmMarker("pm", "pm")
233+
}
234+
}
235+
}
236+
219237
private fun test(strings: Map<LocalTime, Pair<String, Set<String>>>, format: DateTimeFormat<LocalTime>) {
220238
for ((date, stringsForDate) in strings) {
221239
val (canonicalString, otherStrings) = stringsForDate

0 commit comments

Comments
 (0)