From e768b4e2850fee3b03e40b8d0e5868bf6d3f37fc Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 4 Nov 2014 19:02:16 +0400 Subject: [PATCH] stdlib: Introduced filterIsInstance version without class-literal as a parameter --- libraries/stdlib/src/generated/_SpecialJVM.kt | 45 +++++++++++++++++++ .../test/collections/CollectionJVMTest.kt | 38 ++++++++++++++++ .../stdlib/test/collections/StreamJVMTest.kt | 26 +++++++++++ .../kotlin-stdlib-gen/src/templates/Engine.kt | 18 +++++--- .../src/templates/SpecialJVM.kt | 40 +++++++++++++++++ 5 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 libraries/stdlib/test/collections/StreamJVMTest.kt diff --git a/libraries/stdlib/src/generated/_SpecialJVM.kt b/libraries/stdlib/src/generated/_SpecialJVM.kt index 1f75142a77a..a37737b08f3 100644 --- a/libraries/stdlib/src/generated/_SpecialJVM.kt +++ b/libraries/stdlib/src/generated/_SpecialJVM.kt @@ -324,6 +324,27 @@ public fun ShortArray.fill(element: Short): ShortArray { return this } +/** + * Returns a list containing all elements that are instances of specified type parameter R + */ +public inline fun Array<*>.filterIsInstance(): List { + return filterIsInstanceTo(ArrayList()) +} + +/** + * Returns a list containing all elements that are instances of specified type parameter R + */ +public inline fun Iterable<*>.filterIsInstance(): List { + return filterIsInstanceTo(ArrayList()) +} + +/** + * Returns a stream containing all elements that are instances of specified type parameter R + */ +public inline fun Stream<*>.filterIsInstance(): Stream { + return FilteringStream(this, true, { it is R }) as Stream +} + /** * Returns a list containing all elements that are instances of specified class */ @@ -345,6 +366,30 @@ public fun Stream.filterIsInstance(klass: Class): Stream { return FilteringStream(this, true, { klass.isInstance(it) }) as Stream } +/** + * Appends all elements that are instances of specified type parameter R to the given *destination* + */ +public inline fun > Array<*>.filterIsInstanceTo(destination: C): C { + for (element in this) if (element is R) destination.add(element) + return destination +} + +/** + * Appends all elements that are instances of specified type parameter R to the given *destination* + */ +public inline fun > Iterable<*>.filterIsInstanceTo(destination: C): C { + for (element in this) if (element is R) destination.add(element) + return destination +} + +/** + * Appends all elements that are instances of specified type parameter R to the given *destination* + */ +public inline fun > Stream<*>.filterIsInstanceTo(destination: C): C { + for (element in this) if (element is R) destination.add(element) + return destination +} + /** * Appends all elements that are instances of specified class to the given *destination* */ diff --git a/libraries/stdlib/test/collections/CollectionJVMTest.kt b/libraries/stdlib/test/collections/CollectionJVMTest.kt index 3718a4639c3..0ec08769e41 100644 --- a/libraries/stdlib/test/collections/CollectionJVMTest.kt +++ b/libraries/stdlib/test/collections/CollectionJVMTest.kt @@ -104,4 +104,42 @@ class CollectionJVMTest { test fun takeReturnsFirstNElements() { expect(setOf(1, 2)) { sortedSetOf(1, 2, 3, 4, 5).take(2).toSet() } } + + test fun filterIsInstanceList() { + val src: List = listOf(1,2,3.toDouble(), "abc", "cde") + + val ints: List = src.filterIsInstance() + assertEquals(arrayListOf(1,2), ints) + + val doubles: List = src.filterIsInstance() + assertEquals(arrayListOf(3.0), doubles) + + val strings: List = src.filterIsInstance() + assertEquals(arrayListOf("abc", "cde"), strings) + + val anys: List = src.filterIsInstance() + assertEquals(src.toList(), anys) + + val chars: List = src.filterIsInstance() + assertEquals(0, chars.size()) + } + + test fun filterIsInstanceArray() { + val src: Array = array(1,2,3.toDouble(), "abc", "cde") + + val ints: List = src.filterIsInstance() + assertEquals(arrayListOf(1,2), ints) + + val doubles: List = src.filterIsInstance() + assertEquals(arrayListOf(3.0), doubles) + + val strings: List = src.filterIsInstance() + assertEquals(arrayListOf("abc", "cde"), strings) + + val anys: List = src.filterIsInstance() + assertEquals(src.toList(), anys) + + val chars: List = src.filterIsInstance() + assertEquals(0, chars.size()) + } } diff --git a/libraries/stdlib/test/collections/StreamJVMTest.kt b/libraries/stdlib/test/collections/StreamJVMTest.kt new file mode 100644 index 00000000000..e893d87912d --- /dev/null +++ b/libraries/stdlib/test/collections/StreamJVMTest.kt @@ -0,0 +1,26 @@ +package test.collections + +import org.junit.Test as test +import kotlin.test.assertEquals + +class StreamJVMTest { + + test fun filterIsInstance() { + val src: Stream = listOf(1,2,3.toDouble(), "abc", "cde").stream() + + val ints: Stream = src.filterIsInstance() + assertEquals(arrayListOf(1,2), ints.toArrayList()) + + val doubles: Stream = src.filterIsInstance() + assertEquals(arrayListOf(3.0), doubles.toArrayList()) + + val strings: Stream = src.filterIsInstance() + assertEquals(arrayListOf("abc", "cde"), strings.toArrayList()) + + val anys: Stream = src.filterIsInstance() + assertEquals(src.toList(), anys.toArrayList()) + + val chars: Stream = src.filterIsInstance() + assertEquals(0, chars.toArrayList().size()) + } +} diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt index 3eb52665191..8c51e1accbe 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt @@ -36,6 +36,7 @@ class GenericFunction(val signature: String) : Comparable { var toNullableT: Boolean = false var defaultInline = false + var receiverAsterisk = false val inlineFamilies = HashMap() val buildFamilies = HashSet(defaultFamilies.toList()) @@ -104,6 +105,10 @@ class GenericFunction(val signature: String) : Comparable { typeParams.add(t) } + fun receiverAsterisk(v: Boolean) { + receiverAsterisk = true + } + fun inline(value: Boolean, vararg families: Family) { if (families.isEmpty()) defaultInline = value @@ -157,13 +162,14 @@ class GenericFunction(val signature: String) : Comparable { if (returnType.isEmpty()) throw RuntimeException("No return type specified for $signature") + val isAsteriskOrT = if (receiverAsterisk) "*" else "T" val receiver = when (f) { - Iterables -> "Iterable" - Collections -> "Collection" - Lists -> "List" + Iterables -> "Iterable<$isAsteriskOrT>" + Collections -> "Collection<$isAsteriskOrT>" + Lists -> "List<$isAsteriskOrT>" Maps -> "Map" - Streams -> "Stream" - ArraysOfObjects -> "Array" + Streams -> "Stream<$isAsteriskOrT>" + ArraysOfObjects -> "Array<$isAsteriskOrT>" Strings -> "String" ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type") else -> throw IllegalStateException("Invalid family") @@ -215,7 +221,7 @@ class GenericFunction(val signature: String) : Comparable { if (primitive == null && f != Strings) { val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).filterNot { it == ' ' }.takeWhile { it != '>' }.split(",") for (implicit in implicitTypeParameters.reverse()) { - if (!types.any { it.startsWith(implicit) }) { + if (implicit != "*" && !types.any { it.startsWith(implicit) || it.startsWith("reified " + implicit) }) { types.add(0, implicit) } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt index 73df13859f2..41844500e07 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt @@ -107,5 +107,45 @@ fun specialJVM(): List { } } + templates add f("filterIsInstanceTo(destination: C)") { + doc { "Appends all elements that are instances of specified type parameter R to the given *destination*" } + typeParam("reified R") + typeParam("C : MutableCollection") + inline(true) + receiverAsterisk(true) + returns("C") + exclude(ArraysOfPrimitives, Strings) + body { + """ + for (element in this) if (element is R) destination.add(element) + return destination + """ + } + } + + templates add f("filterIsInstance()") { + doc { "Returns a list containing all elements that are instances of specified type parameter R" } + typeParam("reified R") + returns("List") + inline(true) + receiverAsterisk(true) + body { + """ + return filterIsInstanceTo(ArrayList()) + """ + } + exclude(ArraysOfPrimitives, Strings) + + doc(Streams) { "Returns a stream containing all elements that are instances of specified type parameter R" } + returns(Streams) { "Stream" } + inline(true) + receiverAsterisk(true) + body(Streams) { + """ + return FilteringStream(this, true, { it is R }) as Stream + """ + } + } + return templates } \ No newline at end of file