diff --git a/libraries/stdlib/src/generated/_SpecialJVM.kt b/libraries/stdlib/src/generated/_SpecialJVM.kt index 754e161fde8..6700360e8fd 100644 --- a/libraries/stdlib/src/generated/_SpecialJVM.kt +++ b/libraries/stdlib/src/generated/_SpecialJVM.kt @@ -9,6 +9,133 @@ import java.util.* import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js +/** + * Returns a list that wraps the original array + */ +public fun Array.asList(): List { + return Arrays.asList(*this) +} + +/** + * Returns a list that wraps the original array + */ +public fun BooleanArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Boolean) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Boolean = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Boolean) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Boolean) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun ByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Byte) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Byte = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Byte) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Byte) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun CharArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Char) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Char = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Char) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Char) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun DoubleArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Double) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Double = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Double) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Double) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun FloatArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Float) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Float = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Float) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Float) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun IntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Int) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Int = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Int) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Int) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun LongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Long) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Long = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Long) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Long) + } +} + +/** + * Returns a list that wraps the original array + */ +public fun ShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as Short) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): Short = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as Short) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as Short) + } +} + /** * Searches array or range of array for provided element index using binary search algorithm. Array is expected to be sorted. */ diff --git a/libraries/stdlib/test/collections/ArraysJVMTest.kt b/libraries/stdlib/test/collections/ArraysJVMTest.kt index a24341c7c8b..0d69356f920 100644 --- a/libraries/stdlib/test/collections/ArraysJVMTest.kt +++ b/libraries/stdlib/test/collections/ArraysJVMTest.kt @@ -303,4 +303,68 @@ class ArraysJVMTest { expect(listOf("a"), { array("a", null).filterNotNull() }) } + test fun asListPrimitives() { + // Array of primitives + val arr = intArray(1, 2, 3, 4, 2, 5) + val list = arr.asList() + assertEquals(list, arr.toList()) + + assertTrue(2 in list) + assertFalse(0 in list) + assertTrue(list.containsAll(listOf(5, 4, 3))) + assertFalse(list.containsAll(listOf(5, 6, 3))) + + expect(1) { list.indexOf(2) } + expect(4) { list.lastIndexOf(2) } + expect(-1) { list.indexOf(6) } + + assertEquals(list.subList(3, 5), listOf(4, 2)) + + val iter = list.listIterator(2) + expect(2) { iter.nextIndex() } + expect(1) { iter.previousIndex() } + expect(3) { + iter.next() + iter.previous() + iter.next() + } + + arr[2] = 4 + assertEquals(list, arr.toList()) + + assertEquals(IntArray(0).asList(), emptyList()) + } + + test fun asListObjects() { + val arr = array("a", "b", "c", "d", "b", "e") + val list = arr.asList() + + assertEquals(list, arr.toList()) + + assertTrue("b" in list) + assertFalse("z" in list) + + expect(1) { list.indexOf("b") } + expect(4) { list.lastIndexOf("b") } + expect(-1) { list.indexOf("x") } + + assertTrue(list.containsAll(listOf("e", "d", "c"))) + assertFalse(list.containsAll(listOf("e", "x", "c"))) + + assertEquals(list.subList(3, 5), listOf("d", "b")) + + val iter = list.listIterator(2) + expect(2) { iter.nextIndex() } + expect(1) { iter.previousIndex() } + expect("c") { + iter.next() + iter.previous() + iter.next() + } + + arr[2] = "xx" + assertEquals(list, arr.toList()) + + assertEquals(Array(0, { "" }).asList(), emptyList()) + } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt index 48e4ad6f0e8..f9d9bfdf49f 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/SpecialJVM.kt @@ -151,5 +151,30 @@ fun specialJVM(): List { } } + templates add f("asList()") { + only(ArraysOfObjects, ArraysOfPrimitives) + doc { "Returns a list that wraps the original array" } + returns("List") + body(ArraysOfObjects) { + """ + return Arrays.asList(*this) + """ + } + + body(ArraysOfPrimitives) { + """ + return object : AbstractList(), RandomAccess { + override fun size(): Int = this@asList.size() + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(o: Any?): Boolean = this@asList.contains(o as T) + override fun iterator(): Iterator = this@asList.iterator() + override fun get(index: Int): T = this@asList[index] + override fun indexOf(o: Any?): Int = this@asList.indexOf(o as T) + override fun lastIndexOf(o: Any?): Int = this@asList.lastIndexOf(o as T) + } + """ + } + } + return templates } \ No newline at end of file