Generate coerceAtLeast, coerceAtMost and coerceIn extension functions for numbers and other Comparables.

This commit is contained in:
Ilya Gorbunov
2015-04-15 22:14:27 +03:00
parent ade69ec0e9
commit ccc3646bb8
5 changed files with 560 additions and 6 deletions
@@ -0,0 +1,305 @@
package kotlin
//
// NOTE THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt
// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib
//
import java.util.*
import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun <T: Comparable<T>> T.coerceAtLeast(minimumValue: T): T {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Byte.coerceAtLeast(minimumValue: Byte): Byte {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Double.coerceAtLeast(minimumValue: Double): Double {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Float.coerceAtLeast(minimumValue: Float): Float {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Int.coerceAtLeast(minimumValue: Int): Int {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Long.coerceAtLeast(minimumValue: Long): Long {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not less than the specified [minimumValue].
* @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise.
*/
public fun Short.coerceAtLeast(minimumValue: Short): Short {
return if (this < minimumValue) minimumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun <T: Comparable<T>> T.coerceAtMost(maximumValue: T): T {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Byte.coerceAtMost(maximumValue: Byte): Byte {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Double.coerceAtMost(maximumValue: Double): Double {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Float.coerceAtMost(maximumValue: Float): Float {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Int.coerceAtMost(maximumValue: Int): Int {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Long.coerceAtMost(maximumValue: Long): Long {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value is not greater than the specified [maximumValue].
* @return this value if it's greater than or equal to the [maximumValue] or the [maximumValue] otherwise.
*/
public fun Short.coerceAtMost(maximumValue: Short): Short {
return if (this > maximumValue) maximumValue else this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun <T: Comparable<T>> T.coerceIn(minimumValue: T?, maximumValue: T?): T {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Byte.coerceIn(minimumValue: Byte?, maximumValue: Byte?): Byte {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Double.coerceIn(minimumValue: Double?, maximumValue: Double?): Double {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Float.coerceIn(minimumValue: Float?, maximumValue: Float?): Float {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Int.coerceIn(minimumValue: Int?, maximumValue: Int?): Int {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Long.coerceIn(minimumValue: Long?, maximumValue: Long?): Long {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified range [minimumValue]..[maximumValue].
* @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue].
*/
public fun Short.coerceIn(minimumValue: Short?, maximumValue: Short?): Short {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun <T: Comparable<T>> T.coerceIn(range: Range<T>): T {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Byte.coerceIn(range: ByteRange): Byte {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Double.coerceIn(range: DoubleRange): Double {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Float.coerceIn(range: FloatRange): Float {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Int.coerceIn(range: IntRange): Int {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Long.coerceIn(range: LongRange): Long {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
/**
* Ensures that this value lies in the specified [range].
* @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end.
*/
public fun Short.coerceIn(range: ShortRange): Short {
if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.")
return if (this < range.start) range.start else if (this > range.end) range.end else this
}
@@ -0,0 +1,118 @@
package numbers
import org.junit.Test
import org.junit.Test as test
import kotlin.test.*
class CoercionTest {
fun usage() {
val n = 1
// infix usage
val n1 = n coerceAtLeast 2
// function usage
val n2 = n.coerceAtLeast(2)
// infix with range
val n3 = n coerceIn 2..5
}
Test fun coercionsInt() {
expect(5) { 5.coerceAtLeast(1) }
expect(5) { 1.coerceAtLeast(5) }
expect(1) { 5.coerceAtMost(1) }
expect(1) { 1.coerceAtMost(5) }
for (value in 0..10) {
expect(value) { value.coerceIn(null, null) }
val min = 2
val max = 5
val range = min..max
expect(value.coerceAtLeast(min)) { value.coerceIn(min, null) }
expect(value.coerceAtMost(max)) { value.coerceIn(null, max) }
expect(value.coerceAtLeast(min).coerceAtMost(max)) { value.coerceIn(min, max) }
expect(value.coerceAtMost(max).coerceAtLeast(min)) { value coerceIn range }
assertTrue((value coerceIn range) in range)
}
fails { 1.coerceIn(1, 0) }
fails { 1.coerceIn(1..0) }
}
Test fun coercionsLong() {
expect(5L) { 5L.coerceAtLeast(1L) }
expect(5L) { 1L.coerceAtLeast(5L) }
expect(1L) { 5L.coerceAtMost(1L) }
expect(1L) { 1L.coerceAtMost(5L) }
for (value in 0L..10L) {
expect(value) { value.coerceIn(null, null) }
val min = 2L
val max = 5L
val range = min..max
expect(value.coerceAtLeast(min)) { value.coerceIn(min, null) }
expect(value.coerceAtMost(max)) { value.coerceIn(null, max) }
expect(value.coerceAtLeast(min).coerceAtMost(max)) { value.coerceIn(min, max) }
expect(value.coerceAtMost(max).coerceAtLeast(min)) { value coerceIn range }
assertTrue((value coerceIn range) in range)
}
fails { 1L.coerceIn(1L, 0L) }
fails { 1L.coerceIn(1L..0L) }
}
Test fun coercionsDouble() {
expect(5.0) { 5.0.coerceAtLeast(1.0) }
expect(5.0) { 1.0.coerceAtLeast(5.0) }
expect(1.0) { 5.0.coerceAtMost(1.0) }
expect(1.0) { 1.0.coerceAtMost(5.0) }
for (value in 0.0..10.0) {
expect(value) { value.coerceIn(null, null) }
val min = 2.0
val max = 5.0
val range = min..max
expect(value.coerceAtLeast(min)) { value.coerceIn(min, null) }
expect(value.coerceAtMost(max)) { value.coerceIn(null, max) }
expect(value.coerceAtLeast(min).coerceAtMost(max)) { value.coerceIn(min, max) }
expect(value.coerceAtMost(max).coerceAtLeast(min)) { value coerceIn range }
assertTrue((value coerceIn range) in range)
}
fails { 1.0.coerceIn(1.0, 0.0) }
fails { 1.0.coerceIn(1.0..0.0) }
}
Test fun coercionsComparable() {
val v = 0..10 map { ComparableNumber(it) }
expect(5) { v[5].coerceAtLeast(v[1]).value }
expect(5) { v[1].coerceAtLeast(v[5]).value }
expect(v[5]) { v[5].coerceAtLeast(ComparableNumber(5)) }
expect(1) { v[5].coerceAtMost(v[1]).value }
expect(1) { v[1].coerceAtMost(v[5]).value }
expect(v[1]) { v[1].coerceAtMost(ComparableNumber(1)) }
for (value in v) {
expect(value) { value.coerceIn(null, null) }
val min = v[2]
val max = v[5]
val range = min..max
expect(value.coerceAtLeast(min)) { value.coerceIn(min, null) }
expect(value.coerceAtMost(max)) { value.coerceIn(null, max) }
expect(value.coerceAtLeast(min).coerceAtMost(max)) { value.coerceIn(min, max) }
expect(value.coerceAtMost(max).coerceAtLeast(min)) { value coerceIn range }
assertTrue((value coerceIn range) in range)
}
fails { v[1].coerceIn(v[1], v[0]) }
fails { v[1].coerceIn(v[1]..v[0]) }
}
}
private class ComparableNumber(public val value: Int) : Comparable<ComparableNumber> {
override fun compareTo(other: ComparableNumber): Int = this.value - other.value
override fun toString(): String = "CV$value"
}