Add contains extension for mixed types for open ranges and open-closed range specializations

#KT-52932
This commit is contained in:
Ilya Gorbunov
2022-06-21 21:21:48 +03:00
committed by Space
parent 9574040f85
commit 8584fe2725
2 changed files with 212 additions and 2 deletions
@@ -362,6 +362,52 @@ public operator fun ClosedRange<Float>.contains(value: Byte): Boolean {
return contains(value.toFloat())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("intRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Int>.contains(value: Byte): Boolean {
return contains(value.toInt())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("longRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Long>.contains(value: Byte): Boolean {
return contains(value.toLong())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("shortRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Short>.contains(value: Byte): Boolean {
return contains(value.toShort())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun IntRange.contains(value: Byte): Boolean {
return (this as ClosedRange<Int>).contains(value)
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun LongRange.contains(value: Byte): Boolean {
return (this as ClosedRange<Long>).contains(value)
}
/**
* Checks if the specified [value] belongs to this range.
*/
@@ -458,7 +504,15 @@ public operator fun ClosedRange<Double>.contains(value: Float): Boolean {
return contains(value.toDouble())
}
// TODO: for OpenEndRange<Double>
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("doubleRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Double>.contains(value: Float): Boolean {
return contains(value.toDouble())
}
/**
* Checks if the specified [value] belongs to this range.
@@ -504,6 +558,44 @@ public operator fun ClosedRange<Float>.contains(value: Int): Boolean {
return contains(value.toFloat())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("longRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Long>.contains(value: Int): Boolean {
return contains(value.toLong())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("byteRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Byte>.contains(value: Int): Boolean {
return value.toByteExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("shortRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Short>.contains(value: Int): Boolean {
return value.toShortExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun LongRange.contains(value: Int): Boolean {
return (this as ClosedRange<Long>).contains(value)
}
/**
* Checks if the specified [value] belongs to this range.
*/
@@ -548,6 +640,44 @@ public operator fun ClosedRange<Float>.contains(value: Long): Boolean {
return contains(value.toFloat())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("intRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Int>.contains(value: Long): Boolean {
return value.toIntExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("byteRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Byte>.contains(value: Long): Boolean {
return value.toByteExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("shortRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Short>.contains(value: Long): Boolean {
return value.toShortExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun IntRange.contains(value: Long): Boolean {
return (this as ClosedRange<Int>).contains(value)
}
/**
* Checks if the specified [value] belongs to this range.
*/
@@ -592,6 +722,52 @@ public operator fun ClosedRange<Float>.contains(value: Short): Boolean {
return contains(value.toFloat())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("intRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Int>.contains(value: Short): Boolean {
return contains(value.toInt())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("longRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Long>.contains(value: Short): Boolean {
return contains(value.toLong())
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.jvm.JvmName("byteRangeContains")
@SinceKotlin("1.7")
@ExperimentalStdlibApi
public operator fun OpenEndRange<Byte>.contains(value: Short): Boolean {
return value.toByteExactOrNull().let { if (it != null) contains(it) else false }
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun IntRange.contains(value: Short): Boolean {
return (this as ClosedRange<Int>).contains(value)
}
/**
* Checks if the specified [value] belongs to this range.
*/
@kotlin.internal.InlineOnly
public inline operator fun LongRange.contains(value: Short): Boolean {
return (this as ClosedRange<Long>).contains(value)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
@@ -176,7 +176,7 @@ object RangeOps : TemplateGroupBase() {
body { "return until(to)" }
}
val f_contains = fn("contains(value: Primitive)").byTwoPrimitives {
val f_containsMixedClosed = fn("contains(value: Primitive)").byTwoPrimitives {
include(Ranges, numericCombinations)
filter { _, (rangeType, itemType) -> rangeType != itemType }
} builderWith { (rangeType, itemType) ->
@@ -200,6 +200,40 @@ object RangeOps : TemplateGroupBase() {
}
}
val f_containsMixedOpenAndPrimitive = fn("contains(value: Primitive)").byTwoPrimitives {
include(OpenRanges, numericCombinations)
include(RangesOfPrimitives, numericCombinations.filter { (rangeType, _) -> rangeType in rangePrimitives })
filter { _, (rangeType, itemType) ->
rangeType != itemType && rangeType.isIntegral() == itemType.isIntegral() &&
rangeType != PrimitiveType.Float
}
} builderWith { (rangeType, itemType) ->
operator()
specialFor(OpenRanges) {
since("1.7")
annotation("@ExperimentalStdlibApi")
}
signature("contains(value: $itemType)")
check(rangeType.isNumeric() == itemType.isNumeric()) { "Required rangeType and itemType both to be numeric or both not, got: $rangeType, $itemType" }
platformName("${rangeType.name.decapitalize()}RangeContains")
returns("Boolean")
doc { "Checks if the specified [value] belongs to this range." }
body {
if (shouldCheckForConversionOverflow(fromType = itemType, toType = rangeType))
"return value.to${rangeType}ExactOrNull().let { if (it != null) contains(it) else false }"
else
"return contains(value.to$rangeType())"
}
specialFor(RangesOfPrimitives) {
inlineOnly()
body {
"return (this as ClosedRange<$rangeType>).contains(value)"
}
}
}
val f_contains_nullable = fn("contains(element: T?)") {
include(RangesOfPrimitives, rangePrimitives)
} builder {