From e632d58936077c92cbe18a9e877f77597b140326 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Thu, 27 Feb 2020 14:44:33 +0300 Subject: [PATCH] Nullable Array.contentEquals/contentHashCode/contentToString #KT-34161 --- .../stdlib/common/src/generated/_Arrays.kt | 282 +++++++++++ .../stdlib/common/src/generated/_UArrays.kt | 156 +++++- .../stdlib/js-ir/runtime/collectionsHacks.kt | 7 +- .../stdlib/js-ir/src/generated/_ArraysJs.kt | 392 ++++++++++++++- libraries/stdlib/js-v1/src/js/arrayUtils.js | 4 +- .../stdlib/js/src/generated/_ArraysJs.kt | 450 +++++++++++++++--- .../js/src/kotlin/collections/ArraysJs.kt | 3 +- .../stdlib/jvm/src/generated/_ArraysJvm.kt | 450 +++++++++++++++++- .../jvm/src/kotlin/collections/ArraysJVM.kt | 2 +- .../jvm/test/collections/ArraysJVMTest.kt | 66 +++ .../stdlib/src/kotlin/collections/Arrays.kt | 7 +- .../stdlib/test/collections/ArraysTest.kt | 18 + .../test/collections/UnsignedArraysTest.kt | 8 + .../kotlin-stdlib-runtime-merged.txt | 12 + .../kotlin-stdlib-gen/src/templates/Arrays.kt | 169 ++++++- .../src/templates/dsl/TypeParameterParsers.kt | 4 +- 16 files changed, 1897 insertions(+), 133 deletions(-) create mode 100644 libraries/stdlib/jvm/test/collections/ArraysJVMTest.kt diff --git a/libraries/stdlib/common/src/generated/_Arrays.kt b/libraries/stdlib/common/src/generated/_Arrays.kt index 31cba44a11c..291efc99d58 100644 --- a/libraries/stdlib/common/src/generated/_Arrays.kt +++ b/libraries/stdlib/common/src/generated/_Arrays.kt @@ -6015,8 +6015,24 @@ public expect fun CharArray.asList(): List * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun Array.contentDeepEquals(other: Array): Boolean +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun Array?.contentDeepEquals(other: Array?): Boolean + /** * Returns a hash code based on the contents of this array as if it is [List]. * Nested arrays are treated as lists too. @@ -6024,8 +6040,18 @@ public expect infix fun Array.contentDeepEquals(other: Array): * If any of arrays contains itself on any nesting level the behavior is undefined. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun Array.contentDeepHashCode(): Int +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +public expect fun Array?.contentDeepHashCode(): Int + /** * Returns a string representation of the contents of this array as if it is a [List]. * Nested arrays are treated as lists too. @@ -6036,8 +6062,21 @@ public expect fun Array.contentDeepHashCode(): Int * @sample samples.collections.Arrays.ContentOperations.contentDeepToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun Array.contentDeepToString(): String +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +public expect fun Array?.contentDeepToString(): String + /** * Returns `true` if the two specified arrays are *structurally* equal to one another, * i.e. contain the same number of the same elements in the same order. @@ -6046,6 +6085,7 @@ public expect fun Array.contentDeepToString(): String * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun Array.contentEquals(other: Array): Boolean /** @@ -6056,6 +6096,7 @@ public expect infix fun Array.contentEquals(other: Array): Boo * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun ByteArray.contentEquals(other: ByteArray): Boolean /** @@ -6066,6 +6107,7 @@ public expect infix fun ByteArray.contentEquals(other: ByteArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun ShortArray.contentEquals(other: ShortArray): Boolean /** @@ -6076,6 +6118,7 @@ public expect infix fun ShortArray.contentEquals(other: ShortArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun IntArray.contentEquals(other: IntArray): Boolean /** @@ -6086,6 +6129,7 @@ public expect infix fun IntArray.contentEquals(other: IntArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun LongArray.contentEquals(other: LongArray): Boolean /** @@ -6096,6 +6140,7 @@ public expect infix fun LongArray.contentEquals(other: LongArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun FloatArray.contentEquals(other: FloatArray): Boolean /** @@ -6106,6 +6151,7 @@ public expect infix fun FloatArray.contentEquals(other: FloatArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean /** @@ -6116,6 +6162,7 @@ public expect infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean /** @@ -6126,68 +6173,223 @@ public expect infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect infix fun CharArray.contentEquals(other: CharArray): Boolean +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun Array?.contentEquals(other: Array?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun IntArray?.contentEquals(other: IntArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun LongArray?.contentEquals(other: LongArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public expect infix fun CharArray?.contentEquals(other: CharArray?): Boolean + /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun Array.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun ByteArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun ShortArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun IntArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun LongArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun FloatArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun DoubleArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun BooleanArray.contentHashCode(): Int /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun CharArray.contentHashCode(): Int +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun Array?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun ByteArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun ShortArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun IntArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun LongArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun FloatArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun DoubleArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun BooleanArray?.contentHashCode(): Int + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public expect fun CharArray?.contentHashCode(): Int + /** * Returns a string representation of the contents of the specified array as if it is [List]. * * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun Array.contentToString(): String /** @@ -6196,6 +6398,7 @@ public expect fun Array.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun ByteArray.contentToString(): String /** @@ -6204,6 +6407,7 @@ public expect fun ByteArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun ShortArray.contentToString(): String /** @@ -6212,6 +6416,7 @@ public expect fun ShortArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun IntArray.contentToString(): String /** @@ -6220,6 +6425,7 @@ public expect fun IntArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun LongArray.contentToString(): String /** @@ -6228,6 +6434,7 @@ public expect fun LongArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun FloatArray.contentToString(): String /** @@ -6236,6 +6443,7 @@ public expect fun FloatArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun DoubleArray.contentToString(): String /** @@ -6244,6 +6452,7 @@ public expect fun DoubleArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun BooleanArray.contentToString(): String /** @@ -6252,8 +6461,81 @@ public expect fun BooleanArray.contentToString(): String * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public expect fun CharArray.contentToString(): String +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun Array?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun ByteArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun ShortArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun IntArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun LongArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun FloatArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun DoubleArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun BooleanArray?.contentToString(): String + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public expect fun CharArray?.contentToString(): String + /** * Copies this array or its subrange into the [destination] array and returns that array. * diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index 7ad2c4f028b..f56b4612c27 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -3015,9 +3015,10 @@ public inline fun ShortArray.asUShortArray(): UShortArray { * i.e. contain the same number of the same elements in the same order. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public infix fun UIntArray.contentEquals(other: UIntArray): Boolean { - return storage.contentEquals(other.storage) + return this.contentEquals(other) } /** @@ -3025,9 +3026,10 @@ public infix fun UIntArray.contentEquals(other: UIntArray): Boolean { * i.e. contain the same number of the same elements in the same order. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public infix fun ULongArray.contentEquals(other: ULongArray): Boolean { - return storage.contentEquals(other.storage) + return this.contentEquals(other) } /** @@ -3035,9 +3037,10 @@ public infix fun ULongArray.contentEquals(other: ULongArray): Boolean { * i.e. contain the same number of the same elements in the same order. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public infix fun UByteArray.contentEquals(other: UByteArray): Boolean { - return storage.contentEquals(other.storage) + return this.contentEquals(other) } /** @@ -3045,45 +3048,126 @@ public infix fun UByteArray.contentEquals(other: UByteArray): Boolean { * i.e. contain the same number of the same elements in the same order. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public infix fun UShortArray.contentEquals(other: UShortArray): Boolean { - return storage.contentEquals(other.storage) + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public infix fun UIntArray?.contentEquals(other: UIntArray?): Boolean { + return this?.storage.contentEquals(other?.storage) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public infix fun ULongArray?.contentEquals(other: ULongArray?): Boolean { + return this?.storage.contentEquals(other?.storage) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public infix fun UByteArray?.contentEquals(other: UByteArray?): Boolean { + return this?.storage.contentEquals(other?.storage) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public infix fun UShortArray?.contentEquals(other: UShortArray?): Boolean { + return this?.storage.contentEquals(other?.storage) } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UIntArray.contentHashCode(): Int { - return storage.contentHashCode() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun ULongArray.contentHashCode(): Int { - return storage.contentHashCode() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UByteArray.contentHashCode(): Int { - return storage.contentHashCode() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UShortArray.contentHashCode(): Int { - return storage.contentHashCode() + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UIntArray?.contentHashCode(): Int { + return this?.storage.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun ULongArray?.contentHashCode(): Int { + return this?.storage.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UByteArray?.contentHashCode(): Int { + return this?.storage.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UShortArray?.contentHashCode(): Int { + return this?.storage.contentHashCode() } /** @@ -3092,9 +3176,10 @@ public fun UShortArray.contentHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UIntArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -3103,9 +3188,10 @@ public fun UIntArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun ULongArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -3114,9 +3200,10 @@ public fun ULongArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UByteArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -3125,9 +3212,54 @@ public fun UByteArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.3") +@kotlin.internal.LowPriorityInOverloadResolution @ExperimentalUnsignedTypes public fun UShortArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UIntArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun ULongArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UByteArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@ExperimentalUnsignedTypes +public fun UShortArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" } /** diff --git a/libraries/stdlib/js-ir/runtime/collectionsHacks.kt b/libraries/stdlib/js-ir/runtime/collectionsHacks.kt index e9c1562a81c..09adcb30588 100644 --- a/libraries/stdlib/js-ir/runtime/collectionsHacks.kt +++ b/libraries/stdlib/js-ir/runtime/collectionsHacks.kt @@ -9,7 +9,8 @@ import kotlin.js.* internal fun arrayToString(array: Array<*>) = array.joinToString(", ", "[", "]") { toString(it) } -internal fun Array.contentDeepHashCodeInternal(): Int { +internal fun Array?.contentDeepHashCodeInternal(): Int { + if (this == null) return 0 var result = 1 for (element in this) { val elementHash = when { @@ -35,7 +36,7 @@ internal fun T.contentEqualsInternal(other: T): Boolean { if (a === b) return true - if (!isArrayish(b) || a.length != b.length) return false + if (a == null || b == null || !isArrayish(b) || a.length != b.length) return false for (i in 0 until a.length) { if (!equals(a[i], b[i])) { @@ -47,6 +48,8 @@ internal fun T.contentEqualsInternal(other: T): Boolean { internal fun T.contentHashCodeInternal(): Int { val a = this.asDynamic() + if (a == null) return 0 + var result = 1 for (i in 0 until a.length) { diff --git a/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt b/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt index d5c5f8b1b5c..dc764b0d850 100644 --- a/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt +++ b/libraries/stdlib/js-ir/src/generated/_ArraysJs.kt @@ -194,7 +194,25 @@ public actual fun CharArray.asList(): List { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun Array.contentDeepEquals(other: Array): Boolean { + return this.contentDeepEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentDeepEquals(other: Array?): Boolean { return contentDeepEqualsImpl(other) } @@ -205,7 +223,19 @@ public actual infix fun Array.contentDeepEquals(other: Array): * If any of arrays contains itself on any nesting level the behavior is undefined. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentDeepHashCode(): Int { + return this.contentDeepHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepHashCode(): Int { return contentDeepHashCodeInternal() } @@ -219,7 +249,22 @@ public actual fun Array.contentDeepHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentDeepToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentDeepToString(): String { + return this.contentDeepToString() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepToString(): String { return contentDeepToStringImpl() } @@ -231,8 +276,9 @@ public actual fun Array.contentDeepToString(): String { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun Array.contentEquals(other: Array): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -243,8 +289,9 @@ public actual infix fun Array.contentEquals(other: Array): Boo * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -255,8 +302,9 @@ public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -267,8 +315,9 @@ public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -279,8 +328,9 @@ public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -291,8 +341,9 @@ public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -303,8 +354,9 @@ public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -315,8 +367,9 @@ public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { - return contentEqualsInternal(other) + return this.contentEquals(other) } /** @@ -327,7 +380,116 @@ public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentEquals(other: Array?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun IntArray?.contentEquals(other: IntArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun LongArray?.contentEquals(other: LongArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean { + return contentEqualsInternal(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun CharArray?.contentEquals(other: CharArray?): Boolean { return contentEqualsInternal(other) } @@ -335,71 +497,152 @@ public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ByteArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ShortArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun IntArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun LongArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun FloatArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun DoubleArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun BooleanArray.contentHashCode(): Int { - return contentHashCodeInternal() + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun CharArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentHashCode(): Int { + return contentHashCodeInternal() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentHashCode(): Int { return contentHashCodeInternal() } @@ -409,8 +652,9 @@ public actual fun CharArray.contentHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -419,8 +663,9 @@ public actual fun Array.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ByteArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -429,8 +674,9 @@ public actual fun ByteArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ShortArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -439,8 +685,9 @@ public actual fun ShortArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun IntArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -449,8 +696,9 @@ public actual fun IntArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun LongArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -459,8 +707,9 @@ public actual fun LongArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun FloatArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -469,8 +718,9 @@ public actual fun FloatArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun DoubleArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -479,8 +729,9 @@ public actual fun DoubleArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun BooleanArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() } /** @@ -489,8 +740,99 @@ public actual fun BooleanArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun CharArray.contentToString(): String { - return joinToString(", ", "[", "]") + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" } /** diff --git a/libraries/stdlib/js-v1/src/js/arrayUtils.js b/libraries/stdlib/js-v1/src/js/arrayUtils.js index 2ed84d20c8d..9774c8fd3d1 100644 --- a/libraries/stdlib/js-v1/src/js/arrayUtils.js +++ b/libraries/stdlib/js-v1/src/js/arrayUtils.js @@ -44,6 +44,7 @@ Kotlin.isArrayish = function (a) { }; Kotlin.arrayToString = function (a) { + if (a === null) return "null" var toString = Kotlin.isCharArray(a) ? String.fromCharCode : Kotlin.toString; return "[" + Array.prototype.map.call(a, function(e) { return toString(e); }).join(", ") + "]"; }; @@ -56,7 +57,7 @@ Kotlin.arrayEquals = function (a, b) { if (a === b) { return true; } - if (!Kotlin.isArrayish(b) || a.length !== b.length) { + if (a === null || b === null || !Kotlin.isArrayish(b) || a.length !== b.length) { return false; } @@ -73,6 +74,7 @@ Kotlin.arrayDeepEquals = function (a, b) { }; Kotlin.arrayHashCode = function (arr) { + if (arr === null) return 0 var result = 1; for (var i = 0, n = arr.length; i < n; i++) { result = ((31 * result | 0) + Kotlin.hashCode(arr[i])) | 0; diff --git a/libraries/stdlib/js/src/generated/_ArraysJs.kt b/libraries/stdlib/js/src/generated/_ArraysJs.kt index f3d39818672..78219c43130 100644 --- a/libraries/stdlib/js/src/generated/_ArraysJs.kt +++ b/libraries/stdlib/js/src/generated/_ArraysJs.kt @@ -194,8 +194,26 @@ public actual fun CharArray.asList(): List { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayDeepEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun Array.contentDeepEquals(other: Array): Boolean { + return this.contentDeepEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayDeepEquals") +public actual infix fun Array?.contentDeepEquals(other: Array?): Boolean { definedExternally } @@ -206,8 +224,20 @@ public actual infix fun Array.contentDeepEquals(other: Array): * If any of arrays contains itself on any nesting level the behavior is undefined. */ @SinceKotlin("1.1") -@library("arrayDeepHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentDeepHashCode(): Int { + return this.contentDeepHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +@library("arrayDeepHashCode") +public actual fun Array?.contentDeepHashCode(): Int { definedExternally } @@ -221,8 +251,23 @@ public actual fun Array.contentDeepHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentDeepToString */ @SinceKotlin("1.1") -@library("arrayDeepToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentDeepToString(): String { + return this.contentDeepToString() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +@library("arrayDeepToString") +public actual fun Array?.contentDeepToString(): String { definedExternally } @@ -234,9 +279,9 @@ public actual fun Array.contentDeepToString(): String { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun Array.contentEquals(other: Array): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -247,9 +292,9 @@ public actual infix fun Array.contentEquals(other: Array): Boo * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -260,9 +305,9 @@ public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -273,9 +318,9 @@ public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -286,9 +331,9 @@ public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -299,9 +344,9 @@ public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -312,9 +357,9 @@ public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -325,9 +370,9 @@ public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { - definedExternally + return this.contentEquals(other) } /** @@ -338,8 +383,125 @@ public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") -@library("arrayEquals") +@kotlin.internal.LowPriorityInOverloadResolution public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun Array?.contentEquals(other: Array?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun IntArray?.contentEquals(other: IntArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun LongArray?.contentEquals(other: LongArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean { + definedExternally +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@library("arrayEquals") +public actual infix fun CharArray?.contentEquals(other: CharArray?): Boolean { definedExternally } @@ -347,80 +509,161 @@ public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ByteArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ShortArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun IntArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun LongArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun FloatArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun DoubleArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun BooleanArray.contentHashCode(): Int { - definedExternally + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") -@library("arrayHashCode") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun CharArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun Array?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun ByteArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun ShortArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun IntArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun LongArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun FloatArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun DoubleArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun BooleanArray?.contentHashCode(): Int { + definedExternally +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@library("arrayHashCode") +public actual fun CharArray?.contentHashCode(): Int { definedExternally } @@ -430,9 +673,9 @@ public actual fun CharArray.contentHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun Array.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -441,9 +684,9 @@ public actual fun Array.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ByteArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -452,9 +695,9 @@ public actual fun ByteArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun ShortArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -463,9 +706,9 @@ public actual fun ShortArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun IntArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -474,9 +717,9 @@ public actual fun IntArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun LongArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -485,9 +728,9 @@ public actual fun LongArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun FloatArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -496,9 +739,9 @@ public actual fun FloatArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun DoubleArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -507,9 +750,9 @@ public actual fun DoubleArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun BooleanArray.contentToString(): String { - definedExternally + return this.contentToString() } /** @@ -518,8 +761,107 @@ public actual fun BooleanArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") -@library("arrayToString") +@kotlin.internal.LowPriorityInOverloadResolution public actual fun CharArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun Array?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun ByteArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun ShortArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun IntArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun LongArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun FloatArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun DoubleArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun BooleanArray?.contentToString(): String { + definedExternally +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@library("arrayToString") +public actual fun CharArray?.contentToString(): String { definedExternally } diff --git a/libraries/stdlib/js/src/kotlin/collections/ArraysJs.kt b/libraries/stdlib/js/src/kotlin/collections/ArraysJs.kt index 82472e736be..2cd9afe3c4f 100644 --- a/libraries/stdlib/js/src/kotlin/collections/ArraysJs.kt +++ b/libraries/stdlib/js/src/kotlin/collections/ArraysJs.kt @@ -9,7 +9,8 @@ package kotlin.collections @OptIn(ExperimentalUnsignedTypes::class) @SinceKotlin("1.3") @kotlin.js.JsName("contentDeepHashCodeImpl") -internal fun Array.contentDeepHashCodeImpl(): Int { +internal fun Array?.contentDeepHashCodeImpl(): Int { + if (this == null) return 0 var result = 1 for (element in this) { val elementHash = when { diff --git a/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt b/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt index fb15638ca7f..3e8cc0404cd 100644 --- a/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt +++ b/libraries/stdlib/jvm/src/generated/_ArraysJvm.kt @@ -387,9 +387,29 @@ public fun CharArray.binarySearch(element: Char, fromIndex: Int = 0, toIndex: In * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @JvmName("contentDeepEqualsInline") @kotlin.internal.InlineOnly public actual inline infix fun Array.contentDeepEquals(other: Array): Boolean { + return this.contentDeepEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentDeepEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun Array?.contentDeepEquals(other: Array?): Boolean { if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) return contentDeepEqualsImpl(other) else @@ -403,9 +423,23 @@ public actual inline infix fun Array.contentDeepEquals(other: Array Array.contentDeepHashCode(): Int { + return this.contentDeepHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +@JvmName("contentDeepHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun Array?.contentDeepHashCode(): Int { if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) return contentDeepHashCodeImpl() else @@ -422,9 +456,26 @@ public actual inline fun Array.contentDeepHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentDeepToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @JvmName("contentDeepToStringInline") @kotlin.internal.InlineOnly public actual inline fun Array.contentDeepToString(): String { + return this.contentDeepToString() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +@JvmName("contentDeepToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun Array?.contentDeepToString(): String { if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) return contentDeepToStringImpl() else @@ -439,9 +490,10 @@ public actual inline fun Array.contentDeepToString(): String { * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline infix fun Array.contentEquals(other: Array): Boolean { - return java.util.Arrays.equals(this, other) + return this.contentEquals(other) } /** @@ -452,9 +504,10 @@ public actual inline infix fun Array.contentEquals(other: Array Array?.contentEquals(other: Array?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun IntArray?.contentEquals(other: IntArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun LongArray?.contentEquals(other: LongArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean { + return java.util.Arrays.equals(this, other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +@JvmName("contentEqualsNullable") +@kotlin.internal.InlineOnly +public actual inline infix fun CharArray?.contentEquals(other: CharArray?): Boolean { return java.util.Arrays.equals(this, other) } @@ -552,80 +738,179 @@ public actual inline infix fun CharArray.contentEquals(other: CharArray): Boolea * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun Array.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun ByteArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun ShortArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun IntArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun LongArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun FloatArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun DoubleArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun BooleanArray.contentHashCode(): Int { - return java.util.Arrays.hashCode(this) + return this.contentHashCode() } /** * Returns a hash code based on the contents of this array as if it is [List]. */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun CharArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun Array?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun ByteArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun ShortArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun IntArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun LongArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun FloatArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray?.contentHashCode(): Int { + return java.util.Arrays.hashCode(this) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +@JvmName("contentHashCodeNullable") +@kotlin.internal.InlineOnly +public actual inline fun CharArray?.contentHashCode(): Int { return java.util.Arrays.hashCode(this) } @@ -635,9 +920,10 @@ public actual inline fun CharArray.contentHashCode(): Int { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun Array.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -646,9 +932,10 @@ public actual inline fun Array.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun ByteArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -657,9 +944,10 @@ public actual inline fun ByteArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun ShortArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -668,9 +956,10 @@ public actual inline fun ShortArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun IntArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -679,9 +968,10 @@ public actual inline fun IntArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun LongArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -690,9 +980,10 @@ public actual inline fun LongArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun FloatArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -701,9 +992,10 @@ public actual inline fun FloatArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun DoubleArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -712,9 +1004,10 @@ public actual inline fun DoubleArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun BooleanArray.contentToString(): String { - return java.util.Arrays.toString(this) + return this.contentToString() } /** @@ -723,8 +1016,117 @@ public actual inline fun BooleanArray.contentToString(): String { * @sample samples.collections.Arrays.ContentOperations.contentToString */ @SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution @kotlin.internal.InlineOnly public actual inline fun CharArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun Array?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun ByteArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun ShortArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun IntArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun LongArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun FloatArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray?.contentToString(): String { + return java.util.Arrays.toString(this) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +@JvmName("contentToStringNullable") +@kotlin.internal.InlineOnly +public actual inline fun CharArray?.contentToString(): String { return java.util.Arrays.toString(this) } diff --git a/libraries/stdlib/jvm/src/kotlin/collections/ArraysJVM.kt b/libraries/stdlib/jvm/src/kotlin/collections/ArraysJVM.kt index 68487fd2695..afd3bf2d929 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/ArraysJVM.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/ArraysJVM.kt @@ -53,7 +53,7 @@ internal fun copyOfRangeToIndexCheck(toIndex: Int, size: Int) { @SinceKotlin("1.3") @PublishedApi @kotlin.jvm.JvmName("contentDeepHashCode") -internal fun Array.contentDeepHashCodeImpl(): Int = +internal fun Array?.contentDeepHashCodeImpl(): Int = // returns valid result for unsigned arrays by accident: // hash code of an inline class, which an unsigned array is, // is calculated structurally as in a data class diff --git a/libraries/stdlib/jvm/test/collections/ArraysJVMTest.kt b/libraries/stdlib/jvm/test/collections/ArraysJVMTest.kt new file mode 100644 index 00000000000..8b3506cfd7b --- /dev/null +++ b/libraries/stdlib/jvm/test/collections/ArraysJVMTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package test.collections + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue +import java.util.Collections + + +class ArraysJVMTest { + + @Suppress("HasPlatformType", "UNCHECKED_CAST") + fun platformNull() = Collections.singletonList(null as T).first() + + @Test + fun contentEquals() { + assertTrue(platformNull() contentEquals null) + assertTrue(null contentEquals platformNull()) + + assertFalse(platformNull>() contentEquals emptyArray()) + assertFalse(arrayOf("a", "b") contentEquals platformNull>()) + + assertFalse(platformNull() contentEquals ushortArrayOf()) + assertFalse(ubyteArrayOf() contentEquals platformNull()) + } + + @Test + fun contentHashCode() { + assertEquals(0, platformNull>().contentHashCode()) + assertEquals(0, platformNull().contentHashCode()) + assertEquals(0, platformNull().contentHashCode()) + assertEquals(0, platformNull().contentHashCode()) + assertEquals(0, platformNull().contentHashCode()) + assertEquals(0, platformNull().contentHashCode()) + } + + @Test + fun contentToString() { + assertEquals("null", platformNull>().contentToString()) + assertEquals("null", platformNull().contentToString()) + assertEquals("null", platformNull().contentToString()) + assertEquals("null", platformNull().contentToString()) + assertEquals("null", platformNull().contentToString()) + } + + @Test + fun contentDeepEquals() { + assertFalse(platformNull>() contentDeepEquals emptyArray()) + assertFalse(arrayOf("a", "b") contentDeepEquals platformNull>()) + } + + @Test + fun contentDeepHashCode() { + assertEquals(0, platformNull>().contentDeepHashCode()) + } + + @Test + fun contentDeepToString() { + assertEquals("null", platformNull>().contentDeepToString()) + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/collections/Arrays.kt b/libraries/stdlib/src/kotlin/collections/Arrays.kt index af5b48ddf43..fe2e6bd2a93 100644 --- a/libraries/stdlib/src/kotlin/collections/Arrays.kt +++ b/libraries/stdlib/src/kotlin/collections/Arrays.kt @@ -72,9 +72,9 @@ public inline fun C.ifEmpty(defaultValue: () -> R): R where C : Array<*>, @PublishedApi @kotlin.jvm.JvmName("contentDeepEquals") @kotlin.js.JsName("contentDeepEqualsImpl") -internal fun Array.contentDeepEqualsImpl(other: Array): Boolean { +internal fun Array?.contentDeepEqualsImpl(other: Array?): Boolean { if (this === other) return true - if (this.size != other.size) return false + if (this == null || other == null || this.size != other.size) return false for (i in indices) { val v1 = this[i] @@ -113,7 +113,8 @@ internal fun Array.contentDeepEqualsImpl(other: Array): Boolea @PublishedApi @kotlin.jvm.JvmName("contentDeepToString") @kotlin.js.JsName("contentDeepToStringImpl") -internal fun Array.contentDeepToStringImpl(): String { +internal fun Array?.contentDeepToStringImpl(): String { + if (this == null) return "null" val length = size.coerceAtMost((Int.MAX_VALUE - 2) / 5) * 5 + 2 // in order not to overflow Int.MAX_VALUE return buildString(length) { contentDeepToStringInternal(this, mutableListOf()) diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index b7618a60998..797dba40d9c 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -220,6 +220,11 @@ class ArraysTest { checkArray(longArrayOf(1, 2, 3), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { reverse() }) checkArray(doubleArrayOf(Double.NaN, -0.0, 0.0, Double.POSITIVE_INFINITY, 1.0), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { this[1] = 0.0 }) + + assertTrue((null as BooleanArray?) contentEquals null) + assertFalse(null contentEquals shortArrayOf(1)) + assertFalse((emptyArray() as Array?) contentEquals null) + assertFalse(null.contentEquals(arrayOf("0", null))) } @Test fun contentDeepEquals() { @@ -245,6 +250,11 @@ class ArraysTest { arr5[0][0] = 0.0 assertTrue(arr5 contentDeepEquals arr6) + + assertTrue((null as Array?) contentDeepEquals null) + assertTrue(null contentDeepEquals (null as Array?)) + assertFalse(arrayOf("") contentDeepEquals null) + assertFalse(null contentDeepEquals arrayOf(null)) } @Test fun contentToString() { @@ -253,6 +263,8 @@ class ArraysTest { intArrayOf(1, 10, 42).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } longArrayOf(1L, 5L, Long.MAX_VALUE).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } doubleArrayOf(0.0, Double.MAX_VALUE, Double.POSITIVE_INFINITY, Double.NaN).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } + + (null as ByteArray?).let { arr -> assertEquals(arr?.asList().toString(), arr.contentToString()) } } @Test fun contentDeepToString() { @@ -263,6 +275,8 @@ class ArraysTest { doubleArrayOf(3.14), floatArrayOf(1.25f) ) assertEquals("[aa, 1, null, [[foo]], [d], [false], [-1], [-1], [-1], [-1], [4294967295], [18446744073709551615], [65535], [255], [3.14], [1.25]]", arr.contentDeepToString()) + + assertEquals("null", (null as Array?).contentDeepToString()) } @Test fun contentDeepToStringNoRecursion() { @@ -290,6 +304,8 @@ class ArraysTest { charArrayOf('a', Char.MAX_VALUE, Char.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } doubleArrayOf(1.0, -0.0, 0.0, Double.NaN, Double.POSITIVE_INFINITY).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } floatArrayOf(1.0f, -0.0f, 0.0f, Float.NaN, Float.POSITIVE_INFINITY).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } + + (null as IntArray?).let { assertEquals(it?.toList().hashCode(), it.contentHashCode()) } } @Test fun contentDeepHashCode() { @@ -310,6 +326,8 @@ class ArraysTest { val uintList2 = listOf(listOf(1u, 2u), listOf(3u, 4u)) assertEquals(uintList2.hashCode(), uintArray2.contentDeepHashCode()) + + assertEquals(0, (null as Array?).contentDeepHashCode()) } diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt index bb4c254f9eb..d0874ca0002 100644 --- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt +++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt @@ -86,6 +86,8 @@ class UnsignedArraysTest { uintArrayOf(1u, UInt.MAX_VALUE, UInt.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } ushortArrayOf(1u, UShort.MAX_VALUE, UShort.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } ubyteArrayOf(1u, UByte.MAX_VALUE, UByte.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } + + (null as ULongArray?).let { assertEquals(it?.toList().hashCode(), it.contentHashCode()) } } @Test @@ -94,6 +96,8 @@ class UnsignedArraysTest { uintArrayOf(1u, UInt.MAX_VALUE, UInt.MIN_VALUE).let { assertEquals(it.toList().toString(), it.contentToString()) } ushortArrayOf(1u, UShort.MAX_VALUE, UShort.MIN_VALUE).let { assertEquals(it.toList().toString(), it.contentToString()) } ubyteArrayOf(1u, UByte.MAX_VALUE, UByte.MIN_VALUE).let { assertEquals(it.toList().toString(), it.contentToString()) } + + (null as UIntArray?).let { assertEquals(it?.toList().toString(), it.contentToString()) } } @Test @@ -114,6 +118,10 @@ class UnsignedArraysTest { assertTrue(arr contentEquals UByteArray(arr.size, arr::get)) assertFalse(arr contentEquals UByteArray(arr.size - 1, arr::get)) } + + assertTrue((null as UShortArray?) contentEquals null) + assertFalse(null contentEquals ubyteArrayOf(1u)) + assertFalse(ulongArrayOf() contentEquals null) } @Test diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index c3983ac8d11..9aa01a89ca9 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -2439,18 +2439,30 @@ public final class kotlin/collections/unsigned/UArraysKt { public static synthetic fun binarySearch-K6DWlUc$default ([JJIIILjava/lang/Object;)I public static final fun binarySearch-WpHrYlw ([BBII)I public static synthetic fun binarySearch-WpHrYlw$default ([BBIIILjava/lang/Object;)I + public static final fun contentEquals-FGO6Aew ([S[S)Z + public static final fun contentEquals-KJPZfPQ ([I[I)Z public static final fun contentEquals-ctEhBpI ([I[I)Z + public static final fun contentEquals-kV0jMPg ([B[B)Z public static final fun contentEquals-kdPth3s ([B[B)Z + public static final fun contentEquals-lec5QzE ([J[J)Z public static final fun contentEquals-mazbYpA ([S[S)Z public static final fun contentEquals-us8wMrg ([J[J)Z public static final fun contentHashCode--ajY-9A ([I)I + public static final fun contentHashCode-2csIQuQ ([B)I public static final fun contentHashCode-GBYM_sE ([B)I public static final fun contentHashCode-QwZRm1k ([J)I + public static final fun contentHashCode-XUkPCBk ([I)I + public static final fun contentHashCode-d-6D3K8 ([S)I public static final fun contentHashCode-rL5Bavg ([S)I + public static final fun contentHashCode-uLth9ew ([J)I public static final fun contentToString--ajY-9A ([I)Ljava/lang/String; + public static final fun contentToString-2csIQuQ ([B)Ljava/lang/String; public static final fun contentToString-GBYM_sE ([B)Ljava/lang/String; public static final fun contentToString-QwZRm1k ([J)Ljava/lang/String; + public static final fun contentToString-XUkPCBk ([I)Ljava/lang/String; + public static final fun contentToString-d-6D3K8 ([S)Ljava/lang/String; public static final fun contentToString-rL5Bavg ([S)Ljava/lang/String; + public static final fun contentToString-uLth9ew ([J)Ljava/lang/String; public static final fun drop-PpDY95g ([BI)Ljava/util/List; public static final fun drop-nggk6HY ([SI)Ljava/util/List; public static final fun drop-qFRl0hI ([II)Ljava/util/List; diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index 9b5602daa7d..225ae229d23 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -85,6 +85,7 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") infix(true) doc { """ @@ -93,8 +94,8 @@ object ArrayOps : TemplateGroupBase() { """ } returns("Boolean") - if (family == ArraysOfUnsigned) { - body { "return storage.contentEquals(other.storage)" } + body { "return this.contentEquals(other)" } + if (f == ArraysOfUnsigned) { return@builder } doc { @@ -105,6 +106,36 @@ object ArrayOps : TemplateGroupBase() { } on(Platform.JVM) { inlineOnly() + } + } + + val f_contentEquals_nullable = fn("contentEquals(other: SELF?)") { + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) + } builder { + since("1.4") + infix(true) + doc { + """ + Returns `true` if the two specified arrays are *structurally* equal to one another, + i.e. contain the same number of the same elements in the same order. + """ + } + receiver("SELF?") + returns("Boolean") + if (family == ArraysOfUnsigned) { + body { "return this?.storage.contentEquals(other?.storage)" } + return@builder + } + + doc { + doc + """ + The elements are compared for equality with the [equals][Any.equals] function. + For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + """ + } + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentEqualsNullable")""") body { "return java.util.Arrays.equals(this, other)" } } @@ -126,6 +157,7 @@ object ArrayOps : TemplateGroupBase() { body { """ if (this === other) return true + if (this === null || other === null) return false if (size != other.size) return false for (i in indices) { if (${notEq("this[i]", "other[i]")}) return false @@ -140,6 +172,7 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") infix(true) doc { """ @@ -154,9 +187,37 @@ object ArrayOps : TemplateGroupBase() { """ } returns("Boolean") + body { "return this.contentDeepEquals(other)" } on(Platform.JVM) { inlineOnly() annotation("""@JvmName("contentDeepEqualsInline")""") + } + } + + val f_contentDeepEquals_nullable = fn("contentDeepEquals(other: SELF?)") { + include(ArraysOfObjects) + } builder { + since("1.4") + infix(true) + doc { + """ + Returns `true` if the two specified arrays are *deeply* equal to one another, + i.e. contain the same number of the same elements in the same order. + + The specified arrays are also considered deeply equal if both are `null`. + + If two corresponding elements are nested arrays, they are also compared deeply. + If any of arrays contains itself on any nesting level the behavior is undefined. + + The elements of other types are compared for equality with the [equals][Any.equals] function. + For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + """ + } + receiver("SELF?") + returns("Boolean") + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentDeepEqualsNullable")""") body { """ if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) @@ -185,6 +246,7 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") doc { """ Returns a string representation of the contents of the specified array as if it is [List]. @@ -192,12 +254,35 @@ object ArrayOps : TemplateGroupBase() { } sample("samples.collections.Arrays.ContentOperations.contentToString") returns("String") - if (family == ArraysOfUnsigned) { - body { """return joinToString(", ", "[", "]")""" } + body { "return this.contentToString()" } + if (f == ArraysOfUnsigned) { return@builder } on(Platform.JVM) { inlineOnly() + } + } + + val f_contentToString_nullable = fn("contentToString()") { + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) + } builder { + since("1.4") + doc { + """ + Returns a string representation of the contents of the specified array as if it is [List]. + """ + } + sample("samples.collections.Arrays.ContentOperations.contentToString") + receiver("SELF?") + returns("String") + if (family == ArraysOfUnsigned) { + body { """return this?.joinToString(", ", "[", "]") ?: "null"""" } + return@builder + } + + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentToStringNullable")""") body { "return java.util.Arrays.toString(this)" } } on(Platform.JS) { @@ -206,11 +291,11 @@ object ArrayOps : TemplateGroupBase() { body { "definedExternally" } } on(Backend.IR) { - body { """return joinToString(", ", "[", "]")""" } + body { """return this?.joinToString(", ", "[", "]") ?: "null"""" } } } on(Platform.Native) { - body { """return joinToString(", ", "[", "]")""" } + body { """return this?.joinToString(", ", "[", "]") ?: "null"""" } } } @@ -218,6 +303,7 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") doc { """ Returns a string representation of the contents of this array as if it is a [List]. @@ -229,9 +315,32 @@ object ArrayOps : TemplateGroupBase() { } sample("samples.collections.Arrays.ContentOperations.contentDeepToString") returns("String") + body { "return this.contentDeepToString()" } on(Platform.JVM) { inlineOnly() annotation("""@JvmName("contentDeepToStringInline")""") + } + } + + val f_contentDeepToString_nullable = fn("contentDeepToString()") { + include(ArraysOfObjects) + } builder { + since("1.4") + doc { + """ + Returns a string representation of the contents of this array as if it is a [List]. + Nested arrays are treated as lists too. + + If any of arrays contains itself on any nesting level that reference + is rendered as `"[...]"` to prevent recursion. + """ + } + sample("samples.collections.Arrays.ContentOperations.contentDeepToString") + receiver("SELF?") + returns("String") + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentDeepToStringNullable")""") body { """ if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) @@ -259,16 +368,37 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") doc { "Returns a hash code based on the contents of this array as if it is [List]." } returns("Int") - if (family == ArraysOfUnsigned) { - body { "return storage.contentHashCode()" } + body { "return this.contentHashCode()" } + if (f == ArraysOfUnsigned) { return@builder } on(Platform.JVM) { inlineOnly() + } + } + + val f_contentHashCode_nullable = fn("contentHashCode()") { + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) + } builder { + since("1.4") + doc { + "Returns a hash code based on the contents of this array as if it is [List]." + } + receiver("SELF?") + returns("Int") + if (family == ArraysOfUnsigned) { + body { "return this?.storage.contentHashCode()" } + return@builder + } + + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentHashCodeNullable")""") body { "return java.util.Arrays.hashCode(this)" } } on(Platform.JS) { @@ -283,6 +413,7 @@ object ArrayOps : TemplateGroupBase() { on(Platform.Native) { body { """ + if (this === null) return 0 var result = 1 for (element in this) result = 31 * result + element.hashCode() @@ -296,6 +427,7 @@ object ArrayOps : TemplateGroupBase() { include(ArraysOfObjects) } builder { since("1.1") + annotation("@kotlin.internal.LowPriorityInOverloadResolution") doc { """ Returns a hash code based on the contents of this array as if it is [List]. @@ -305,9 +437,30 @@ object ArrayOps : TemplateGroupBase() { """ } returns("Int") + body { "return this.contentDeepHashCode()" } on(Platform.JVM) { inlineOnly() annotation("""@JvmName("contentDeepHashCodeInline")""") + } + } + + val f_contentDeepHashCode_nullable = fn("contentDeepHashCode()") { + include(ArraysOfObjects) + } builder { + since("1.4") + doc { + """ + Returns a hash code based on the contents of this array as if it is [List]. + Nested arrays are treated as lists too. + + If any of arrays contains itself on any nesting level the behavior is undefined. + """ + } + receiver("SELF?") + returns("Int") + on(Platform.JVM) { + inlineOnly() + annotation("""@JvmName("contentDeepHashCodeNullable")""") body { """ if (kotlin.internal.apiVersionIsAtLeast(1, 3, 0)) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/TypeParameterParsers.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/TypeParameterParsers.kt index 5b02e708547..c1ed49d25c1 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/TypeParameterParsers.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/TypeParameterParsers.kt @@ -33,8 +33,8 @@ fun parseTypeParameter(typeString: String): TypeParameter = fun parseTypeRef(typeRef: String): TypeRef = typeRef.trim().run { - if (contains('<') && endsWith('>')) { - val name = substringBefore('<') + if (contains('<') && (endsWith('>') || endsWith(">?"))) { + val name = substringBefore('<') + if (endsWith(">?")) "?" else "" val params = substringAfter('<').substringBeforeLast('>') TypeRef(name, parseArguments(params)) }