From 8d02467e6db099e626f5a0ad361891d4e3d54910 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 26 Jan 2016 18:42:30 +0300 Subject: [PATCH] Introduce plusElement and minusElement to disambiguate situations like List> + List #KT-9992 Fixed --- js/js.libraries/src/core/kotlin_special.kt | 8 +++++++ libraries/stdlib/src/generated/_Arrays.kt | 8 +++++++ .../stdlib/src/generated/_Collections.kt | 21 ++++++++++++++++++ libraries/stdlib/src/generated/_Sequences.kt | 14 ++++++++++++ libraries/stdlib/src/generated/_Sets.kt | 14 ++++++++++++ .../stdlib/test/collections/ArraysTest.kt | 14 ++++++++++++ .../stdlib/test/collections/CollectionTest.kt | 12 ++++++++++ .../src/templates/Generators.kt | 22 +++++++++++++++++++ .../src/templates/SpecialJS.kt | 14 ++++++++++++ .../src/templates/SpecialJVM.kt | 7 ++++++ 10 files changed, 134 insertions(+) diff --git a/js/js.libraries/src/core/kotlin_special.kt b/js/js.libraries/src/core/kotlin_special.kt index d4e1a531f4b..522c2c2b51a 100644 --- a/js/js.libraries/src/core/kotlin_special.kt +++ b/js/js.libraries/src/core/kotlin_special.kt @@ -488,6 +488,14 @@ public inline operator fun ShortArray.plus(elements: ShortArray): ShortArray { return this.asDynamic().concat(elements) } +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@Suppress("NOTHING_TO_INLINE") +public inline fun Array.plusElement(element: T): Array { + return this.asDynamic().concat(arrayOf(element)) +} + /** * Sorts the array in-place. */ diff --git a/libraries/stdlib/src/generated/_Arrays.kt b/libraries/stdlib/src/generated/_Arrays.kt index 8d0cd371eaa..632a61f90b9 100644 --- a/libraries/stdlib/src/generated/_Arrays.kt +++ b/libraries/stdlib/src/generated/_Arrays.kt @@ -12358,6 +12358,14 @@ public operator fun ShortArray.plus(elements: ShortArray): ShortArray { return result } +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@kotlin.jvm.JvmVersion +public fun Array.plusElement(element: T): Array { + return plus(element) +} + /** * Sorts the array in-place. */ diff --git a/libraries/stdlib/src/generated/_Collections.kt b/libraries/stdlib/src/generated/_Collections.kt index 338bbb05cfc..6e07ab54c34 100644 --- a/libraries/stdlib/src/generated/_Collections.kt +++ b/libraries/stdlib/src/generated/_Collections.kt @@ -1599,6 +1599,13 @@ public operator fun Iterable.minus(elements: Sequence): List { return this.filterNot { it in other } } +/** + * Returns a list containing all elements of the original collection without the first occurrence of the given [element]. + */ +public fun Iterable.minusElement(element: T): List { + return minus(element) +} + /** * Splits the original collection into pair of lists, * where *first* list contains elements for which [predicate] yielded `true`, @@ -1706,6 +1713,20 @@ public operator fun Iterable.plus(elements: Sequence): List { return result } +/** + * Returns a list containing all elements of the original collection and then the given [element]. + */ +public fun Collection.plusElement(element: T): List { + return plus(element) +} + +/** + * Returns a list containing all elements of the original collection and then the given [element]. + */ +public fun Iterable.plusElement(element: T): List { + return plus(element) +} + /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ diff --git a/libraries/stdlib/src/generated/_Sequences.kt b/libraries/stdlib/src/generated/_Sequences.kt index 01f6bc7cfcc..c690caabc8b 100644 --- a/libraries/stdlib/src/generated/_Sequences.kt +++ b/libraries/stdlib/src/generated/_Sequences.kt @@ -1024,6 +1024,13 @@ public operator fun Sequence.minus(elements: Sequence): Sequence { } } +/** + * Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]. + */ +public fun Sequence.minusElement(element: T): Sequence { + return minus(element) +} + /** * Splits the original sequence into pair of lists, * where *first* list contains elements for which [predicate] yielded `true`, @@ -1076,6 +1083,13 @@ public operator fun Sequence.plus(elements: Sequence): Sequence { return sequenceOf(this, elements).flatten() } +/** + * Returns a sequence containing all elements of the original sequence and then the given [element]. + */ +public fun Sequence.plusElement(element: T): Sequence { + return plus(element) +} + /** * Returns a sequence of pairs built from elements of both sequences with same indexes. * Resulting sequence has length of shortest input sequence. diff --git a/libraries/stdlib/src/generated/_Sets.kt b/libraries/stdlib/src/generated/_Sets.kt index a6b31c807b1..e69c5257a59 100644 --- a/libraries/stdlib/src/generated/_Sets.kt +++ b/libraries/stdlib/src/generated/_Sets.kt @@ -54,6 +54,13 @@ public operator fun Set.minus(elements: Sequence): Set { return result } +/** + * Returns a set containing all elements of the original set except the given [element]. + */ +public fun Set.minusElement(element: T): Set { + return minus(element) +} + /** * Returns a set containing all elements of the original set and then the given [element]. */ @@ -94,3 +101,10 @@ public operator fun Set.plus(elements: Sequence): Set { return result } +/** + * Returns a set containing all elements of the original set and then the given [element]. + */ +public fun Set.plusElement(element: T): Set { + return plus(element) +} + diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index 8872ec7ae0c..a8aa77e92df 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -430,6 +430,20 @@ class ArraysTest { assertTrue(intArrayOf(1).isNotEmpty()) } + @test fun plusInference() { + val arrayOfArrays: Array> = arrayOf(arrayOf("s") as Array) + val elementArray = arrayOf("a") as Array + val arrayPlusElement: Array> = arrayOfArrays.plusElement(elementArray) + assertEquals("a", arrayPlusElement[1][0]) + // ambiguity + // val arrayPlusArray: Array> = arrayOfArrays + arrayOfArrays + + val arrayOfStringArrays = arrayOf(arrayOf("s")) + val arrayPlusArray = arrayOfStringArrays + arrayOfStringArrays + assertEquals("s", arrayPlusArray[1][0]) + } + + @test fun plus() { assertEquals(listOf("1", "2", "3", "4"), listOf("1", "2") + arrayOf("3", "4")) assertArrayNotSameButEquals(arrayOf("1", "2", "3"), arrayOf("1", "2") + "3") diff --git a/libraries/stdlib/test/collections/CollectionTest.kt b/libraries/stdlib/test/collections/CollectionTest.kt index 5878a43ee81..0ad2a01f31d 100644 --- a/libraries/stdlib/test/collections/CollectionTest.kt +++ b/libraries/stdlib/test/collections/CollectionTest.kt @@ -247,6 +247,18 @@ class CollectionTest { assertEquals(listOf("foo", "bar", "cheese", "wine"), list) } + @test fun plusCollectionInference() { + val listOfLists = listOf(listOf("s")) + val elementList = listOf("a") + val result: List> = listOfLists.plusElement(elementList) + assertEquals(listOf(listOf("s"), listOf("a")), result, "should be list + element") + + val listOfAny = listOf("a") + listOf("b") + assertEquals(listOf("a", "b"), listOfAny, "should be list + list") + + val listOfAnyAndList = listOf("a") + listOf("b") as Any + assertEquals(listOf("a", listOf("b")), listOfAnyAndList, "should be list + Any") + } @test fun plusAssign() { // lets use a mutable variable of readonly list diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt index 506c307fb7f..f2612a7f24c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt @@ -5,6 +5,17 @@ import templates.Family.* fun generators(): List { val templates = arrayListOf() + templates add f("plusElement(element: T)") { + only(Iterables, Collections, Sets, Sequences) + doc { "Returns a list containing all elements of the original collection and then the given [element]." } + doc(Sets) { "Returns a set containing all elements of the original set and then the given [element]." } + doc(Sequences) { "Returns a sequence containing all elements of the original sequence and then the given [element]." } + + returns("List") + returns("SELF", Sets, Sequences) + body { "return plus(element)" } + } + templates add f("plus(element: T)") { operator(true) @@ -206,6 +217,17 @@ fun generators(): List { } } + templates add f("minusElement(element: T)") { + only(Iterables, Sets, Sequences) + doc { "Returns a list containing all elements of the original collection without the first occurrence of the given [element]." } + doc(Sets) { "Returns a set containing all elements of the original set except the given [element]." } + doc(Sequences) { "Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]." } + + returns("List") + returns("SELF", Sets, Sequences) + body { "return minus(element)" } + } + templates add f("minus(element: T)") { operator(true) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJS.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJS.kt index 6c6d70a253f..11247bfe441 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJS.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJS.kt @@ -90,6 +90,20 @@ fun specialJS(): List { } + templates add f("plusElement(element: T)") { + only(ArraysOfObjects) + returns("SELF") + returns(ArraysOfObjects) { "Array" } + inline(true) + annotations("""@Suppress("NOTHING_TO_INLINE")""") + doc { "Returns an array containing all elements of the original array and then the given [element]." } + body() { + """ + return this.asDynamic().concat(arrayOf(element)) + """ + } + } + templates add f("plus(element: T)") { operator(true) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt index 21a0bf2f81a..2f96a10fd08 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt @@ -5,6 +5,13 @@ import templates.Family.* fun specialJVM(): List { val templates = arrayListOf() + templates add f("plusElement(element: T)") { + only(InvariantArraysOfObjects) + returns("SELF") + doc { "Returns an array containing all elements of the original array and then the given [element]." } + body { "return plus(element)" } + } + templates add f("plus(element: T)") { operator(true)