Skip to content

Commit

Permalink
Document the thrown exceptions better; forbid parsing equal names
Browse files Browse the repository at this point in the history
  • Loading branch information
dkhalanskyjb committed Apr 29, 2024
1 parent 420a034 commit b5f40cd
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 4 deletions.
1 change: 1 addition & 0 deletions core/common/src/format/DateTimeFormatBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public sealed interface DateTimeFormatBuilder {
* [am] is used for the AM marker (0-11 hours), [pm] is used for the PM marker (12-23 hours).
*
* Empty strings can not be used as markers.
* [IllegalArgumentException] is thrown if either [am] or [pm] is empty or if they are equal.
*
* @see [amPmHour]
*/
Expand Down
22 changes: 18 additions & 4 deletions core/common/src/format/LocalDateFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import kotlinx.datetime.internal.format.parser.Copyable
/**
* A description of how month names are formatted.
*
* An empty string can not be a month name.
* An [IllegalArgumentException] will be thrown if some month name is empty or there are duplicate names.
*/
public class MonthNames(
/**
Expand All @@ -23,7 +23,14 @@ public class MonthNames(
) {
init {
require(names.size == 12) { "Month names must contain exactly 12 elements" }
names.forEach { require(it.isNotEmpty()) { "A month name can not be empty" } }
names.indices.forEach { ix ->
require(names[ix].isNotEmpty()) { "A month name can not be empty" }
for (ix2 in 0 until ix) {
require(names[ix] != names[ix2]) {
"Month names must be unique, but '${names[ix]}' was repeated"
}
}
}
}

/**
Expand Down Expand Up @@ -67,7 +74,7 @@ internal fun MonthNames.toKotlinCode(): String = when (this.names) {
/**
* A description of how day of week names are formatted.
*
* An empty string can not be a day-of-week name.
* An [IllegalArgumentException] will be thrown if some day-of-week name is empty or there are duplicate names.
*/
public class DayOfWeekNames(
/**
Expand All @@ -77,7 +84,14 @@ public class DayOfWeekNames(
) {
init {
require(names.size == 7) { "Day of week names must contain exactly 7 elements" }
names.forEach { require(it.isNotEmpty()) { "A month name can not be empty" } }
names.indices.forEach { ix ->
require(names[ix].isNotEmpty()) { "A day-of-week name can not be empty" }
for (ix2 in 0 until ix) {
require(names[ix] != names[ix2]) {
"Day-of-week names must be unique, but '${names[ix]}' was repeated"
}
}
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions core/common/src/internal/format/parser/ParserOperation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ internal class StringSetParserOperation<Output>(
node.children[searchResult].second
}
}
require(!node.isTerminal) { "The string '$string' was passed several times" }
node.isTerminal = true
}
fun reduceTrie(trie: TrieNode) {
Expand Down
32 changes: 32 additions & 0 deletions core/common/test/format/LocalDateFormatTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,38 @@ class LocalDateFormatTest {
assertEquals("2020 Jan 05", format.format(LocalDate(2020, 1, 5)))
}

@Test
fun testEmptyMonthNames() {
val names = MonthNames.ENGLISH_FULL.names
for (i in 0 until 12) {
val newNames = (0 until 12).map { if (it == i) "" else names[it] }
assertFailsWith<IllegalArgumentException> { MonthNames(newNames) }
}
}

@Test
fun testEmptyDayOfWeekNames() {
val names = DayOfWeekNames.ENGLISH_FULL.names
for (i in 0 until 7) {
val newNames = (0 until 7).map { if (it == i) "" else names[it] }
assertFailsWith<IllegalArgumentException> { DayOfWeekNames(newNames) }
}
}

@Test
fun testIdenticalMonthNames() {
assertFailsWith<IllegalArgumentException> {
MonthNames("Jan", "Jan", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
}
}

@Test
fun testIdenticalDayOfWeekNames() {
assertFailsWith<IllegalArgumentException> {
DayOfWeekNames("Mon", "Tue", "Tue", "Thu", "Fri", "Sat", "Sun")
}
}

private fun test(strings: Map<LocalDate, Pair<String, Set<String>>>, format: DateTimeFormat<LocalDate>) {
for ((date, stringsForDate) in strings) {
val (canonicalString, otherStrings) = stringsForDate
Expand Down
18 changes: 18 additions & 0 deletions core/common/test/format/LocalTimeFormatTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,24 @@ class LocalTimeFormatTest {
}
}

@Test
fun testEmptyAmPmMarkers() {
assertFailsWith<IllegalArgumentException> {
LocalTime.Format {
amPmMarker("", "pm")
}
}
}

@Test
fun testIdenticalAmPmMarkers() {
assertFailsWith<IllegalArgumentException> {
LocalTime.Format {
amPmMarker("pm", "pm")
}
}
}

private fun test(strings: Map<LocalTime, Pair<String, Set<String>>>, format: DateTimeFormat<LocalTime>) {
for ((date, stringsForDate) in strings) {
val (canonicalString, otherStrings) = stringsForDate
Expand Down

0 comments on commit b5f40cd

Please sign in to comment.