From f8fe3e6c1d41edcce17eaaa7d903822f1f8d4ce9 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Sun, 29 Nov 2015 04:27:14 +0300 Subject: [PATCH] Restore dropped hidden declarations for binary compatibility until RC. --- .../gotoSymbol/stdLibJoinToString.kt | 11 + libraries/stdlib/src/generated/_Arrays.kt | 90 +++ .../stdlib/src/generated/_Collections.kt | 10 + libraries/stdlib/src/generated/_Ranges.kt | 163 +++++ libraries/stdlib/src/generated/_Sequences.kt | 10 + libraries/stdlib/src/generated/_Strings.kt | 668 ++++++++++++++++++ .../stdlib/src/kotlin/collections/MapsJVM.kt | 4 + .../src/kotlin/text/StringsDeprecated.kt | 577 +++++++++++++++ .../src/kotlin/text/StringsDeprecatedJVM.kt | 182 +++++ .../src/templates/Aggregates.kt | 57 +- .../src/templates/Comparables.kt | 21 + .../src/templates/Elements.kt | 69 +- .../src/templates/Filtering.kt | 6 +- .../src/templates/Generators.kt | 6 +- .../src/templates/Mapping.kt | 27 +- .../kotlin-stdlib-gen/src/templates/Ranges.kt | 92 ++- .../src/templates/Sequence.kt | 3 +- .../src/templates/Snapshots.kt | 28 +- .../src/templates/Strings.kt | 21 + 19 files changed, 1975 insertions(+), 70 deletions(-) create mode 100644 libraries/stdlib/src/kotlin/text/StringsDeprecated.kt create mode 100644 libraries/stdlib/src/kotlin/text/StringsDeprecatedJVM.kt diff --git a/idea/testData/navigation/gotoSymbol/stdLibJoinToString.kt b/idea/testData/navigation/gotoSymbol/stdLibJoinToString.kt index e8c14e3bda8..ca6f86b67b2 100644 --- a/idea/testData/navigation/gotoSymbol/stdLibJoinToString.kt +++ b/idea/testData/navigation/gotoSymbol/stdLibJoinToString.kt @@ -2,13 +2,24 @@ // CHECK_BOX // SEARCH_TEXT: joinToString // REF: (for Array in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((T) -> CharSequence)?) +// REF: (for Array in kotlin).joinToString(String, String, String, Int, String, ((T) -> String)?) // REF: (for BooleanArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Boolean) -> CharSequence)?) +// REF: (for BooleanArray in kotlin).joinToString(String, String, String, Int, String, ((Boolean) -> String)?) // REF: (for ByteArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Byte) -> CharSequence)?) +// REF: (for ByteArray in kotlin).joinToString(String, String, String, Int, String, ((Byte) -> String)?) // REF: (for CharArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Char) -> CharSequence)?) +// REF: (for CharArray in kotlin).joinToString(String, String, String, Int, String, ((Char) -> String)?) // REF: (for DoubleArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Double) -> CharSequence)?) +// REF: (for DoubleArray in kotlin).joinToString(String, String, String, Int, String, ((Double) -> String)?) // REF: (for FloatArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Float) -> CharSequence)?) +// REF: (for FloatArray in kotlin).joinToString(String, String, String, Int, String, ((Float) -> String)?) // REF: (for IntArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Int) -> CharSequence)?) +// REF: (for IntArray in kotlin).joinToString(String, String, String, Int, String, ((Int) -> String)?) // REF: (for Iterable in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((T) -> CharSequence)?) +// REF: (for Iterable in kotlin).joinToString(String, String, String, Int, String, ((T) -> String)?) // REF: (for LongArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Long) -> CharSequence)?) +// REF: (for LongArray in kotlin).joinToString(String, String, String, Int, String, ((Long) -> String)?) // REF: (for Sequence in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((T) -> CharSequence)?) +// REF: (for Sequence in kotlin).joinToString(String, String, String, Int, String, ((T) -> String)?) // REF: (for ShortArray in kotlin).joinToString(CharSequence, CharSequence, CharSequence, Int, CharSequence, ((Short) -> CharSequence)?) +// REF: (for ShortArray in kotlin).joinToString(String, String, String, Int, String, ((Short) -> String)?) \ No newline at end of file diff --git a/libraries/stdlib/src/generated/_Arrays.kt b/libraries/stdlib/src/generated/_Arrays.kt index 76363a716c6..eb692f652c8 100644 --- a/libraries/stdlib/src/generated/_Arrays.kt +++ b/libraries/stdlib/src/generated/_Arrays.kt @@ -10253,6 +10253,51 @@ public fun ShortArray.joinTo(buffer: A, separator: CharSequence return buffer } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Array.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun BooleanArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Boolean) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun ByteArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Byte) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun CharArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Char) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun DoubleArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Double) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun FloatArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Float) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun IntArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Int) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun LongArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Long) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun ShortArray.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Short) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + /** * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] @@ -10334,6 +10379,51 @@ public fun ShortArray.joinToString(separator: CharSequence = ", ", prefix: CharS return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Array.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun BooleanArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Boolean) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun ByteArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Byte) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun CharArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Char) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun DoubleArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Double) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun FloatArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Float) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun IntArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Int) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun LongArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Long) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun ShortArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Short) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + /** * Returns a sequence from the given collection. */ diff --git a/libraries/stdlib/src/generated/_Collections.kt b/libraries/stdlib/src/generated/_Collections.kt index 4b84788adae..271e4417b26 100644 --- a/libraries/stdlib/src/generated/_Collections.kt +++ b/libraries/stdlib/src/generated/_Collections.kt @@ -1734,6 +1734,11 @@ public fun Iterable.joinTo(buffer: A, separator: CharSequ return buffer } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Iterable.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + /** * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] @@ -1743,6 +1748,11 @@ public fun Iterable.joinToString(separator: CharSequence = ", ", prefix: return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Iterable.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + /** * Returns a sequence from the given collection. */ diff --git a/libraries/stdlib/src/generated/_Ranges.kt b/libraries/stdlib/src/generated/_Ranges.kt index 8725ec32105..6c21ed33e06 100644 --- a/libraries/stdlib/src/generated/_Ranges.kt +++ b/libraries/stdlib/src/generated/_Ranges.kt @@ -12,6 +12,60 @@ import java.util.* import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("downTo") kotlin.jvm.JvmVersion] +public fun Byte.`-downTo`(to: Byte): ByteProgression { + return ByteProgression.fromClosedRange(this, to, -1) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("downTo") kotlin.jvm.JvmVersion] +public fun Short.`-downTo`(to: Byte): ShortProgression { + return ShortProgression.fromClosedRange(this, to.toShort(), -1) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("downTo") kotlin.jvm.JvmVersion] +public fun Byte.`-downTo`(to: Short): ShortProgression { + return ShortProgression.fromClosedRange(this.toShort(), to, -1) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("downTo") kotlin.jvm.JvmVersion] +public fun Short.`-downTo`(to: Short): ShortProgression { + return ShortProgression.fromClosedRange(this, to, -1) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("until") kotlin.jvm.JvmVersion] +public fun Byte.`-until`(to: Byte): ByteRange { + val to_ = (to - 1).toByte() + if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") + return ByteRange(this, to_) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("until") kotlin.jvm.JvmVersion] +public fun Short.`-until`(to: Byte): ShortRange { + return ShortRange(this, (to.toShort() - 1).toShort()) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("until") kotlin.jvm.JvmVersion] +public fun Byte.`-until`(to: Short): ShortRange { + val to_ = (to - 1).toShort() + if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") + return ShortRange(this.toShort(), to_) +} + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@[kotlin.jvm.JvmName("until") kotlin.jvm.JvmVersion] +public fun Short.`-until`(to: Short): ShortRange { + val to_ = (to - 1).toShort() + if (to_ > to) throw IllegalArgumentException("The to argument value '$to' was too small.") + return ShortRange(this, to_) +} + /** * Checks if the specified [item] belongs to this range. */ @@ -679,6 +733,30 @@ public fun LongProgression.reversed(): LongProgression { return LongProgression.fromClosedRange(last, first, -increment) } +/** + * Returns a progression that goes over this range in reverse direction. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun CharRange.reversed(): CharProgression { + return CharProgression.fromClosedRange(last, first, -1) +} + +/** + * Returns a progression that goes over this range in reverse direction. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun IntRange.reversed(): IntProgression { + return IntProgression.fromClosedRange(last, first, -1) +} + +/** + * Returns a progression that goes over this range in reverse direction. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun LongRange.reversed(): LongProgression { + return LongProgression.fromClosedRange(last, first, -1L) +} + /** * Returns a progression that goes over the same range in the opposite direction with the same step. */ @@ -697,6 +775,24 @@ public fun ShortProgression.reversed(): ShortProgression { return ShortProgression.fromClosedRange(last, first, -increment) } +/** + * Returns a progression that goes over this range in reverse direction. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@Suppress("DEPRECATION_ERROR") +public fun ByteRange.reversed(): ByteProgression { + return ByteProgression.fromClosedRange(last, first, -1) +} + +/** + * Returns a progression that goes over this range in reverse direction. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@Suppress("DEPRECATION_ERROR") +public fun ShortRange.reversed(): ShortProgression { + return ShortProgression.fromClosedRange(last, first, -1) +} + /** * Returns a progression that goes over the same range with the given step. */ @@ -721,6 +817,33 @@ public infix fun LongProgression.step(step: Long): LongProgression { return LongProgression.fromClosedRange(first, last, if (increment > 0) step else -step) } +/** + * Returns a progression that goes over this range with given step. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public infix fun CharRange.step(step: Int): CharProgression { + checkStepIsPositive(step > 0, step) + return CharProgression.fromClosedRange(first, last, step) +} + +/** + * Returns a progression that goes over this range with given step. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public infix fun IntRange.step(step: Int): IntProgression { + checkStepIsPositive(step > 0, step) + return IntProgression.fromClosedRange(first, last, step) +} + +/** + * Returns a progression that goes over this range with given step. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public infix fun LongRange.step(step: Long): LongProgression { + checkStepIsPositive(step > 0, step) + return LongProgression.fromClosedRange(first, last, step) +} + /** * Returns a progression that goes over the same range with the given step. */ @@ -741,6 +864,26 @@ public infix fun ShortProgression.step(step: Int): ShortProgression { return ShortProgression.fromClosedRange(first, last, if (increment > 0) step else -step) } +/** + * Returns a progression that goes over this range with given step. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@Suppress("DEPRECATION_ERROR") +public infix fun ByteRange.step(step: Int): ByteProgression { + checkStepIsPositive(step > 0, step) + return ByteProgression.fromClosedRange(first, last, step) +} + +/** + * Returns a progression that goes over this range with given step. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@Suppress("DEPRECATION_ERROR") +public infix fun ShortRange.step(step: Int): ShortProgression { + checkStepIsPositive(step > 0, step) + return ShortProgression.fromClosedRange(first, last, step) +} + /** * Returns a range from this value up to but excluding the specified [to] value. */ @@ -1192,3 +1335,23 @@ public fun Short.coerceIn(range: Range): Short { return if (this < range.start) range.start else if (this > range.end) range.end else this } +/** + * Ensures that this value lies in the specified [range]. + * @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Double.coerceIn(range: Range): Double { + if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") + return if (this < range.start) range.start else if (this > range.end) range.end else this +} + +/** + * Ensures that this value lies in the specified [range]. + * @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Float.coerceIn(range: Range): Float { + if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") + return if (this < range.start) range.start else if (this > range.end) range.end else this +} + diff --git a/libraries/stdlib/src/generated/_Sequences.kt b/libraries/stdlib/src/generated/_Sequences.kt index 14e2b45f9d8..53d73e6db77 100644 --- a/libraries/stdlib/src/generated/_Sequences.kt +++ b/libraries/stdlib/src/generated/_Sequences.kt @@ -1048,6 +1048,11 @@ public fun Sequence.joinTo(buffer: A, separator: CharSequ return buffer } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Sequence.joinTo(buffer: A, separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): A { + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) +} + /** * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] @@ -1057,6 +1062,11 @@ public fun Sequence.joinToString(separator: CharSequence = ", ", prefix: return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun Sequence.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((T) -> String)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + /** * Returns a sequence from the given collection. */ diff --git a/libraries/stdlib/src/generated/_Strings.kt b/libraries/stdlib/src/generated/_Strings.kt index 8abe6511b88..5228f1b0f06 100644 --- a/libraries/stdlib/src/generated/_Strings.kt +++ b/libraries/stdlib/src/generated/_Strings.kt @@ -19,6 +19,14 @@ public fun CharSequence.elementAt(index: Int): Char { return get(index) } +/** + * Returns a character at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.elementAt(index: Int): Char { + return get(index) +} + /** * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this char sequence. */ @@ -26,6 +34,14 @@ public inline fun CharSequence.elementAtOrElse(index: Int, defaultValue: (Int) - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } +/** + * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { + return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +} + /** * Returns a character at the given [index] or `null` if the [index] is out of bounds of this char sequence. */ @@ -33,6 +49,14 @@ public fun CharSequence.elementAtOrNull(index: Int): Char? { return if (index >= 0 && index <= lastIndex) get(index) else null } +/** + * Returns a character at the given [index] or `null` if the [index] is out of bounds of this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.elementAtOrNull(index: Int): Char? { + return if (index >= 0 && index <= lastIndex) get(index) else null +} + /** * Returns the first character matching the given [predicate], or `null` if no such character was found. */ @@ -40,6 +64,14 @@ public inline fun CharSequence.find(predicate: (Char) -> Boolean): Char? { return firstOrNull(predicate) } +/** + * Returns the first character matching the given [predicate], or `null` if no such character was found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.find(predicate: (Char) -> Boolean): Char? { + return firstOrNull(predicate) +} + /** * Returns the last character matching the given [predicate], or `null` if no such character was found. */ @@ -47,6 +79,14 @@ public inline fun CharSequence.findLast(predicate: (Char) -> Boolean): Char? { return lastOrNull(predicate) } +/** + * Returns the last character matching the given [predicate], or `null` if no such character was found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.findLast(predicate: (Char) -> Boolean): Char? { + return lastOrNull(predicate) +} + /** * Returns first character. * @throws [NoSuchElementException] if the char sequence is empty. @@ -57,6 +97,17 @@ public fun CharSequence.first(): Char { return this[0] } +/** + * Returns first character. + * @throws [NoSuchElementException] if the string is empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.first(): Char { + if (isEmpty()) + throw NoSuchElementException("Collection is empty.") + return this[0] +} + /** * Returns the first character matching the given [predicate]. * @throws [NoSuchElementException] if no such character is found. @@ -66,6 +117,16 @@ public inline fun CharSequence.first(predicate: (Char) -> Boolean): Char { throw NoSuchElementException("No element matching predicate was found.") } +/** + * Returns the first character matching the given [predicate]. + * @throws [NoSuchElementException] if no such character is found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.first(predicate: (Char) -> Boolean): Char { + for (element in this) if (predicate(element)) return element + throw NoSuchElementException("No element matching predicate was found.") +} + /** * Returns the first character, or `null` if the char sequence is empty. */ @@ -73,6 +134,14 @@ public fun CharSequence.firstOrNull(): Char? { return if (isEmpty()) null else this[0] } +/** + * Returns the first character, or `null` if the string is empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.firstOrNull(): Char? { + return if (isEmpty()) null else this[0] +} + /** * Returns the first character matching the given [predicate], or `null` if character was not found. */ @@ -81,6 +150,15 @@ public inline fun CharSequence.firstOrNull(predicate: (Char) -> Boolean): Char? return null } +/** + * Returns the first character matching the given [predicate], or `null` if character was not found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.firstOrNull(predicate: (Char) -> Boolean): Char? { + for (element in this) if (predicate(element)) return element + return null +} + /** * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this char sequence. */ @@ -88,6 +166,14 @@ public inline fun CharSequence.getOrElse(index: Int, defaultValue: (Int) -> Char return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) } +/** + * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.getOrElse(index: Int, defaultValue: (Int) -> Char): Char { + return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +} + /** * Returns a character at the given [index] or `null` if the [index] is out of bounds of this char sequence. */ @@ -95,6 +181,14 @@ public fun CharSequence.getOrNull(index: Int): Char? { return if (index >= 0 && index <= lastIndex) get(index) else null } +/** + * Returns a character at the given [index] or `null` if the [index] is out of bounds of this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.getOrNull(index: Int): Char? { + return if (index >= 0 && index <= lastIndex) get(index) else null +} + /** * Returns index of the first character matching the given [predicate], or -1 if the char sequence does not contain such character. */ @@ -107,6 +201,19 @@ public inline fun CharSequence.indexOfFirst(predicate: (Char) -> Boolean): Int { return -1 } +/** + * Returns index of the first character matching the given [predicate], or -1 if the string does not contain such character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.indexOfFirst(predicate: (Char) -> Boolean): Int { + for (index in indices) { + if (predicate(this[index])) { + return index + } + } + return -1 +} + /** * Returns index of the last character matching the given [predicate], or -1 if the char sequence does not contain such character. */ @@ -119,6 +226,19 @@ public inline fun CharSequence.indexOfLast(predicate: (Char) -> Boolean): Int { return -1 } +/** + * Returns index of the last character matching the given [predicate], or -1 if the string does not contain such character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.indexOfLast(predicate: (Char) -> Boolean): Int { + for (index in indices.reversed()) { + if (predicate(this[index])) { + return index + } + } + return -1 +} + /** * Returns the last character. * @throws [NoSuchElementException] if the char sequence is empty. @@ -129,6 +249,17 @@ public fun CharSequence.last(): Char { return this[lastIndex] } +/** + * Returns the last character. + * @throws [NoSuchElementException] if the string is empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.last(): Char { + if (isEmpty()) + throw NoSuchElementException("Collection is empty.") + return this[lastIndex] +} + /** * Returns the last character matching the given [predicate]. * @throws [NoSuchElementException] if no such character is found. @@ -141,6 +272,19 @@ public inline fun CharSequence.last(predicate: (Char) -> Boolean): Char { throw NoSuchElementException("Collection doesn't contain any element matching the predicate.") } +/** + * Returns the last character matching the given [predicate]. + * @throws [NoSuchElementException] if no such character is found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.last(predicate: (Char) -> Boolean): Char { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + throw NoSuchElementException("Collection doesn't contain any element matching the predicate.") +} + /** * Returns the last character, or `null` if the char sequence is empty. */ @@ -148,6 +292,14 @@ public fun CharSequence.lastOrNull(): Char? { return if (isEmpty()) null else this[length - 1] } +/** + * Returns the last character, or `null` if the string is empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lastOrNull(): Char? { + return if (isEmpty()) null else this[length - 1] +} + /** * Returns the last character matching the given [predicate], or `null` if no such character was found. */ @@ -159,6 +311,18 @@ public inline fun CharSequence.lastOrNull(predicate: (Char) -> Boolean): Char? { return null } +/** + * Returns the last character matching the given [predicate], or `null` if no such character was found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.lastOrNull(predicate: (Char) -> Boolean): Char? { + for (index in this.indices.reversed()) { + val element = this[index] + if (predicate(element)) return element + } + return null +} + /** * Returns the single character, or throws an exception if the char sequence is empty or has more than one character. */ @@ -170,6 +334,18 @@ public fun CharSequence.single(): Char { } } +/** + * Returns the single character, or throws an exception if the string is empty or has more than one character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.single(): Char { + return when (length) { + 0 -> throw NoSuchElementException("Collection is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("Collection has more than one element.") + } +} + /** * Returns the single character matching the given [predicate], or throws exception if there is no or more than one matching character. */ @@ -187,6 +363,24 @@ public inline fun CharSequence.single(predicate: (Char) -> Boolean): Char { return single as Char } +/** + * Returns the single character matching the given [predicate], or throws exception if there is no or more than one matching character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.single(predicate: (Char) -> Boolean): Char { + var single: Char? = null + var found = false + for (element in this) { + if (predicate(element)) { + if (found) throw IllegalArgumentException("Collection contains more than one matching element.") + single = element + found = true + } + } + if (!found) throw NoSuchElementException("Collection doesn't contain any element matching predicate.") + return single as Char +} + /** * Returns single character, or `null` if the char sequence is empty or has more than one character. */ @@ -194,6 +388,14 @@ public fun CharSequence.singleOrNull(): Char? { return if (length == 1) this[0] else null } +/** + * Returns single character, or `null` if the string is empty or has more than one character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.singleOrNull(): Char? { + return if (length == 1) this[0] else null +} + /** * Returns the single character matching the given [predicate], or `null` if character was not found or more than one character was found. */ @@ -211,6 +413,24 @@ public inline fun CharSequence.singleOrNull(predicate: (Char) -> Boolean): Char? return single } +/** + * Returns the single character matching the given [predicate], or `null` if character was not found or more than one character was found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.singleOrNull(predicate: (Char) -> Boolean): Char? { + var single: Char? = null + var found = false + for (element in this) { + if (predicate(element)) { + if (found) return null + single = element + found = true + } + } + if (!found) return null + return single +} + /** * Returns a subsequence of this char sequence with the first [n] characters removed. */ @@ -343,6 +563,15 @@ public inline fun CharSequence.filterNotTo(destination: C, pred return destination } +/** + * Appends all elements not matching the given [predicate] to the given [destination]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.filterNotTo(destination: C, predicate: (Char) -> Boolean): C { + for (element in this) if (!predicate(element)) destination.append(element) + return destination +} + /** * Appends all characters matching the given [predicate] to the given [destination]. */ @@ -354,6 +583,18 @@ public inline fun CharSequence.filterTo(destination: C, predica return destination } +/** + * Appends all characters matching the given [predicate] to the given [destination]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.filterTo(destination: C, predicate: (Char) -> Boolean): C { + for (index in 0..length - 1) { + val element = get(index) + if (predicate(element)) destination.append(element) + } + return destination +} + /** * Returns a char sequence containing characters of the original char sequence at the specified range of [indices]. */ @@ -497,6 +738,14 @@ public fun CharSequence.toArrayList(): ArrayList { return toCollection(ArrayList(length)) } +/** + * Returns an [ArrayList] of all characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.toArrayList(): ArrayList { + return toCollection(ArrayList(length)) +} + /** * Appends all characters to the given [destination] collection. */ @@ -507,6 +756,17 @@ public fun > CharSequence.toCollection(destinatio return destination } +/** + * Appends all characters to the given [destination] collection. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun > String.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} + /** * Returns a [HashSet] of all characters. */ @@ -514,6 +774,14 @@ public fun CharSequence.toHashSet(): HashSet { return toCollection(HashSet(mapCapacity(length))) } +/** + * Returns a [HashSet] of all characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.toHashSet(): HashSet { + return toCollection(HashSet(mapCapacity(length))) +} + /** * Returns a [List] containing all characters. */ @@ -521,11 +789,24 @@ public fun CharSequence.toList(): List { return this.toArrayList() } +/** + * Returns a [List] containing all characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.toList(): List { + return this.toArrayList() +} + @Deprecated("Use toMapBy instead.", ReplaceWith("toMapBy(selector)")) public inline fun CharSequence.toMap(selector: (Char) -> K): Map { return toMapBy(selector) } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.toMap(selector: (Char) -> K): Map { + return toMapBy(selector) +} + /** * Returns Map containing the values provided by [transform] and indexed by [selector] functions applied to characters of the given char sequence. * If any two characters would have the same key returned by [selector] the last one gets added to the map. @@ -539,6 +820,20 @@ public inline fun CharSequence.toMap(selector: (Char) -> K, transform: (C return result } +/** + * Returns Map containing the values provided by [transform] and indexed by [selector] functions applied to characters of the given string. + * If any two characters would have the same key returned by [selector] the last one gets added to the map. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.toMap(selector: (Char) -> K, transform: (Char) -> V): Map { + val capacity = (length/.75f) + 1 + val result = LinkedHashMap(Math.max(capacity.toInt(), 16)) + for (element in this) { + result.put(selector(element), transform(element)) + } + return result +} + /** * Returns Map containing the characters from the given char sequence indexed by the key * returned from [selector] function applied to each character. @@ -553,6 +848,21 @@ public inline fun CharSequence.toMapBy(selector: (Char) -> K): Map return result } +/** + * Returns Map containing the characters from the given string indexed by the key + * returned from [selector] function applied to each character. + * If any two characters would have the same key returned by [selector] the last one gets added to the map. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.toMapBy(selector: (Char) -> K): Map { + val capacity = (length/.75f) + 1 + val result = LinkedHashMap(Math.max(capacity.toInt(), 16)) + for (element in this) { + result.put(selector(element), element) + } + return result +} + /** * Returns a [Set] of all characters. */ @@ -560,6 +870,14 @@ public fun CharSequence.toSet(): Set { return toCollection(LinkedHashSet(mapCapacity(length))) } +/** + * Returns a [Set] of all characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.toSet(): Set { + return toCollection(LinkedHashSet(mapCapacity(length))) +} + /** * Returns a [SortedSet] of all characters. */ @@ -567,6 +885,14 @@ public fun CharSequence.toSortedSet(): SortedSet { return toCollection(TreeSet()) } +/** + * Returns a [SortedSet] of all characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.toSortedSet(): SortedSet { + return toCollection(TreeSet()) +} + /** * Returns a single list of all elements yielded from results of [transform] function being invoked on each character of original char sequence. */ @@ -574,6 +900,14 @@ public inline fun CharSequence.flatMap(transform: (Char) -> Iterable): Li return flatMapTo(ArrayList(), transform) } +/** + * Returns a single list of all elements yielded from results of [transform] function being invoked on each character of original string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.flatMap(transform: (Char) -> Iterable): List { + return flatMapTo(ArrayList(), transform) +} + /** * Appends all elements yielded from results of [transform] function being invoked on each character of original char sequence, to the given [destination]. */ @@ -585,6 +919,18 @@ public inline fun > CharSequence.flatMapTo(destin return destination } +/** + * Appends all elements yielded from results of [transform] function being invoked on each character of original string, to the given [destination]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun > String.flatMapTo(destination: C, transform: (Char) -> Iterable): C { + for (element in this) { + val list = transform(element) + destination.addAll(list) + } + return destination +} + /** * Returns a map of the characters in original char sequence grouped by the key returned by the given [selector] function. */ @@ -592,6 +938,14 @@ public inline fun CharSequence.groupBy(selector: (Char) -> K): Map>(), selector) } +/** + * Returns a map of the characters in original string grouped by the key returned by the given [selector] function. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.groupBy(selector: (Char) -> K): Map> { + return groupByTo(LinkedHashMap>(), selector) +} + /** * Appends characters from original char sequence grouped by the key returned by the given [selector] function to the given [map]. */ @@ -604,6 +958,19 @@ public inline fun CharSequence.groupByTo(map: MutableMap String.groupByTo(map: MutableMap>, selector: (Char) -> K): Map> { + for (element in this) { + val key = selector(element) + val list = map.getOrPut(key) { ArrayList() } + list.add(element) + } + return map +} + /** * Returns a list containing the results of applying the given [transform] function * to each character in the original char sequence. @@ -612,6 +979,15 @@ public inline fun CharSequence.map(transform: (Char) -> R): List { return mapTo(ArrayList(length), transform) } +/** + * Returns a list containing the results of applying the given [transform] function + * to each character in the original string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.map(transform: (Char) -> R): List { + return mapTo(ArrayList(length), transform) +} + /** * Returns a list containing the results of applying the given [transform] function * to each character and its index in the original char sequence. @@ -620,6 +996,15 @@ public inline fun CharSequence.mapIndexed(transform: (Int, Char) -> R): List return mapIndexedTo(ArrayList(length), transform) } +/** + * Returns a list containing the results of applying the given [transform] function + * to each character and its index in the original string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.mapIndexed(transform: (Int, Char) -> R): List { + return mapIndexedTo(ArrayList(length), transform) +} + /** * Returns a list containing only the non-null results of applying the given [transform] function * to each character and its index in the original char sequence. @@ -648,6 +1033,18 @@ public inline fun > CharSequence.mapIndexedTo(des return destination } +/** + * Applies the given [transform] function to each character and its index in the original string + * and appends the results to the given [destination]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun > String.mapIndexedTo(destination: C, transform: (Int, Char) -> R): C { + var index = 0 + for (item in this) + destination.add(transform(index++, item)) + return destination +} + /** * Returns a list containing only the non-null results of applying the given [transform] function * to each character in the original char sequence. @@ -675,6 +1072,17 @@ public inline fun > CharSequence.mapTo(destinatio return destination } +/** + * Applies the given [transform] function to each character of the original string + * and appends the results to the given [destination]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun > String.mapTo(destination: C, transform: (Char) -> R): C { + for (item in this) + destination.add(transform(item)) + return destination +} + /** * Returns a lazy [Iterable] of [IndexedValue] for each character of the original char sequence. */ @@ -682,6 +1090,14 @@ public fun CharSequence.withIndex(): Iterable> { return IndexingIterable { iterator() } } +/** + * Returns a lazy [Iterable] of [IndexedValue] for each character of the original string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.withIndex(): Iterable> { + return IndexingIterable { iterator() } +} + /** * Returns `true` if all characters match the given [predicate]. */ @@ -690,6 +1106,15 @@ public inline fun CharSequence.all(predicate: (Char) -> Boolean): Boolean { return true } +/** + * Returns `true` if all characters match the given [predicate]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.all(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (!predicate(element)) return false + return true +} + /** * Returns `true` if char sequence has at least one character. */ @@ -698,6 +1123,15 @@ public fun CharSequence.any(): Boolean { return false } +/** + * Returns `true` if string has at least one character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.any(): Boolean { + for (element in this) return true + return false +} + /** * Returns `true` if at least one character matches the given [predicate]. */ @@ -706,6 +1140,15 @@ public inline fun CharSequence.any(predicate: (Char) -> Boolean): Boolean { return false } +/** + * Returns `true` if at least one character matches the given [predicate]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.any(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return true + return false +} + /** * Returns the length of this char sequence. */ @@ -713,6 +1156,14 @@ public fun CharSequence.count(): Int { return length } +/** + * Returns the number of characters in this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.count(): Int { + return length +} + /** * Returns the number of characters matching the given [predicate]. */ @@ -722,6 +1173,16 @@ public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int { return count } +/** + * Returns the number of characters matching the given [predicate]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.count(predicate: (Char) -> Boolean): Int { + var count = 0 + for (element in this) if (predicate(element)) count++ + return count +} + /** * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each character. */ @@ -731,6 +1192,16 @@ public inline fun CharSequence.fold(initial: R, operation: (R, Char) -> R): return accumulator } +/** + * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.fold(initial: R, operation: (R, Char) -> R): R { + var accumulator = initial + for (element in this) accumulator = operation(accumulator, element) + return accumulator +} + /** * Accumulates value starting with [initial] value and applying [operation] from right to left to each character and current accumulator value. */ @@ -743,6 +1214,19 @@ public inline fun CharSequence.foldRight(initial: R, operation: (Char, R) -> return accumulator } +/** + * Accumulates value starting with [initial] value and applying [operation] from right to left to each character and current accumulator value. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.foldRight(initial: R, operation: (Char, R) -> R): R { + var index = lastIndex + var accumulator = initial + while (index >= 0) { + accumulator = operation(get(index--), accumulator) + } + return accumulator +} + /** * Performs the given [action] on each character. */ @@ -750,6 +1234,14 @@ public inline fun CharSequence.forEach(action: (Char) -> Unit): Unit { for (element in this) action(element) } +/** + * Performs the given [action] on each character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.forEach(action: (Char) -> Unit): Unit { + for (element in this) action(element) +} + /** * Performs the given [action] on each character, providing sequential index with the character. */ @@ -758,6 +1250,15 @@ public inline fun CharSequence.forEachIndexed(action: (Int, Char) -> Unit): Unit for (item in this) action(index++, item) } +/** + * Performs the given [action] on each character, providing sequential index with the character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.forEachIndexed(action: (Int, Char) -> Unit): Unit { + var index = 0 + for (item in this) action(index++, item) +} + /** * Returns the largest character or `null` if there are no characters. */ @@ -771,6 +1272,20 @@ public fun CharSequence.max(): Char? { return max } +/** + * Returns the largest character or `null` if there are no characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.max(): Char? { + if (isEmpty()) return null + var max = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (max < e) max = e + } + return max +} + /** * Returns the first character yielding the largest value of the given function or `null` if there are no characters. */ @@ -789,6 +1304,25 @@ public inline fun > CharSequence.maxBy(selector: (Char) -> R): return maxElem } +/** + * Returns the first character yielding the largest value of the given function or `null` if there are no characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun > String.maxBy(selector: (Char) -> R): Char? { + if (isEmpty()) return null + var maxElem = this[0] + var maxValue = selector(maxElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (maxValue < v) { + maxElem = e + maxValue = v + } + } + return maxElem +} + /** * Returns the smallest character or `null` if there are no characters. */ @@ -802,6 +1336,20 @@ public fun CharSequence.min(): Char? { return min } +/** + * Returns the smallest character or `null` if there are no characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.min(): Char? { + if (isEmpty()) return null + var min = this[0] + for (i in 1..lastIndex) { + val e = this[i] + if (min > e) min = e + } + return min +} + /** * Returns the first character yielding the smallest value of the given function or `null` if there are no characters. */ @@ -820,6 +1368,25 @@ public inline fun > CharSequence.minBy(selector: (Char) -> R): return minElem } +/** + * Returns the first character yielding the smallest value of the given function or `null` if there are no characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun > String.minBy(selector: (Char) -> R): Char? { + if (isEmpty()) return null + var minElem = this[0] + var minValue = selector(minElem) + for (i in 1..lastIndex) { + val e = this[i] + val v = selector(e) + if (minValue > v) { + minElem = e + minValue = v + } + } + return minElem +} + /** * Returns `true` if the char sequence has no characters. */ @@ -828,6 +1395,15 @@ public fun CharSequence.none(): Boolean { return true } +/** + * Returns `true` if the string has no characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.none(): Boolean { + for (element in this) return false + return true +} + /** * Returns `true` if no characters match the given [predicate]. */ @@ -836,6 +1412,15 @@ public inline fun CharSequence.none(predicate: (Char) -> Boolean): Boolean { return true } +/** + * Returns `true` if no characters match the given [predicate]. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.none(predicate: (Char) -> Boolean): Boolean { + for (element in this) if (predicate(element)) return false + return true +} + /** * Accumulates value starting with the first character and applying [operation] from left to right to current accumulator value and each character. */ @@ -849,6 +1434,20 @@ public inline fun CharSequence.reduce(operation: (Char, Char) -> Char): Char { return accumulator } +/** + * Accumulates value starting with the first character and applying [operation] from left to right to current accumulator value and each character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.reduce(operation: (Char, Char) -> Char): Char { + val iterator = this.iterator() + if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced.") + var accumulator = iterator.next() + while (iterator.hasNext()) { + accumulator = operation(accumulator, iterator.next()) + } + return accumulator +} + /** * Accumulates value starting with last character and applying [operation] from right to left to each character and current accumulator value. */ @@ -862,6 +1461,20 @@ public inline fun CharSequence.reduceRight(operation: (Char, Char) -> Char): Cha return accumulator } +/** + * Accumulates value starting with last character and applying [operation] from right to left to each character and current accumulator value. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.reduceRight(operation: (Char, Char) -> Char): Char { + var index = lastIndex + if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced.") + var accumulator = get(index--) + while (index >= 0) { + accumulator = operation(get(index--), accumulator) + } + return accumulator +} + /** * Returns the sum of all values produced by [selector] function applied to each character in the char sequence. */ @@ -873,6 +1486,18 @@ public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int { return sum } +/** + * Returns the sum of all values produced by [selector] function applied to each character in the string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.sumBy(selector: (Char) -> Int): Int { + var sum: Int = 0 + for (element in this) { + sum += selector(element) + } + return sum +} + /** * Returns the sum of all values produced by [selector] function applied to each character in the char sequence. */ @@ -884,6 +1509,18 @@ public inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double { return sum } +/** + * Returns the sum of all values produced by [selector] function applied to each character in the string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.sumByDouble(selector: (Char) -> Double): Double { + var sum: Double = 0.0 + for (element in this) { + sum += selector(element) + } + return sum +} + /** * Splits the original char sequence into pair of char sequences, * where *first* char sequence contains characters for which [predicate] yielded `true`, @@ -939,11 +1576,29 @@ public inline fun CharSequence.zip(other: CharSequence, transform: (Char, Ch return list } +/** + * Returns a list of values built from characters of both char sequences with same indexes using provided [transform]. List has length of shortest char sequence. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.zip(other: CharSequence, transform: (Char, Char) -> V): List { + val length = Math.min(this.length, other.length) + val list = ArrayList(length) + for (i in 0..length-1) { + list.add(transform(this[i], other[i])) + } + return list +} + @Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) public infix fun CharSequence.zip(other: String): List> { return zip(other) { c1, c2 -> c1 to c2 } } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public infix fun String.zip(other: String): List> { + return zip(other) { c1, c2 -> c1 to c2 } +} + /** * Returns a sequence from the given collection. */ @@ -956,3 +1611,16 @@ public fun CharSequence.asSequence(): Sequence { } } +/** + * Returns a sequence from the given collection. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.asSequence(): Sequence { + if (this is String && isEmpty()) return emptySequence() + return object : Sequence { + override fun iterator(): Iterator { + return this@asSequence.iterator() + } + } +} + diff --git a/libraries/stdlib/src/kotlin/collections/MapsJVM.kt b/libraries/stdlib/src/kotlin/collections/MapsJVM.kt index 1c04aa8d23f..e2b292c5ebd 100644 --- a/libraries/stdlib/src/kotlin/collections/MapsJVM.kt +++ b/libraries/stdlib/src/kotlin/collections/MapsJVM.kt @@ -18,6 +18,10 @@ public operator fun MutableMap.set(key: K, value: V): Unit { put(key, value) } +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +@JvmName("set") +public fun MutableMap.set(key: K, value: V): V? = put(key, value) + /** * getOrPut is not supported on [ConcurrentMap] since it cannot be implemented correctly in terms of concurrency. * Use [concurrentGetOrPut] instead, or cast this to a [MutableMap] if you want to sacrifice the concurrent-safety. diff --git a/libraries/stdlib/src/kotlin/text/StringsDeprecated.kt b/libraries/stdlib/src/kotlin/text/StringsDeprecated.kt new file mode 100644 index 00000000000..95be0ee6097 --- /dev/null +++ b/libraries/stdlib/src/kotlin/text/StringsDeprecated.kt @@ -0,0 +1,577 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("StringsKt") + + +package kotlin + +import java.util.NoSuchElementException +import kotlin.text.MatchResult +import kotlin.text.Regex + +/** Returns `true` if the string is not `null` and not empty */ +@Deprecated("Use !isNullOrEmpty() or isNullOrEmpty().not() for nullable strings.", ReplaceWith("this != null && this.isNotEmpty()"), DeprecationLevel.ERROR) +@kotlin.jvm.JvmName("isNotEmptyNullable") +public fun CharSequence?.isNotEmpty(): Boolean = this != null && this.length() > 0 + + +/** Returns `true` if the string is not `null` and not empty */ +@Deprecated("Use !isNullOrEmpty() or isNullOrEmpty().not() for nullable strings.", ReplaceWith("this != null && this.isNotEmpty()"), DeprecationLevel.HIDDEN) +@kotlin.jvm.JvmName("isNotEmptyNullable") +public fun String?.isNotEmpty(): Boolean = this != null && this.length() > 0 + +/** + * Returns `true` if this nullable string is either `null` or empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String?.isNullOrEmpty(): Boolean = this == null || this.length() == 0 + +/** + * Returns `true` if this string is empty (contains no characters). + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.isEmpty(): Boolean = length() == 0 + +/** + * Returns `true` if this string is not empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.isNotEmpty(): Boolean = length() > 0 + +// implemented differently in JVM and JS +//public fun String.isBlank(): Boolean = length() == 0 || all { it.isWhitespace() } + + +/** + * Returns `true` if this string is not empty and contains some characters except of whitespace characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.isNotBlank(): Boolean = !isBlank() + +/** + * Returns `true` if this nullable string is either `null` or empty or consists solely of whitespace characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank() + +/** + * Returns the range of valid character indices for this string. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public val String.indices: IntRange + get() = 0..length() - 1 + +/** + * Returns the index of the last character in the String or -1 if the String is empty. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public val String.lastIndex: Int + get() = this.length() - 1 + +/* +/** + * Returns a substring before the first occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringBefore(delimiter: Char, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(0, index) +} + +/** + * Returns a substring before the first occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringBefore(delimiter: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(0, index) +} + +/** + * Returns a substring after the first occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringAfter(delimiter: Char, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(index + 1, length()) +} + +/** + * Returns a substring after the first occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringAfter(delimiter: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(index + delimiter.length(), length()) +} + +/** + * Returns a substring before the last occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringBeforeLast(delimiter: Char, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(0, index) +} + +/** + * Returns a substring before the last occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringBeforeLast(delimiter: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(0, index) +} + +/** + * Returns a substring after the last occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringAfterLast(delimiter: Char, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(index + 1, length()) +} + +/** + * Returns a substring after the last occurrence of [delimiter]. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.substringAfterLast(delimiter: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else substring(index + delimiter.length(), length()) +} + + +/** + * Replace part of string before the first occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceBefore(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) +} + +/** + * Replace part of string before the first occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceBefore(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) +} + +/** + * Replace part of string after the first occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceAfter(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(index + 1, length(), replacement) +} + +/** + * Replace part of string after the first occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceAfter(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(index + delimiter.length(), length(), replacement) +} + +/** + * Replace part of string after the last occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceAfterLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(index + delimiter.length(), length(), replacement) +} + +/** + * Replace part of string after the last occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceAfterLast(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(index + 1, length(), replacement) +} + +/** + * Replace part of string before the last occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceBeforeLast(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) +} + +/** + * Replace part of string before the last occurrence of given delimiter with the [replacement] string. + * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. + */ +public fun String.replaceBeforeLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { + val index = lastIndexOf(delimiter) + return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) +} +*/ + + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.replaceRange(firstIndex: Int, lastIndex: Int, replacement: String): String + = replaceRange(firstIndex, lastIndex, replacement) + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.replaceRange(range: IntRange, replacement: String): String + = replaceRange(range.start, range.end + 1, replacement) + + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.removePrefix(prefix: String): String = removePrefix(prefix) + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.removeSuffix(suffix: String): String = removeSuffix(suffix) + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.removeSurrounding(prefix: String, suffix: String): String = removeSurrounding(prefix, suffix) + +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.removeSurrounding(delimiter: String): String = removeSurrounding(delimiter, delimiter) + + + +/** + * Returns a new string obtained by replacing each substring of this string that matches the given regular expression + * with the given [replacement]. + * + * The [replacement] can consist of any combination of literal text and $-substitutions. To treat the replacement string + * literally escape it with the [kotlin.text.Regex.Companion.escapeReplacement] method. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.replace(regex: Regex, replacement: String): String = regex.replace(this, replacement) + +/** + * Returns a new string obtained by replacing each substring of this string that matches the given regular expression + * with the result of the given function [transform] that takes [MatchResult] and returns a string to be used as a + * replacement for that match. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.replace(regex: Regex, transform: (MatchResult) -> String): String = regex.replace(this, transform) + +/** + * Replaces the first occurrence of the given regular expression [regex] in this string with specified [replacement] expression. + * + * @param replacement A replacement expression that can include substitutions. See [Regex.replaceFirst] for details. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.replaceFirst(regex: Regex, replacement: String): String = regex.replaceFirst(this, replacement) + + +/** + * Returns `true` if this string matches the given regular expression. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.matches(regex: Regex): Boolean = regex.matches(this) + + +/** + * Returns `true` if this string starts with the specified character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.startsWith(char: Char, ignoreCase: Boolean = false): Boolean = + this.length() > 0 && this[0].equals(char, ignoreCase) + +/** + * Returns `true` if this string ends with the specified character. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.endsWith(char: Char, ignoreCase: Boolean = false): Boolean = + this.length() > 0 && this[lastIndex].equals(char, ignoreCase) + + + + + +// indexOfAny() + +private fun String.findAnyOf(chars: CharArray, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? { + if (!ignoreCase && chars.size() == 1) { + val char = chars.single() + val index = if (!last) nativeIndexOf(char, startIndex) else nativeLastIndexOf(char, startIndex) + return if (index < 0) null else index to char + } + + val indices = if (!last) Math.max(startIndex, 0)..lastIndex else Math.min(startIndex, lastIndex) downTo 0 + for (index in indices) { + val charAtIndex = get(index) + val matchingCharIndex = chars.indexOfFirst { it.equals(charAtIndex, ignoreCase) } + if (matchingCharIndex >= 0) + return index to chars[matchingCharIndex] + } + + return null +} + +/** + * Finds the index of the first occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. + * @returns An index of the first occurrence of matched character from [chars] or -1 if none of [chars] are found. + * + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Int = + findAnyOf(chars, startIndex, ignoreCase, last = false)?.first ?: -1 + +/** + * Finds the index of the last occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. + * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. + * @returns An index of the last occurrence of matched character from [chars] or -1 if none of [chars] are found. + * + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int = + findAnyOf(chars, startIndex, ignoreCase, last = true)?.first ?: -1 + + +private fun String.findAnyOf(strings: Collection, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? { + if (!ignoreCase && strings.size() == 1) { + val string = strings.single() + val index = if (!last) nativeIndexOf(string, startIndex) else nativeLastIndexOf(string, startIndex) + return if (index < 0) null else index to string + } + + val indices = if (!last) Math.max(startIndex, 0)..length() else Math.min(startIndex, lastIndex) downTo 0 + for (index in indices) { + val matchingString = strings.firstOrNull { it.regionMatches(0, this, index, it.length(), ignoreCase) } + if (matchingString != null) + return index to matchingString + } + + return null +} + +/** + * Finds the first occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns A pair of an index of the first occurrence of matched string from [strings] and the string matched or `null` if none of [strings] are found. + * + * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from + * the beginning to the end of this string, and finds at each position the first element in [strings] + * that matches this string at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.findAnyOf(strings: Collection, startIndex: Int = 0, ignoreCase: Boolean = false): Pair? = + findAnyOf(strings, startIndex, ignoreCase, last = false) + +/** + * Finds the last occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns A pair of an index of the last occurrence of matched string from [strings] and the string matched or `null` if none of [strings] are found. + * + * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from + * the end toward the beginning of this string, and finds at each position the first element in [strings] + * that matches this string at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.findLastAnyOf(strings: Collection, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Pair? = + findAnyOf(strings, startIndex, ignoreCase, last = true) + +/** + * Finds the index of the first occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns An index of the first occurrence of matched string from [strings] or -1 if none of [strings] are found. + * + * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from + * the beginning to the end of this string, and finds at each position the first element in [strings] + * that matches this string at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.indexOfAny(strings: Collection, startIndex: Int = 0, ignoreCase: Boolean = false): Int = + findAnyOf(strings, startIndex, ignoreCase, last = false)?.first ?: -1 + +/** + * Finds the index of the last occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and + * optionally ignoring the case. + * + * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns An index of the last occurrence of matched string from [strings] or -1 if none of [strings] are found. + * + * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from + * the end toward the beginning of this string, and finds at each position the first element in [strings] + * that matches this string at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lastIndexOfAny(strings: Collection, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int = + findAnyOf(strings, startIndex, ignoreCase, last = true)?.first ?: -1 + + +// indexOf + +/** + * Returns the index within this string of the first occurrence of the specified character, starting from the specified [startIndex]. + * + * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. + * @returns An index of the first occurrence of [char] or -1 if none is found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.indexOf(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int { + return if (ignoreCase) + indexOfAny(charArrayOf(char), startIndex, ignoreCase) + else + nativeIndexOf(char, startIndex) +} + +/** + * Returns the index within this string of the first occurrence of the specified [string], starting from the specified [startIndex]. + * + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns An index of the first occurrence of [string] or -1 if none is found. + */ +@kotlin.jvm.JvmOverloads +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int { + return if (ignoreCase) + indexOfAny(listOf(string), startIndex, ignoreCase) + else + nativeIndexOf(string, startIndex) +} + +/** + * Returns the index within this string of the last occurrence of the specified character, starting from the specified [startIndex]. + * + * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. + * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. + * @returns An index of the first occurrence of [char] or -1 if none is found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lastIndexOf(char: Char, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int { + return if (ignoreCase) + lastIndexOfAny(charArrayOf(char), startIndex, ignoreCase) + else + nativeLastIndexOf(char, startIndex) +} + + +/** + * Returns the index within this string of the last occurrence of the specified [string], starting from the specified [startIndex]. + * + * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. + * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. + * @returns An index of the first occurrence of [string] or -1 if none is found. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lastIndexOf(string: String, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int { + return if (ignoreCase) + lastIndexOfAny(listOf(string), startIndex, ignoreCase) + else + nativeLastIndexOf(string, startIndex) +} + +/** + * Returns `true` if this string contains the specified sequence of characters as a substring. + * + * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public operator fun String.contains(seq: CharSequence, ignoreCase: Boolean = false): Boolean = + indexOf(seq.toString(), ignoreCase = ignoreCase) >= 0 + + +/** + * Returns `true` if this string contains the specified character. + * + * @param ignoreCase `true` to ignore character case when comparing characters. By default `false`. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public operator fun String.contains(char: Char, ignoreCase: Boolean = false): Boolean = + indexOf(char, ignoreCase = ignoreCase) >= 0 + + + + +// split + +/** + * Splits this string to a sequence of strings around occurrences of the specified [delimiters]. + * + * @param delimiters One or more strings to be used as delimiters. + * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. + * @param limit The maximum number of substrings to return. Zero by default means no limit is set. + * + * To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from + * the beginning to the end of this string, and finds at each position the first element in [delimiters] + * that matches this string at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence = + splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit) + +/** + * Splits this string to a list of strings around occurrences of the specified [delimiters]. + * + * @param delimiters One or more strings to be used as delimiters. + * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. + * @param limit The maximum number of substrings to return. Zero by default means no limit is set. + * + * To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from + * the beginning to the end of this string, and matches at each position the first element in [delimiters] + * that is equal to a delimiter in this instance at that position. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List = + splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList() + +/** + * Splits this string to a sequence of strings around occurrences of the specified [delimiters]. + * + * @param delimiters One or more characters to be used as delimiters. + * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. + * @param limit The maximum number of substrings to return. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence = + splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit) + +/** + * Splits this string to a list of strings around occurrences of the specified [delimiters]. + * + * @param delimiters One or more characters to be used as delimiters. + * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. + * @param limit The maximum number of substrings to return. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List = + splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList() + +/** + * Splits this string around matches of the given regular expression. + * + * @param limit Non-negative value specifying the maximum number of substrings to return. + * Zero by default means no limit is set. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.split(pattern: Regex, limit: Int = 0): List = pattern.split(this, limit) + +/** + * Splits this string to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lineSequence(): Sequence = lineSequence() + +/** + * * Splits this string to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.lines(): List = lineSequence().toList() + diff --git a/libraries/stdlib/src/kotlin/text/StringsDeprecatedJVM.kt b/libraries/stdlib/src/kotlin/text/StringsDeprecatedJVM.kt new file mode 100644 index 00000000000..d14f9654851 --- /dev/null +++ b/libraries/stdlib/src/kotlin/text/StringsDeprecatedJVM.kt @@ -0,0 +1,182 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("StringsKt") + +package kotlin + +import java.io.StringReader +import java.util.regex.Pattern +import java.nio.charset.Charset +import java.util.* + +/* +/** + * Returns `true` if this string is equal to [anotherString], optionally ignoring character case. + * + * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. + */ +public fun String.equals(anotherString: String, ignoreCase: Boolean = false): Boolean { + return if (!ignoreCase) + (this as java.lang.String).equals(anotherString) + else + (this as java.lang.String).equalsIgnoreCase(anotherString) +} + +/** + * Returns a new string with all occurrences of [oldChar] replaced with [newChar]. + */ +public fun String.replace(oldChar: Char, newChar: Char, ignoreCase: Boolean = false): String { + if (!ignoreCase) + return (this as java.lang.String).replace(oldChar, newChar) + else + return splitToSequence(oldChar, ignoreCase = ignoreCase).joinToString(separator = newChar.toString()) +} + +/** + * Returns a new string obtained by replacing all occurrences of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +public fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String = + splitToSequence(oldValue, ignoreCase = ignoreCase).joinToString(separator = newValue) + + +/** + * Returns a new string with the first occurrence of [oldChar] replaced with [newChar]. + */ +public fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean = false): String { + val index = indexOf(oldChar, ignoreCase = ignoreCase) + return if (index < 0) this else this.replaceRange(index, index + 1, newChar.toString()) +} + +/** + * Returns a new string obtained by replacing the first occurrence of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +public fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean = false): String { + val index = indexOf(oldValue, ignoreCase = ignoreCase) + return if (index < 0) this else this.replaceRange(index, index + oldValue.length(), newValue) +} + +*/ + +/** + * Splits this string around matches of the given regular expression. + + * @param limit Non-negative value specifying the maximum number of substrings to return. + * Zero by default means no limit is set. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.split(regex: Pattern, limit: Int = 0): List +{ + require(limit >= 0, { "Limit must be non-negative, but was $limit" } ) + return regex.split(this, if (limit == 0) -1 else limit).asList() +} + +/* + +/** + * Compares two strings lexicographically, optionally ignoring case differences. + */ +public fun String.compareTo(other: String, ignoreCase: Boolean = false): Int { + if (ignoreCase) + return (this as java.lang.String).compareToIgnoreCase(other) + else + return (this as java.lang.String).compareTo(other) +} + +/** + * Returns a new string obtained by concatenating this string and the specified string. + */ +public fun String.concat(str: String): String = (this as java.lang.String).concat(str) + +/** + * Returns `true` if this string is equal to the contents of the specified CharSequence. + */ +public fun String.contentEquals(cs: CharSequence): Boolean = (this as java.lang.String).contentEquals(cs) + +/** + * Returns `true` if this string is equal to the contents of the specified StringBuffer. + */ +public fun String.contentEquals(sb: StringBuffer): Boolean = (this as java.lang.String).contentEquals(sb) + +*/ +/** + * Returns `true` if this string is empty or consists solely of whitespace characters. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.isBlank(): Boolean = length() == 0 || all { it.isWhitespace() } + +/* + +/** + * Returns a subsequence of this sequence specified by given [range]. + */ +public fun CharSequence.slice(range: IntRange): CharSequence { + return subSequence(range.start, range.end + 1) // inclusive +} + +/** + * Returns a copy of this string having its first letter uppercased, or the original string, + * if it's empty or already starts with an upper case letter. + * + * @sample test.text.StringTest.capitalize + */ +public fun String.capitalize(): String { + return if (isNotEmpty() && charAt(0).isLowerCase()) substring(0, 1).toUpperCase() + substring(1) else this +} + +/** + * Returns a copy of this string having its first letter lowercased, or the original string, + * if it's empty or already starts with a lower case letter. + * + * @sample test.text.StringTest.decapitalize + */ +public fun String.decapitalize(): String { + return if (isNotEmpty() && charAt(0).isUpperCase()) substring(0, 1).toLowerCase() + substring(1) else this +} +*/ + +/** + * Repeats a given string [n] times. + * @throws [IllegalArgumentException] when n < 0. + * @sample test.text.StringJVMTest.repeat + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public fun String.repeat(n: Int): String { + if (n < 0) + throw IllegalArgumentException("Value should be non-negative, but was $n") + + val sb = StringBuilder() + for (i in 1..n) { + sb.append(this) + } + return sb.toString() +} + + +/** + * Appends the contents of this string, excluding the first characters that satisfy the given [predicate], + * to the given Appendable. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.dropWhileTo(result: T, predicate: (Char) -> Boolean): T { + var start = true + for (element in this) { + if (start && predicate(element)) { + // ignore + } else { + start = false + result.append(element) + } + } + return result +} + +/** + * Appends the first characters from this string that satisfy the given [predicate] to the given Appendable. + */ +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +public inline fun String.takeWhileTo(result: T, predicate: (Char) -> Boolean): T { + for (c in this) if (predicate(c)) result.append(c) else break + return result +} + diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt index 23ba27e9150..195d84a5250 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Aggregates.kt @@ -15,7 +15,8 @@ fun aggregates(): List { return true """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("none(predicate: (T) -> Boolean)") { @@ -29,7 +30,8 @@ fun aggregates(): List { return true """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("none()") { @@ -41,7 +43,8 @@ fun aggregates(): List { return true """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("any(predicate: (T) -> Boolean)") { @@ -55,7 +58,8 @@ fun aggregates(): List { return false """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("any()") { @@ -67,7 +71,8 @@ fun aggregates(): List { return false """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("count(predicate: (T) -> Boolean)") { @@ -82,7 +87,8 @@ fun aggregates(): List { return count """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("count()") { @@ -95,8 +101,9 @@ fun aggregates(): List { return count """ } + deprecate(Strings) { forBinaryCompatibility } doc(CharSequences) { "Returns the length of this char sequence."} - body(CharSequences) { + body(CharSequences, Strings) { "return length" } body(Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) { @@ -106,7 +113,8 @@ fun aggregates(): List { templates add f("sumBy(selector: (T) -> Int)") { inline(true) - include(CharSequences) + include(CharSequences, Strings) + deprecate(Strings) { forBinaryCompatibility } doc { f -> "Returns the sum of all values produced by [selector] function applied to each ${f.element} in the ${f.collection}." } returns("Int") body { @@ -122,7 +130,8 @@ fun aggregates(): List { templates add f("sumByDouble(selector: (T) -> Double)") { inline(true) - include(CharSequences) + include(CharSequences, Strings) + deprecate(Strings) { forBinaryCompatibility } doc { f -> "Returns the sum of all values produced by [selector] function applied to each ${f.element} in the ${f.collection}." } returns("Double") body { @@ -154,7 +163,8 @@ fun aggregates(): List { return min """ } - body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) return null var min = this[0] @@ -192,7 +202,8 @@ fun aggregates(): List { return minElem """ } - body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) return null @@ -257,7 +268,8 @@ fun aggregates(): List { """ } - body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) return null @@ -296,7 +308,8 @@ fun aggregates(): List { return maxElem """ } - body(CharSequences, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) return null @@ -345,7 +358,8 @@ fun aggregates(): List { templates add f("fold(initial: R, operation: (R, T) -> R)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each ${f.element}." } typeParam("R") returns("R") @@ -361,7 +375,8 @@ fun aggregates(): List { templates add f("foldRight(initial: R, operation: (T, R) -> R)") { inline(true) - only(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) doc { f -> "Accumulates value starting with [initial] value and applying [operation] from right to left to each ${f.element} and current accumulator value." } typeParam("R") returns("R") @@ -380,7 +395,8 @@ fun aggregates(): List { templates add f("reduce(operation: (T, T) -> T)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) exclude(ArraysOfObjects, Iterables, Sequences) doc { f -> "Accumulates value starting with the first ${f.element} and applying [operation] from left to right to current accumulator value and each ${f.element}." } @@ -424,7 +440,8 @@ fun aggregates(): List { templates add f("reduceRight(operation: (T, T) -> T)") { inline(true) - only(CharSequences, ArraysOfPrimitives) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings, ArraysOfPrimitives) doc { f -> "Accumulates value starting with last ${f.element} and applying [operation] from right to left to each ${f.element} and current accumulator value." } returns("T") body { @@ -475,12 +492,14 @@ fun aggregates(): List { for (element in this) action(element) """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("forEachIndexed(action: (Int, T) -> Unit)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Performs the given [action] on each ${f.element}, providing sequential index with the ${f.element}." } returns("Unit") body { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt index ac9fe54cadc..86f8bad8d61 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt @@ -69,6 +69,27 @@ fun comparables(): List { } } + templates add f("coerceIn(range: Range)") { + sourceFile(SourceFile.Ranges) + only(Primitives) + only(numericPrimitives.filterNot { it.isIntegral() }) + returns("SELF") + deprecate { forBinaryCompatibility } // force use generic overload instead + doc { + """ + Ensures that this value lies in the specified [range]. + + @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. + """ + } + body { + """ + if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: ${'$'}range.") + return if (this < range.start) range.start else if (this > range.end) range.end else this + """ + } + } + templates add f("coerceIn(range: ClosedRange)") { sourceFile(SourceFile.Ranges) only(Primitives, Generic) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index 73504238c6e..72e4e84f893 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -228,7 +228,8 @@ fun elements(): List { """ } - body(Lists, CharSequences, ArraysOfPrimitives, ArraysOfObjects) { + deprecate(Strings) { forBinaryCompatibility } + body(Lists, CharSequences, Strings, ArraysOfPrimitives, ArraysOfObjects) { """ for (index in indices) { if (predicate(this[index])) { @@ -258,7 +259,8 @@ fun elements(): List { """ } - body(Lists, CharSequences, ArraysOfPrimitives, ArraysOfObjects) { + deprecate(Strings) { forBinaryCompatibility } + body(Lists, CharSequences, Strings, ArraysOfPrimitives, ArraysOfObjects) { """ for (index in indices.reversed()) { if (predicate(this[index])) { @@ -287,7 +289,8 @@ fun elements(): List { return elementAtOrElse(index) { throw IndexOutOfBoundsException("Sequence doesn't contain element at index $index.") } """ } - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ return get(index) """ @@ -327,8 +330,9 @@ fun elements(): List { return defaultValue(index) """ } - inline(true, CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + inline(true, CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) """ @@ -339,7 +343,8 @@ fun elements(): List { doc { f -> "Returns ${f.element.prefixWithArticle()} at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this ${f.collection}." } returns("T") inline(true) - only(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) body { """ return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) @@ -381,7 +386,8 @@ fun elements(): List { return null """ } - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ return if (index >= 0 && index <= lastIndex) get(index) else null """ @@ -391,7 +397,8 @@ fun elements(): List { templates add f("getOrNull(index: Int)") { doc { f -> "Returns ${f.element.prefixWithArticle()} at the given [index] or `null` if the [index] is out of bounds of this ${f.collection}." } returns("T?") - only(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) body { """ return if (index >= 0 && index <= lastIndex) get(index) else null @@ -423,7 +430,8 @@ fun elements(): List { } """ } - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) throw NoSuchElementException("Collection is empty.") @@ -460,7 +468,8 @@ fun elements(): List { } """ } - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ return if (isEmpty()) null else this[0] """ @@ -478,7 +487,8 @@ fun elements(): List { templates add f("first(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> """Returns the first ${f.element} matching the given [predicate]. @throws [NoSuchElementException] if no such ${f.element} is found.""" } returns("T") @@ -493,7 +503,8 @@ fun elements(): List { templates add f("firstOrNull(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns the first ${f.element} matching the given [predicate], or `null` if ${f.element} was not found." } returns("T?") body { @@ -506,7 +517,8 @@ fun elements(): List { templates add f("find(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns the first ${f.element} matching the given [predicate], or `null` if no such ${f.element} was found." } returns("T?") body { "return firstOrNull(predicate)"} @@ -548,7 +560,8 @@ fun elements(): List { return last """ } - body(CharSequences, Lists, ArraysOfObjects, ArraysOfPrimitives) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) { """ if (isEmpty()) throw NoSuchElementException("Collection is empty.") @@ -587,7 +600,8 @@ fun elements(): List { return last """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ return if (isEmpty()) null else this[length - 1] """ @@ -602,7 +616,8 @@ fun elements(): List { templates add f("last(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> """Returns the last ${f.element} matching the given [predicate]. @throws [NoSuchElementException] if no such ${f.element} is found.""" } returns("T") @@ -627,7 +642,7 @@ fun elements(): List { """ } - body(CharSequences, ArraysOfPrimitives, ArraysOfObjects, Lists) { + body(CharSequences, Strings, ArraysOfPrimitives, ArraysOfObjects, Lists) { """ for (index in this.indices.reversed()) { val element = this[index] @@ -640,7 +655,8 @@ fun elements(): List { templates add f("lastOrNull(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns the last ${f.element} matching the given [predicate], or `null` if no such ${f.element} was found." } returns("T?") body { f -> @@ -661,7 +677,7 @@ fun elements(): List { """ } - body(CharSequences, ArraysOfPrimitives, ArraysOfObjects, Lists) { + body(CharSequences, Strings, ArraysOfPrimitives, ArraysOfObjects, Lists) { """ for (index in this.indices.reversed()) { val element = this[index] @@ -674,7 +690,8 @@ fun elements(): List { templates add f("findLast(predicate: (T) -> Boolean)") { inline(true) - include(Lists, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Lists, CharSequences, Strings) doc { f -> "Returns the last ${f.element} matching the given [predicate], or `null` if no such ${f.element} was found." } returns("T?") body { "return lastOrNull(predicate)"} @@ -714,7 +731,8 @@ fun elements(): List { return single """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ return when (length) { 0 -> throw NoSuchElementException("Collection is empty.") @@ -764,7 +782,8 @@ fun elements(): List { return single """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ return if (length == 1) this[0] else null """ @@ -778,7 +797,8 @@ fun elements(): List { templates add f("single(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns the single ${f.element} matching the given [predicate], or throws exception if there is no or more than one matching ${f.element}." } returns("T") body { @@ -800,7 +820,8 @@ fun elements(): List { templates add f("singleOrNull(predicate: (T) -> Boolean)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns the single ${f.element} matching the given [predicate], or `null` if ${f.element} was not found or more than one ${f.element} was found." } returns("T?") body { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt index 9f5495a3e91..12767e5fecf 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt @@ -384,7 +384,8 @@ fun filtering(): List { """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ for (index in 0..length - 1) { val element = get(index) @@ -479,8 +480,9 @@ fun filtering(): List { """ } + deprecate(Strings) { forBinaryCompatibility } doc(CharSequences) { "Appends all characters not matching the given [predicate] to the given [destination]." } - body(CharSequences) { + body(CharSequences, Strings) { """ for (element in this) if (!predicate(element)) destination.append(element) return destination diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt index 85f3ce5236b..04bcbb6abc5 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt @@ -556,7 +556,8 @@ fun generators(): List { } templates add f("zip(other: CharSequence, transform: (Char, Char) -> V)") { - only(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings) doc { """ Returns a list of values built from characters of both char sequences with same indexes using provided [transform]. List has length of shortest char sequence. @@ -598,7 +599,8 @@ fun generators(): List { templates add f("zip(other: String)") { infix(true) - only(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + only(CharSequences, Strings) deprecate { forBinaryCompatibility } returns("List>") body { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt index 53e6447fdf4..8c535a3856c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Mapping.kt @@ -6,7 +6,8 @@ fun mapping(): List { val templates = arrayListOf() templates add f("withIndex()") { - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns a ${if (f == Sequences) f.mapResult else "lazy [Iterable]"} of [IndexedValue] for each ${f.element} of the original ${f.collection}." } returns("Iterable>") body { @@ -40,7 +41,8 @@ fun mapping(): List { body(ArraysOfObjects, ArraysOfPrimitives) { "return mapIndexedTo(ArrayList(size), transform)" } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { "return mapIndexedTo(ArrayList(length), transform)" } inline(false, Sequences) @@ -67,7 +69,8 @@ fun mapping(): List { body(ArraysOfObjects, ArraysOfPrimitives, Maps) { "return mapTo(ArrayList(size), transform)" } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { "return mapTo(ArrayList(length), transform)" } @@ -146,7 +149,8 @@ fun mapping(): List { return destination """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("mapIndexedTo(destination: C, transform: (Int, T) -> R)") { @@ -170,8 +174,9 @@ fun mapping(): List { return destination """ } + deprecate(Strings) { forBinaryCompatibility } deprecate(Maps) { Deprecation("Use entries.mapIndexedTo instead.", replaceWith = "this.entries.mapIndexedTo(destination, transform)") } - include(Maps, CharSequences) + include(Maps, CharSequences, Strings) } templates add f("mapNotNullTo(destination: C, transform: (T) -> R?)") { @@ -226,7 +231,8 @@ fun mapping(): List { body { "return flatMapTo(ArrayList(), transform)" } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("flatMap(transform: (T) -> Sequence)") { @@ -255,7 +261,8 @@ fun mapping(): List { return destination """ } - include(Maps, CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(Maps, CharSequences, Strings) } templates add f("flatMapTo(destination: C, transform: (T) -> Sequence)") { @@ -280,7 +287,8 @@ fun mapping(): List { templates add f("groupBy(selector: (T) -> K)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns a map of the ${f.element}s in original ${f.collection} grouped by the key returned by the given [selector] function." } typeParam("K") returns("Map>") @@ -290,7 +298,8 @@ fun mapping(): List { templates add f("groupByTo(map: MutableMap>, selector: (T) -> K)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) typeParam("K") doc { f -> "Appends ${f.element}s from original ${f.collection} grouped by the key returned by the given [selector] function to the given [map]." } returns("Map>") diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt index e59e89bee39..a63c874e0fd 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Ranges.kt @@ -14,22 +14,32 @@ fun ranges(): List { fun Collection.permutations(): List> = flatMap { a -> map { b -> a to b } } templates add f("reversed()") { - only(ProgressionsOfPrimitives) + only(RangesOfPrimitives, ProgressionsOfPrimitives) only(rangePrimitives) doc(ProgressionsOfPrimitives) { "Returns a progression that goes over the same range in the opposite direction with the same step." } + doc(RangesOfPrimitives) { "Returns a progression that goes over this range in reverse direction." } returns("TProgression") + deprecate(RangesOfPrimitives) { forBinaryCompatibility } + body(RangesOfPrimitives) { + "return TProgression.fromClosedRange(last, first, -ONE)" + } body(ProgressionsOfPrimitives) { "return TProgression.fromClosedRange(last, first, -increment)" } } templates add f("reversed()") { - only(ProgressionsOfPrimitives) + only(RangesOfPrimitives, ProgressionsOfPrimitives) only(defaultPrimitives - PrimitiveType.Boolean - rangePrimitives - floatingPointPrimitives) doc(ProgressionsOfPrimitives) { "Returns a progression that goes over the same range in the opposite direction with the same step." } + doc(RangesOfPrimitives) { "Returns a progression that goes over this range in reverse direction." } returns("TProgression") deprecate(Deprecation("This range implementation has unclear semantics and will be removed soon.", level = DeprecationLevel.WARNING)) + deprecate(RangesOfPrimitives) { forBinaryCompatibility } annotations("""@Suppress("DEPRECATION_ERROR")""") + body(RangesOfPrimitives) { + "return TProgression.fromClosedRange(last, first, -ONE)" + } body(ProgressionsOfPrimitives) { "return TProgression.fromClosedRange(last, first, -increment)" } @@ -38,10 +48,18 @@ fun ranges(): List { templates add f("step(step: SUM)") { infix(true) - only(ProgressionsOfPrimitives) + only(RangesOfPrimitives, ProgressionsOfPrimitives) only(rangePrimitives) doc(ProgressionsOfPrimitives) { "Returns a progression that goes over the same range with the given step." } + doc(RangesOfPrimitives) { "Returns a progression that goes over this range with given step." } returns("TProgression") + deprecate(RangesOfPrimitives) { forBinaryCompatibility } + body(RangesOfPrimitives) { + """ + checkStepIsPositive(step > 0, step) + return TProgression.fromClosedRange(first, last, step) + """ + } body(ProgressionsOfPrimitives) { """ checkStepIsPositive(step > 0, step) @@ -53,12 +71,27 @@ fun ranges(): List { templates add f("step(step: SUM)") { infix(true) - only(ProgressionsOfPrimitives) + only(RangesOfPrimitives, ProgressionsOfPrimitives) only(defaultPrimitives - PrimitiveType.Boolean - rangePrimitives - floatingPointPrimitives) doc(ProgressionsOfPrimitives) { "Returns a progression that goes over the same range with the given step." } + doc(RangesOfPrimitives) { "Returns a progression that goes over this range with given step." } returns("TProgression") deprecate(Deprecation("This range implementation has unclear semantics and will be removed soon.", level = DeprecationLevel.WARNING)) + deprecate(RangesOfPrimitives) { forBinaryCompatibility } annotations("""@Suppress("DEPRECATION_ERROR")""") + body(RangesOfPrimitives) { + """ + checkStepIsPositive(step > 0, step) + return TProgression.fromClosedRange(first, last, step) + """ + } + bodyForTypes(RangesOfPrimitives, PrimitiveType.Float, PrimitiveType.Double) { + """ + if (step.isNaN()) throw IllegalArgumentException("Step must not be NaN.") + checkStepIsPositive(step > 0, step) + return TProgression.fromClosedRange(start, end, step) + """ + } body(ProgressionsOfPrimitives) { """ checkStepIsPositive(step > 0, step) @@ -102,12 +135,34 @@ fun ranges(): List { body { "return $progressionType.fromClosedRange($fromExpr, $toExpr, $incrementExpr)" } } + fun downToDeprecated(fromType: PrimitiveType, toType: PrimitiveType) = f("`-downTo`(to: $toType)") { + deprecate { forBinaryCompatibility } + sourceFile(SourceFile.Ranges) + only(Primitives) + only(fromType) + val elementType = maxByCapacity(fromType, toType) + val progressionType = elementType.name + "Progression" + returns(progressionType) + annotations("""@[kotlin.jvm.JvmName("downTo") kotlin.jvm.JvmVersion]""") + val fromExpr = if (elementType == fromType) "this" else "this.to$elementType()" + val toExpr = if (elementType == toType) "to" else "to.to$elementType()" + val incrementExpr = when (elementType) { + PrimitiveType.Long -> "-1L" + PrimitiveType.Float -> "-1.0F" + PrimitiveType.Double -> "-1.0" + else -> "-1" + } + + body { "return $progressionType.fromClosedRange($fromExpr, $toExpr, $incrementExpr)" } + } + val numericPrimitives = PrimitiveType.numericPrimitives val numericPermutations = numericPrimitives.permutations() val primitivePermutations = numericPermutations + (PrimitiveType.Char to PrimitiveType.Char) val integralPermutations = primitivePermutations.filter { it.first.isIntegral() && it.second.isIntegral() } templates addAll integralPermutations.map { downTo(it.first, it.second) } + templates addAll listOf(PrimitiveType.Byte, PrimitiveType.Short).permutations().map { downToDeprecated(it.first, it.second) } fun until(fromType: PrimitiveType, toType: PrimitiveType) = f("until(to: $toType)") { infix(true) @@ -152,7 +207,36 @@ fun ranges(): List { } } + fun untilDeprecated(fromType: PrimitiveType, toType: PrimitiveType) = f("`-until`(to: $toType)") { + deprecate { forBinaryCompatibility } + + sourceFile(SourceFile.Ranges) + only(Primitives) + only(fromType) + val elementType = maxByCapacity(fromType, toType) + val progressionType = elementType.name + "Range" + returns(progressionType) + annotations("""@[kotlin.jvm.JvmName("until") kotlin.jvm.JvmVersion]""") + + val fromExpr = if (elementType == fromType) "this" else "this.to$elementType()" + + if (elementType == toType) { + // hack to work around incorrect char overflow behavior in JVM and int overflow behavior in JS + val toExpr = "to" + body { + """ + val to_ = ($toExpr - 1).to$elementType() + if (to_ > to) throw IllegalArgumentException("The to argument value '${'$'}to' was too small.") + return $progressionType($fromExpr, to_) + """ + } + } else { + body { "return $progressionType($fromExpr, (to.to$elementType() - 1).to$elementType())" } + } + } + templates addAll integralPermutations.map { until(it.first, it.second) } + templates addAll listOf(PrimitiveType.Byte, PrimitiveType.Short).permutations().map { untilDeprecated(it.first, it.second) } fun containsDeprecated(rangeType: PrimitiveType, itemType: PrimitiveType) = f("contains(item: $itemType)") { operator(true) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Sequence.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Sequence.kt index ea1cdfec0ba..38f03c0e70e 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Sequence.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Sequence.kt @@ -30,7 +30,8 @@ fun sequences(): List { """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ if (this is String && isEmpty()) return emptySequence() return object : Sequence { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Snapshots.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Snapshots.kt index 03fd5cdf41f..05419ba206b 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Snapshots.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Snapshots.kt @@ -6,7 +6,8 @@ fun snapshots(): List { val templates = arrayListOf() templates add f("toCollection(destination: C)") { - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Appends all ${f.element}s to the given [destination] collection." } returns("C") typeParam("C : MutableCollection") @@ -25,7 +26,8 @@ fun snapshots(): List { returns("Set") body { "return toCollection(LinkedHashSet(mapCapacity(collectionSizeOrDefault(12))))" } body(Sequences) { "return toCollection(LinkedHashSet())" } - body(CharSequences) { "return toCollection(LinkedHashSet(mapCapacity(length)))" } + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { "return toCollection(LinkedHashSet(mapCapacity(length)))" } body(ArraysOfObjects, ArraysOfPrimitives) { "return toCollection(LinkedHashSet(mapCapacity(size)))" } } @@ -34,12 +36,14 @@ fun snapshots(): List { returns("HashSet") body { "return toCollection(HashSet(mapCapacity(collectionSizeOrDefault(12))))" } body(Sequences) { "return toCollection(HashSet())" } - body(CharSequences) { "return toCollection(HashSet(mapCapacity(length)))" } + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { "return toCollection(HashSet(mapCapacity(length)))" } body(ArraysOfObjects, ArraysOfPrimitives) { "return toCollection(HashSet(mapCapacity(size)))" } } templates add f("toSortedSet()") { - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) typeParam("T: Comparable") doc { f -> "Returns a [SortedSet] of all ${f.element}s." } returns("SortedSet") @@ -72,7 +76,8 @@ fun snapshots(): List { """ } body(Collections) { "return ArrayList(this)" } - body(CharSequences) { "return toCollection(ArrayList(length))" } + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { "return toCollection(ArrayList(length))" } body(ArraysOfObjects) { "return ArrayList(this.asCollection())" } body(ArraysOfPrimitives) { """ @@ -98,7 +103,8 @@ fun snapshots(): List { } templates add f("toList()") { - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + include(CharSequences, Strings) doc { f -> "Returns a [List] containing all ${f.element}s." } returns("List") body { "return this.toArrayList()" } @@ -106,7 +112,9 @@ fun snapshots(): List { templates add f("toMap(selector: (T) -> K)") { inline(true) - include(CharSequences) + deprecate(Strings) { forBinaryCompatibility } + body(Strings) { "return toMapBy(selector)" } + include(CharSequences, Strings) typeParam("K") returns("Map") deprecate(Deprecation("Use toMapBy instead.", replaceWith = "toMapBy(selector)")) @@ -148,7 +156,8 @@ fun snapshots(): List { return result """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ val capacity = (length/.75f) + 1 val result = LinkedHashMap(Math.max(capacity.toInt(), 16)) @@ -206,7 +215,8 @@ fun snapshots(): List { return result """ } - body(CharSequences) { + deprecate(Strings) { forBinaryCompatibility } + body(CharSequences, Strings) { """ val capacity = (length/.75f) + 1 val result = LinkedHashMap(Math.max(capacity.toInt(), 16)) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Strings.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Strings.kt index 1ab836e2232..7b75b8c24a1 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Strings.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Strings.kt @@ -55,6 +55,17 @@ fun strings(): List { } } + templates add f("joinTo(buffer: A, separator: String = \", \", prefix: String = \"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\", transform: ((T) -> String)? = null)") { + deprecate { forBinaryCompatibility } + typeParam("A : Appendable") + returns { "A" } + body { + """ + return joinTo(buffer, separator, prefix, postfix, limit, truncated, transform) + """ + } + } + templates add f("joinToString(separator: CharSequence = \", \", prefix: CharSequence = \"\", postfix: CharSequence = \"\", limit: Int = -1, truncated: CharSequence = \"...\", transform: ((T) -> CharSequence)? = null)") { doc { """ @@ -74,5 +85,15 @@ fun strings(): List { } } + templates add f("joinToString(separator: String = \", \", prefix: String = \"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\", transform: ((T) -> String)? = null)") { + deprecate { forBinaryCompatibility } + returns("String") + body { + """ + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() + """ + } + } + return templates } \ No newline at end of file