From 9c4221cda85ca328a53a065d4a4ffef75ede934a Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 19 Aug 2016 17:50:15 +0300 Subject: [PATCH] Return EMPTY range [0, -1] when MIN_VALUE is specified as exclusive upper bound. #KT-12762 Fixed --- libraries/stdlib/src/generated/_Ranges.kt | 56 ++++++++----------- libraries/stdlib/test/ranges/RangeTest.kt | 11 ++-- .../kotlin-stdlib-gen/src/templates/Ranges.kt | 11 ++-- .../src/templates/engine/FamilyProperties.kt | 2 + 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/libraries/stdlib/src/generated/_Ranges.kt b/libraries/stdlib/src/generated/_Ranges.kt index 643b561ef59..d40bd879b21 100644 --- a/libraries/stdlib/src/generated/_Ranges.kt +++ b/libraries/stdlib/src/generated/_Ranges.kt @@ -482,23 +482,21 @@ public infix fun Short.until(to: Byte): IntRange { /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Char.MIN_VALUE]. + * If the [to] value is less than or equal to ['\u0000'] the returned range is empty. */ public infix fun Char.until(to: Char): CharRange { - val to_ = (to.toInt() - 1).toChar() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this .. to_ + if (to <= '\u0000') return CharRange.EMPTY + return this .. (to - 1).toChar() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Int.MIN_VALUE]. + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. */ public infix fun Int.until(to: Int): IntRange { - val to_ = (to.toLong() - 1).toInt() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this .. to_ + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this .. (to - 1).toInt() } /** @@ -511,67 +509,61 @@ public infix fun Long.until(to: Int): LongRange { /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Int.MIN_VALUE]. + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. */ public infix fun Byte.until(to: Int): IntRange { - val to_ = (to.toLong() - 1).toInt() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this.toInt() .. to_ + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Int.MIN_VALUE]. + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. */ public infix fun Short.until(to: Int): IntRange { - val to_ = (to.toLong() - 1).toInt() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this.toInt() .. to_ + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Long.MIN_VALUE]. + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. */ public infix fun Int.until(to: Long): LongRange { - val to_ = (to - 1).toLong() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this.toLong() .. to_ + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Long.MIN_VALUE]. + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. */ public infix fun Long.until(to: Long): LongRange { - val to_ = (to - 1).toLong() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this .. to_ + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this .. (to - 1).toLong() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Long.MIN_VALUE]. + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. */ public infix fun Byte.until(to: Long): LongRange { - val to_ = (to - 1).toLong() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this.toLong() .. to_ + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() } /** * Returns a range from this value up to but excluding the specified [to] value. * - * The [to] value must be greater than [Long.MIN_VALUE]. + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. */ public infix fun Short.until(to: Long): LongRange { - val to_ = (to - 1).toLong() - if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") - return this.toLong() .. to_ + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() } /** diff --git a/libraries/stdlib/test/ranges/RangeTest.kt b/libraries/stdlib/test/ranges/RangeTest.kt index 75360b7e18a..51ac242b6d1 100644 --- a/libraries/stdlib/test/ranges/RangeTest.kt +++ b/libraries/stdlib/test/ranges/RangeTest.kt @@ -36,8 +36,7 @@ public class RangeTest { assertTrue(9 in openRange) assertFalse(10 in openRange) - // fails to throw in JS - // assertTrue(assertFails { 1 until Int.MIN_VALUE } is IllegalArgumentException) + assertTrue((1 until Int.MIN_VALUE).isEmpty()) } @test fun byteRange() { @@ -72,7 +71,7 @@ public class RangeTest { // byte arguments now construct IntRange so no overflow here // assertTrue(assertFails { 0.toByte() until Byte.MIN_VALUE } is IllegalArgumentException) - + assertTrue((0.toByte() until Int.MIN_VALUE).isEmpty()) } @test fun shortRange() { @@ -106,6 +105,7 @@ public class RangeTest { // short arguments now construct IntRange so no overflow here // assertTrue(assertFails { 0.toShort() until Short.MIN_VALUE } is IllegalArgumentException) + assertTrue((0.toShort() until Int.MIN_VALUE).isEmpty()) } @test fun longRange() { @@ -140,7 +140,8 @@ public class RangeTest { assertTrue(9L in openRange) assertFalse(10L in openRange) - assertFailsWith { 0L until Long.MIN_VALUE } + assertTrue((0 until Long.MIN_VALUE).isEmpty()) + assertTrue((0L until Long.MIN_VALUE).isEmpty()) } @@ -168,7 +169,7 @@ public class RangeTest { assertTrue('Y' in openRange) assertFalse('Z' in openRange) - assertFailsWith { 'A' until '\u0000' } + assertTrue(('A' until '\u0000').isEmpty()) } @test fun doubleRange() { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt index a6757d50d16..96dbff0a344 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt @@ -83,12 +83,15 @@ fun ranges(): List { val elementType = rangeElementType(fromType, toType) val progressionType = elementType.name + "Range" returns(progressionType) + val minValue = if (elementType == PrimitiveType.Char) "'\\u0000'" else "$elementType.MIN_VALUE" doc { """ Returns a range from this value up to but excluding the specified [to] value. - ${ if (elementType == toType) "The [to] value must be greater than [$elementType.MIN_VALUE]." else "" } + ${textWhen(elementType == toType) { + "If the [to] value is less than or equal to [$minValue] the returned range is empty." + }} """ } @@ -102,10 +105,10 @@ fun ranges(): List { else -> "to" } body { + // <= instead of == for JS """ - val to_ = ($toExpr - 1).to$elementType() - if (to_ > to) throw IllegalArgumentException("The to argument value '${'$'}to' was too small.") - return $fromExpr .. to_ + if (to <= $minValue) return $progressionType.EMPTY + return $fromExpr .. (to - 1).to$elementType() """ } } else { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/FamilyProperties.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/FamilyProperties.kt index f6b459a40aa..7df16784a81 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/FamilyProperties.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/FamilyProperties.kt @@ -38,6 +38,8 @@ object DocExtensions { else -> "list" } + fun textWhen(condition: Boolean, text: () -> String): String = if (condition) text() else "" + private fun String.singularize() = removeSuffix("s") public fun String.pluralize() = when {