From cd0906a3578fd6078ac180853957d1332fa0a0d1 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Sun, 15 Jul 2018 06:53:46 +0300 Subject: [PATCH] Improve isNullOrEmpty() extensions - Annotate with SinceKotlin("1.3") and InlineOnly - Add contract linking the receiver and the returned value - Unify wording in docs - Add sample for Map.isNullOrEmpty #KT-23279 --- .../samples/test/samples/collections/arrays.kt | 5 +++-- .../samples/test/samples/collections/maps.kt | 12 ++++++++++++ .../stdlib/src/kotlin/collections/Arrays.kt | 14 ++++++++++++-- .../stdlib/src/kotlin/collections/Collections.kt | 3 ++- libraries/stdlib/src/kotlin/collections/Maps.kt | 16 ++++++++++++++-- 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/libraries/stdlib/samples/test/samples/collections/arrays.kt b/libraries/stdlib/samples/test/samples/collections/arrays.kt index f5ee7ee975d..449156d92a4 100644 --- a/libraries/stdlib/samples/test/samples/collections/arrays.kt +++ b/libraries/stdlib/samples/test/samples/collections/arrays.kt @@ -17,6 +17,7 @@ package samples.collections import samples.* +import kotlin.test.* @RunWith(Enclosed::class) @@ -38,10 +39,10 @@ class Arrays { val nullArray: Array? = null assertTrue(nullArray.isNullOrEmpty()) - val emptyArray = emptyArray() + val emptyArray: Array? = emptyArray() assertTrue(emptyArray.isNullOrEmpty()) - val array = arrayOf('a', 'b', 'c') + val array: Array? = arrayOf('a', 'b', 'c') assertFalse(array.isNullOrEmpty()) } } diff --git a/libraries/stdlib/samples/test/samples/collections/maps.kt b/libraries/stdlib/samples/test/samples/collections/maps.kt index 6a7fd194652..87bcf00e265 100644 --- a/libraries/stdlib/samples/test/samples/collections/maps.kt +++ b/libraries/stdlib/samples/test/samples/collections/maps.kt @@ -106,6 +106,18 @@ class Maps { } } + + @Sample + fun mapIsNullOrEmpty() { + val nullMap: Map? = null + assertTrue(nullMap.isNullOrEmpty()) + + val emptyMap: Map? = emptyMap() + assertTrue(emptyMap.isNullOrEmpty()) + + val map: Map? = mapOf('a' to 1, 'b' to 2, 'c' to 3) + assertFalse(map.isNullOrEmpty()) + } } class Filtering { diff --git a/libraries/stdlib/src/kotlin/collections/Arrays.kt b/libraries/stdlib/src/kotlin/collections/Arrays.kt index eefa0ab87eb..1b77e4581ad 100644 --- a/libraries/stdlib/src/kotlin/collections/Arrays.kt +++ b/libraries/stdlib/src/kotlin/collections/Arrays.kt @@ -9,6 +9,8 @@ package kotlin.collections +import kotlin.internal.contracts.* + /** * Returns a single list of all elements from all arrays in the given array. @@ -39,7 +41,15 @@ public fun Array>.unzip(): Pair, List> { } /** - * Returns `true` if this array is null or empty. + * Returns `true` if this nullable array is either null or empty. * @sample samples.collections.Arrays.Usage.arrayIsNullOrEmpty */ -public fun Array<*>?.isNullOrEmpty(): Boolean = this == null || this.isEmpty() +@SinceKotlin("1.3") +@kotlin.internal.InlineOnly +public inline fun Array<*>?.isNullOrEmpty(): Boolean { + contract { + returns(false) implies (this@isNullOrEmpty != null) + } + + return this == null || this.isEmpty() +} diff --git a/libraries/stdlib/src/kotlin/collections/Collections.kt b/libraries/stdlib/src/kotlin/collections/Collections.kt index c738016f946..7579ad77d3f 100644 --- a/libraries/stdlib/src/kotlin/collections/Collections.kt +++ b/libraries/stdlib/src/kotlin/collections/Collections.kt @@ -170,9 +170,10 @@ public val List.lastIndex: Int public inline fun Collection.isNotEmpty(): Boolean = !isEmpty() /** - * Returns `true` if the collection is null or if it is empty. + * Returns `true` if this nullable collection is either null or empty. * @sample samples.collections.Collections.Collections.collectionIsNullOrEmpty */ +@SinceKotlin("1.3") @kotlin.internal.InlineOnly public inline fun Collection?.isNullOrEmpty(): Boolean { contract { diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index 23b7d47cdf2..fcc6808122b 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -8,6 +8,8 @@ package kotlin.collections +import kotlin.internal.contracts.* + private object EmptyMap : Map, Serializable { private const val serialVersionUID: Long = 8246714829545688274 @@ -140,9 +142,19 @@ private const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 @kotlin.internal.InlineOnly public inline fun Map.isNotEmpty(): Boolean = !isEmpty() -/** Returns `true` if this map is null or empty. */ +/** + * Returns `true` if this nullable map is either null or empty. + * @sample samples.collections.Maps.Usage.mapIsNullOrEmpty + */ +@SinceKotlin("1.3") @kotlin.internal.InlineOnly -public inline fun Map?.isNullOrEmpty(): Boolean = this == null || isEmpty() +public inline fun Map?.isNullOrEmpty(): Boolean { + contract { + returns(false) implies (this@isNullOrEmpty != null) + } + + return this == null || isEmpty() +} /** * Returns the [Map] if its not `null`, or the empty [Map] otherwise.