Decommonize collection builder implementations

This commit is contained in:
Abduqodiri Qurbonzoda
2020-04-30 11:40:17 +03:00
parent 379c6944a2
commit f3145454f2
20 changed files with 471 additions and 169 deletions
+54 -1
View File
@@ -49,22 +49,75 @@ internal actual fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<
return array return array
} }
/** /**
* Returns an immutable list containing only the specified object [element]. * Returns an immutable list containing only the specified object [element].
*/ */
public fun <T> listOf(element: T): List<T> = arrayListOf(element) public fun <T> listOf(element: T): List<T> = arrayListOf(element)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E> {
return ArrayList<E>().apply(builderAction).build()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E> {
checkBuilderCapacity(capacity)
return ArrayList<E>(capacity).apply(builderAction).build()
}
/** /**
* Returns an immutable set containing only the specified object [element]. * Returns an immutable set containing only the specified object [element].
*/ */
public fun <T> setOf(element: T): Set<T> = hashSetOf(element) public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E> {
return LinkedHashSet<E>().apply(builderAction).build()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E> {
return LinkedHashSet<E>(capacity).apply(builderAction).build()
}
/** /**
* Returns an immutable map, mapping only the specified key to the * Returns an immutable map, mapping only the specified key to the
* specified value. * specified value.
*/ */
public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = hashMapOf(pair) public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = hashMapOf(pair)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
return LinkedHashMap<K, V>().apply(builderAction).build()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
return LinkedHashMap<K, V>(capacity).apply(builderAction).build()
}
/** /**
* Fills the list with the provided [value]. * Fills the list with the provided [value].
* *
@@ -196,6 +249,6 @@ internal actual fun mapCapacity(expectedSize: Int) = expectedSize
@SinceKotlin("1.3") @SinceKotlin("1.3")
@ExperimentalStdlibApi @ExperimentalStdlibApi
@PublishedApi @PublishedApi
internal actual fun checkBuilderCapacity(capacity: Int) { internal fun checkBuilderCapacity(capacity: Int) {
require(capacity >= 0) { "capacity must be non-negative." } require(capacity >= 0) { "capacity must be non-negative." }
} }
@@ -15,6 +15,7 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
actual abstract override fun add(element: E): Boolean actual abstract override fun add(element: E): Boolean
actual override fun remove(element: E): Boolean { actual override fun remove(element: E): Boolean {
checkIsMutable()
val iterator = iterator() val iterator = iterator()
while (iterator.hasNext()) { while (iterator.hasNext()) {
if (iterator.next() == element) { if (iterator.next() == element) {
@@ -26,6 +27,7 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
} }
actual override fun addAll(elements: Collection<E>): Boolean { actual override fun addAll(elements: Collection<E>): Boolean {
checkIsMutable()
var modified = false var modified = false
for (element in elements) { for (element in elements) {
if (add(element)) modified = true if (add(element)) modified = true
@@ -33,10 +35,18 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
return modified return modified
} }
actual override fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements } actual override fun removeAll(elements: Collection<E>): Boolean {
actual override fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it !in elements } checkIsMutable()
return (this as MutableIterable<E>).removeAll { it in elements }
}
actual override fun retainAll(elements: Collection<E>): Boolean {
checkIsMutable()
return (this as MutableIterable<E>).removeAll { it !in elements }
}
actual override fun clear(): Unit { actual override fun clear(): Unit {
checkIsMutable()
val iterator = this.iterator() val iterator = this.iterator()
while (iterator.hasNext()) { while (iterator.hasNext()) {
iterator.next() iterator.next()
@@ -46,5 +56,12 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
@JsName("toJSON") @JsName("toJSON")
open fun toJSON(): Any = this.toArray() open fun toJSON(): Any = this.toArray()
/**
* This method is called every time when a mutating method is called on this mutable collection.
* Mutable collections that are built (frozen) must throw `UnsupportedOperationException`.
*/
internal open fun checkIsMutable(): Unit { }
} }
@@ -28,11 +28,13 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
* @return `true` because the list is always modified as the result of this operation. * @return `true` because the list is always modified as the result of this operation.
*/ */
actual override fun add(element: E): Boolean { actual override fun add(element: E): Boolean {
checkIsMutable()
add(size, element) add(size, element)
return true return true
} }
actual override fun addAll(index: Int, elements: Collection<E>): Boolean { actual override fun addAll(index: Int, elements: Collection<E>): Boolean {
checkIsMutable()
var _index = index var _index = index
var changed = false var changed = false
for (e in elements) { for (e in elements) {
@@ -43,11 +45,19 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
} }
actual override fun clear() { actual override fun clear() {
checkIsMutable()
removeRange(0, size) removeRange(0, size)
} }
actual override fun removeAll(elements: Collection<E>): Boolean = removeAll { it in elements } actual override fun removeAll(elements: Collection<E>): Boolean {
actual override fun retainAll(elements: Collection<E>): Boolean = removeAll { it !in elements } checkIsMutable()
return removeAll { it in elements }
}
actual override fun retainAll(elements: Collection<E>): Boolean {
checkIsMutable()
return removeAll { it !in elements }
}
actual override fun iterator(): MutableIterator<E> = IteratorImpl() actual override fun iterator(): MutableIterator<E> = IteratorImpl()
@@ -164,7 +174,7 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
override fun set(element: E) { override fun set(element: E) {
check(last != -1) { "Call next() or previous() before updating element value with the iterator." } check(last != -1) { "Call next() or previous() before updating element value with the iterator." }
this@AbstractMutableList[last] = element set(last, element)
} }
} }
@@ -204,6 +214,8 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
} }
override val size: Int get() = _size override val size: Int get() = _size
internal override fun checkIsMutable(): Unit = list.checkIsMutable()
} }
} }
@@ -30,6 +30,10 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
override val value: V get() = _value override val value: V get() = _value
override fun setValue(newValue: V): V { override fun setValue(newValue: V): V {
// Should check if the map containing this entry is mutable.
// However, to not increase entry memory footprint it might be worthwhile not to check it here and
// force subclasses that implement `build()` (freezing) operation to implement their own `MutableEntry`.
// this@AbstractMutableMap.checkIsMutable()
val oldValue = this._value val oldValue = this._value
this._value = newValue this._value = newValue
return oldValue return oldValue
@@ -67,6 +71,7 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
} }
override fun remove(element: K): Boolean { override fun remove(element: K): Boolean {
checkIsMutable()
if (containsKey(element)) { if (containsKey(element)) {
this@AbstractMutableMap.remove(element) this@AbstractMutableMap.remove(element)
return true return true
@@ -75,6 +80,8 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
} }
override val size: Int get() = this@AbstractMutableMap.size override val size: Int get() = this@AbstractMutableMap.size
override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable()
} }
} }
return _keys!! return _keys!!
@@ -83,6 +90,7 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
actual abstract override fun put(key: K, value: V): V? actual abstract override fun put(key: K, value: V): V?
actual override fun putAll(from: Map<out K, V>) { actual override fun putAll(from: Map<out K, V>) {
checkIsMutable()
for ((key, value) in from) { for ((key, value) in from) {
put(key, value) put(key, value)
} }
@@ -117,12 +125,15 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
} }
override fun hashCode(): Int = AbstractList.orderedHashCode(this) override fun hashCode(): Int = AbstractList.orderedHashCode(this)
override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable()
} }
} }
return _values!! return _values!!
} }
actual override fun remove(key: K): V? { actual override fun remove(key: K): V? {
checkIsMutable()
val iter = entries.iterator() val iter = entries.iterator()
while (iter.hasNext()) { while (iter.hasNext()) {
val entry = iter.next() val entry = iter.next()
@@ -136,4 +147,10 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
return null return null
} }
/**
* This method is called every time when a mutating method is called on this mutable map.
* Mutable maps that are built (frozen) must throw `UnsupportedOperationException`.
*/
internal open fun checkIsMutable(): Unit {}
} }
@@ -13,6 +13,7 @@ package kotlin.collections
* capacity and "growth increment" concepts. * capacity and "growth increment" concepts.
*/ */
public actual open class ArrayList<E> internal constructor(private var array: Array<Any?>) : AbstractMutableList<E>(), MutableList<E>, RandomAccess { public actual open class ArrayList<E> internal constructor(private var array: Array<Any?>) : AbstractMutableList<E>(), MutableList<E>, RandomAccess {
private var isReadOnly: Boolean = false
/** /**
* Creates an empty [ArrayList]. * Creates an empty [ArrayList].
@@ -31,6 +32,13 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
*/ */
public actual constructor(elements: Collection<E>) : this(elements.toTypedArray<Any?>()) {} public actual constructor(elements: Collection<E>) : this(elements.toTypedArray<Any?>()) {}
@PublishedApi
internal fun build(): List<E> {
checkIsMutable()
isReadOnly = true
return this
}
/** Does nothing in this ArrayList implementation. */ /** Does nothing in this ArrayList implementation. */
public actual fun trimToSize() {} public actual fun trimToSize() {}
@@ -41,23 +49,27 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
actual override fun get(index: Int): E = array[rangeCheck(index)] as E actual override fun get(index: Int): E = array[rangeCheck(index)] as E
actual override fun set(index: Int, element: E): E { actual override fun set(index: Int, element: E): E {
checkIsMutable()
rangeCheck(index) rangeCheck(index)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return array[index].apply { array[index] = element } as E return array[index].apply { array[index] = element } as E
} }
actual override fun add(element: E): Boolean { actual override fun add(element: E): Boolean {
checkIsMutable()
array.asDynamic().push(element) array.asDynamic().push(element)
modCount++ modCount++
return true return true
} }
actual override fun add(index: Int, element: E): Unit { actual override fun add(index: Int, element: E): Unit {
checkIsMutable()
array.asDynamic().splice(insertionRangeCheck(index), 0, element) array.asDynamic().splice(insertionRangeCheck(index), 0, element)
modCount++ modCount++
} }
actual override fun addAll(elements: Collection<E>): Boolean { actual override fun addAll(elements: Collection<E>): Boolean {
checkIsMutable()
if (elements.isEmpty()) return false if (elements.isEmpty()) return false
array += elements.toTypedArray<Any?>() array += elements.toTypedArray<Any?>()
@@ -66,6 +78,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
} }
actual override fun addAll(index: Int, elements: Collection<E>): Boolean { actual override fun addAll(index: Int, elements: Collection<E>): Boolean {
checkIsMutable()
insertionRangeCheck(index) insertionRangeCheck(index)
if (index == size) return addAll(elements) if (index == size) return addAll(elements)
@@ -81,6 +94,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
} }
actual override fun removeAt(index: Int): E { actual override fun removeAt(index: Int): E {
checkIsMutable()
rangeCheck(index) rangeCheck(index)
modCount++ modCount++
return if (index == lastIndex) return if (index == lastIndex)
@@ -90,6 +104,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
} }
actual override fun remove(element: E): Boolean { actual override fun remove(element: E): Boolean {
checkIsMutable()
for (index in array.indices) { for (index in array.indices) {
if (array[index] == element) { if (array[index] == element) {
array.asDynamic().splice(index, 1) array.asDynamic().splice(index, 1)
@@ -101,11 +116,13 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
} }
override fun removeRange(fromIndex: Int, toIndex: Int) { override fun removeRange(fromIndex: Int, toIndex: Int) {
checkIsMutable()
modCount++ modCount++
array.asDynamic().splice(fromIndex, toIndex - fromIndex) array.asDynamic().splice(fromIndex, toIndex - fromIndex)
} }
actual override fun clear() { actual override fun clear() {
checkIsMutable()
array = emptyArray() array = emptyArray()
modCount++ modCount++
} }
@@ -119,6 +136,10 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
override fun toArray(): Array<Any?> = js("[]").slice.call(array) override fun toArray(): Array<Any?> = js("[]").slice.call(array)
internal override fun checkIsMutable() {
if (isReadOnly) throw UnsupportedOperationException()
}
private fun rangeCheck(index: Int) = index.apply { private fun rangeCheck(index: Int) = index.apply {
AbstractList.checkElementIndex(index, size) AbstractList.checkElementIndex(index, size)
} }
@@ -16,6 +16,8 @@ import kotlin.collections.MutableMap.MutableEntry
* *
* This implementation makes no guarantees regarding the order of enumeration of [keys], [values] and [entries] collections. * This implementation makes no guarantees regarding the order of enumeration of [keys], [values] and [entries] collections.
*/ */
// Classes that extend HashMap and implement `build()` (freezing) operation
// have to make sure mutating methods check `checkIsMutable`.
public actual open class HashMap<K, V> : AbstractMutableMap<K, V>, MutableMap<K, V> { public actual open class HashMap<K, V> : AbstractMutableMap<K, V>, MutableMap<K, V> {
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() { private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
@@ -12,9 +12,11 @@ package kotlin.collections
/** /**
* The implementation of the [MutableSet] interface, backed by a [HashMap] instance. * The implementation of the [MutableSet] interface, backed by a [HashMap] instance.
*/ */
// Classes that extend HashSet and implement `build()` (freezing) operation
// have to make sure mutating methods check `checkIsMutable`.
public actual open class HashSet<E> : AbstractMutableSet<E>, MutableSet<E> { public actual open class HashSet<E> : AbstractMutableSet<E>, MutableSet<E> {
private val map: HashMap<E, Any> internal val map: HashMap<E, Any>
/** /**
* Constructs a new empty [HashSet]. * Constructs a new empty [HashSet].
@@ -30,9 +30,14 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
* small modifications. Paying a small storage cost only if you use * small modifications. Paying a small storage cost only if you use
* LinkedHashMap and minimizing code size seemed like a better tradeoff * LinkedHashMap and minimizing code size seemed like a better tradeoff
*/ */
private class ChainEntry<K, V>(key: K, value: V) : AbstractMutableMap.SimpleEntry<K, V>(key, value) { private inner class ChainEntry<K, V>(key: K, value: V) : AbstractMutableMap.SimpleEntry<K, V>(key, value) {
internal var next: ChainEntry<K, V>? = null internal var next: ChainEntry<K, V>? = null
internal var prev: ChainEntry<K, V>? = null internal var prev: ChainEntry<K, V>? = null
override fun setValue(newValue: V): V {
this@LinkedHashMap.checkIsMutable()
return super.setValue(newValue)
}
} }
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() { private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
@@ -65,6 +70,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
override fun remove() { override fun remove() {
check(last != null) check(last != null)
this@EntrySet.checkIsMutable()
// checkStructuralChange(map, this) // checkStructuralChange(map, this)
last!!.remove() last!!.remove()
@@ -84,6 +90,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = EntryIterator() override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = EntryIterator()
override fun remove(element: MutableEntry<K, V>): Boolean { override fun remove(element: MutableEntry<K, V>): Boolean {
checkIsMutable()
if (contains(element)) { if (contains(element)) {
this@LinkedHashMap.remove(element.key) this@LinkedHashMap.remove(element.key)
return true return true
@@ -92,6 +99,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
} }
override val size: Int get() = this@LinkedHashMap.size override val size: Int get() = this@LinkedHashMap.size
override fun checkIsMutable(): Unit = this@LinkedHashMap.checkIsMutable()
} }
@@ -154,6 +163,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
*/ */
private val map: HashMap<K, ChainEntry<K, V>> private val map: HashMap<K, ChainEntry<K, V>>
private var isReadOnly: Boolean = false
/** /**
* Constructs an empty [LinkedHashMap] instance. * Constructs an empty [LinkedHashMap] instance.
*/ */
@@ -189,7 +200,15 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
this.putAll(original) this.putAll(original)
} }
@PublishedApi
internal fun build(): Map<K, V> {
checkIsMutable()
isReadOnly = true
return this
}
actual override fun clear() { actual override fun clear() {
checkIsMutable()
map.clear() map.clear()
head = null head = null
} }
@@ -219,6 +238,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
actual override operator fun get(key: K): V? = map.get(key)?.value actual override operator fun get(key: K): V? = map.get(key)?.value
actual override fun put(key: K, value: V): V? { actual override fun put(key: K, value: V): V? {
checkIsMutable()
val old = map.get(key) val old = map.get(key)
if (old == null) { if (old == null) {
val newEntry = ChainEntry(key, value) val newEntry = ChainEntry(key, value)
@@ -231,6 +252,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
} }
actual override fun remove(key: K): V? { actual override fun remove(key: K): V? {
checkIsMutable()
val entry = map.remove(key) val entry = map.remove(key)
if (entry != null) { if (entry != null) {
entry.remove() entry.remove()
@@ -241,6 +264,9 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
actual override val size: Int get() = map.size actual override val size: Int get() = map.size
internal override fun checkIsMutable() {
if (isReadOnly) throw UnsupportedOperationException()
}
} }
/** /**
@@ -43,6 +43,14 @@ public actual open class LinkedHashSet<E> : HashSet<E>, MutableSet<E> {
actual constructor(initialCapacity: Int) : this(initialCapacity, 0.0f) actual constructor(initialCapacity: Int) : this(initialCapacity, 0.0f)
@PublishedApi
internal fun build(): Set<E> {
(map as LinkedHashMap<E, Any>).build()
return this
}
internal override fun checkIsMutable(): Unit = map.checkIsMutable()
// public override fun clone(): Any { // public override fun clone(): Any {
// return LinkedHashSet(this) // return LinkedHashSet(this)
// } // }
@@ -8,6 +8,7 @@
package kotlin.collections package kotlin.collections
import kotlin.collections.builders.ListBuilder
import kotlin.internal.InlineOnly import kotlin.internal.InlineOnly
import kotlin.internal.apiVersionIsAtLeast import kotlin.internal.apiVersionIsAtLeast
@@ -18,6 +19,42 @@ import kotlin.internal.apiVersionIsAtLeast
*/ */
public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element) public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E> {
return build(createListBuilder<E>().apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E> {
return build(createListBuilder<E>(capacity).apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> createListBuilder(): MutableList<E> {
return ListBuilder<E>()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> createListBuilder(capacity: Int): MutableList<E> {
return ListBuilder<E>(capacity)
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> build(builder: MutableList<E>): List<E> {
return (builder as ListBuilder<E>).build()
}
/** /**
* Returns a list containing the elements returned by this enumeration * Returns a list containing the elements returned by this enumeration
@@ -9,11 +9,11 @@
package kotlin.collections package kotlin.collections
import java.util.Comparator import java.util.Comparator
import java.util.LinkedHashMap
import java.util.Properties import java.util.Properties
import java.util.SortedMap import java.util.SortedMap
import java.util.TreeMap import java.util.TreeMap
import java.util.concurrent.ConcurrentMap import java.util.concurrent.ConcurrentMap
import kotlin.collections.builders.MapBuilder
/** /**
@@ -26,6 +26,43 @@ import java.util.concurrent.ConcurrentMap
*/ */
public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = java.util.Collections.singletonMap(pair.first, pair.second) public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = java.util.Collections.singletonMap(pair.first, pair.second)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
return build(createMapBuilder<K, V>().apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
return build(createMapBuilder<K, V>(capacity).apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <K, V> createMapBuilder(): MutableMap<K, V> {
return MapBuilder()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <K, V> createMapBuilder(capacity: Int): MutableMap<K, V> {
return MapBuilder(capacity)
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <K, V> build(builder: MutableMap<K, V>): Map<K, V> {
return (builder as MapBuilder<K, V>).build()
}
/** /**
* Concurrent getOrPut, that is safe for concurrent maps. * Concurrent getOrPut, that is safe for concurrent maps.
@@ -111,13 +148,3 @@ internal actual fun mapCapacity(expectedSize: Int): Int = when {
else -> Int.MAX_VALUE else -> Int.MAX_VALUE
} }
private const val INT_MAX_POWER_OF_TWO: Int = 1 shl (Int.SIZE_BITS - 2) private const val INT_MAX_POWER_OF_TWO: Int = 1 shl (Int.SIZE_BITS - 2)
/**
* Checks a collection builder function capacity argument.
* Does nothing, capacity is validated in List/Set/Map constructor
*/
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@PublishedApi
@kotlin.internal.InlineOnly
internal actual inline fun checkBuilderCapacity(capacity: Int) {}
@@ -8,6 +8,8 @@
package kotlin.collections package kotlin.collections
import kotlin.collections.builders.SetBuilder
/** /**
* Returns an immutable set containing only the specified object [element]. * Returns an immutable set containing only the specified object [element].
@@ -15,6 +17,43 @@ package kotlin.collections
*/ */
public fun <T> setOf(element: T): Set<T> = java.util.Collections.singleton(element) public fun <T> setOf(element: T): Set<T> = java.util.Collections.singleton(element)
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E> {
return build(createSetBuilder<E>().apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal actual inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E> {
return build(createSetBuilder<E>(capacity).apply(builderAction))
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> createSetBuilder(): MutableSet<E> {
return SetBuilder()
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> createSetBuilder(capacity: Int): MutableSet<E> {
return SetBuilder(capacity)
}
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
internal fun <E> build(builder: MutableSet<E>): Set<E> {
return (builder as SetBuilder<E>).build()
}
/** /**
* Returns a new [java.util.SortedSet] with the given elements. * Returns a new [java.util.SortedSet] with the given elements.
@@ -5,19 +5,19 @@
package kotlin.collections.builders package kotlin.collections.builders
@PublishedApi
internal class ListBuilder<E> private constructor( internal class ListBuilder<E> private constructor(
private var array: Array<E>, private var array: Array<E>,
private var offset: Int, private var offset: Int,
private var length: Int, private var length: Int,
private var isReadOnly: Boolean, private var isReadOnly: Boolean,
private val backing: ListBuilder<E>? private val backing: ListBuilder<E>?,
private val root: ListBuilder<E>?
) : MutableList<E>, RandomAccess, AbstractMutableList<E>() { ) : MutableList<E>, RandomAccess, AbstractMutableList<E>() {
constructor() : this(10) constructor() : this(10)
constructor(initialCapacity: Int) : this( constructor(initialCapacity: Int) : this(
arrayOfUninitializedElements(initialCapacity), 0, 0, false, null) arrayOfUninitializedElements(initialCapacity), 0, 0, false, null, null)
fun build(): List<E> { fun build(): List<E> {
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ListBuilder if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ListBuilder
@@ -127,7 +127,7 @@ internal class ListBuilder<E> private constructor(
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> { override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
AbstractList.checkRangeIndexes(fromIndex, toIndex, length) AbstractList.checkRangeIndexes(fromIndex, toIndex, length)
return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this) return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this, root ?: this)
} }
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
@@ -155,7 +155,7 @@ internal class ListBuilder<E> private constructor(
// ---------------------------- private ---------------------------- // ---------------------------- private ----------------------------
private fun checkIsMutable() { private fun checkIsMutable() {
if (isReadOnly) throw UnsupportedOperationException() if (isReadOnly || root != null && root.isReadOnly) throw UnsupportedOperationException()
} }
private fun ensureExtraCapacity(n: Int) { private fun ensureExtraCapacity(n: Int) {
@@ -277,9 +277,8 @@ internal class ListBuilder<E> private constructor(
} }
override fun set(element: E) { override fun set(element: E) {
list.checkIsMutable()
check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." } check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." }
list.array[list.offset + lastIndex] = element list.set(lastIndex, element)
} }
override fun add(element: E) { override fun add(element: E) {
@@ -5,7 +5,6 @@
package kotlin.collections.builders package kotlin.collections.builders
@PublishedApi
internal class MapBuilder<K, V> private constructor( internal class MapBuilder<K, V> private constructor(
private var keysArray: Array<K>, private var keysArray: Array<K>,
private var valuesArray: Array<V>?, // allocated only when actually used, always null in pure HashSet private var valuesArray: Array<V>?, // allocated only when actually used, always null in pure HashSet
@@ -19,9 +18,9 @@ internal class MapBuilder<K, V> private constructor(
override var size: Int = 0 override var size: Int = 0
private set private set
private var keysView: HashMapKeys<K>? = null private var keysView: MapBuilderKeys<K>? = null
private var valuesView: HashMapValues<V>? = null private var valuesView: MapBuilderValues<V>? = null
private var entriesView: HashMapEntrySet<K, V>? = null private var entriesView: MapBuilderEntries<K, V>? = null
private var isReadOnly: Boolean = false private var isReadOnly: Boolean = false
@@ -68,7 +67,8 @@ internal class MapBuilder<K, V> private constructor(
} }
override fun putAll(from: Map<out K, V>) { override fun putAll(from: Map<out K, V>) {
putAllEntries(from.entries) // mutability gets checked here checkIsMutable()
putAllEntries(from.entries)
} }
override fun remove(key: K): V? { override fun remove(key: K): V? {
@@ -99,7 +99,7 @@ internal class MapBuilder<K, V> private constructor(
override val keys: MutableSet<K> get() { override val keys: MutableSet<K> get() {
val cur = keysView val cur = keysView
return if (cur == null) { return if (cur == null) {
val new = HashMapKeys(this) val new = MapBuilderKeys(this)
keysView = new keysView = new
new new
} else cur } else cur
@@ -108,7 +108,7 @@ internal class MapBuilder<K, V> private constructor(
override val values: MutableCollection<V> get() { override val values: MutableCollection<V> get() {
val cur = valuesView val cur = valuesView
return if (cur == null) { return if (cur == null) {
val new = HashMapValues(this) val new = MapBuilderValues(this)
valuesView = new valuesView = new
new new
} else cur } else cur
@@ -117,7 +117,7 @@ internal class MapBuilder<K, V> private constructor(
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() { override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() {
val cur = entriesView val cur = entriesView
return if (cur == null) { return if (cur == null) {
val new = HashMapEntrySet(this) val new = MapBuilderEntries(this)
entriesView = new entriesView = new
return new return new
} else cur } else cur
@@ -157,7 +157,7 @@ internal class MapBuilder<K, V> private constructor(
private val capacity: Int get() = keysArray.size private val capacity: Int get() = keysArray.size
private val hashSize: Int get() = hashArray.size private val hashSize: Int get() = hashArray.size
private fun checkIsMutable() { internal fun checkIsMutable() {
if (isReadOnly) throw UnsupportedOperationException() if (isReadOnly) throw UnsupportedOperationException()
} }
@@ -382,8 +382,7 @@ internal class MapBuilder<K, V> private constructor(
return true return true
} }
internal fun putEntry(entry: Map.Entry<K, V>): Boolean { private fun putEntry(entry: Map.Entry<K, V>): Boolean {
checkIsMutable()
val index = addKey(entry.key) val index = addKey(entry.key)
val valuesArray = allocateValuesArray() val valuesArray = allocateValuesArray()
if (index >= 0) { if (index >= 0) {
@@ -398,8 +397,7 @@ internal class MapBuilder<K, V> private constructor(
return false return false
} }
internal fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean { private fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean {
checkIsMutable()
if (from.isEmpty()) return false if (from.isEmpty()) return false
ensureExtraCapacity(from.size) ensureExtraCapacity(from.size)
val it = from.iterator() val it = from.iterator()
@@ -549,7 +547,7 @@ internal class MapBuilder<K, V> private constructor(
} }
} }
internal class HashMapKeys<E> internal constructor( internal class MapBuilderKeys<E> internal constructor(
private val backing: MapBuilder<E, *> private val backing: MapBuilder<E, *>
) : MutableSet<E>, AbstractMutableSet<E>() { ) : MutableSet<E>, AbstractMutableSet<E>() {
@@ -561,9 +559,19 @@ internal class HashMapKeys<E> internal constructor(
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException() override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0 override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
override fun iterator(): MutableIterator<E> = backing.keysIterator() override fun iterator(): MutableIterator<E> = backing.keysIterator()
override fun removeAll(elements: Collection<E>): Boolean {
backing.checkIsMutable()
return super.removeAll(elements)
}
override fun retainAll(elements: Collection<E>): Boolean {
backing.checkIsMutable()
return super.retainAll(elements)
}
} }
internal class HashMapValues<V> internal constructor( internal class MapBuilderValues<V> internal constructor(
val backing: MapBuilder<*, V> val backing: MapBuilder<*, V>
) : MutableCollection<V>, AbstractMutableCollection<V>() { ) : MutableCollection<V>, AbstractMutableCollection<V>() {
@@ -575,9 +583,19 @@ internal class HashMapValues<V> internal constructor(
override fun clear() = backing.clear() override fun clear() = backing.clear()
override fun iterator(): MutableIterator<V> = backing.valuesIterator() override fun iterator(): MutableIterator<V> = backing.valuesIterator()
override fun remove(element: V): Boolean = backing.removeValue(element) override fun remove(element: V): Boolean = backing.removeValue(element)
override fun removeAll(elements: Collection<V>): Boolean {
backing.checkIsMutable()
return super.removeAll(elements)
}
override fun retainAll(elements: Collection<V>): Boolean {
backing.checkIsMutable()
return super.retainAll(elements)
}
} }
internal class HashMapEntrySet<K, V> internal constructor( internal class MapBuilderEntries<K, V> internal constructor(
val backing: MapBuilder<K, V> val backing: MapBuilder<K, V>
) : MutableSet<MutableMap.MutableEntry<K, V>>, AbstractMutableSet<MutableMap.MutableEntry<K, V>>() { ) : MutableSet<MutableMap.MutableEntry<K, V>>, AbstractMutableSet<MutableMap.MutableEntry<K, V>>() {
@@ -585,9 +603,19 @@ internal class HashMapEntrySet<K, V> internal constructor(
override fun isEmpty(): Boolean = backing.isEmpty() override fun isEmpty(): Boolean = backing.isEmpty()
override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = backing.containsEntry(element) override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = backing.containsEntry(element)
override fun clear() = backing.clear() override fun clear() = backing.clear()
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = backing.putEntry(element) override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = throw UnsupportedOperationException()
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = throw UnsupportedOperationException()
override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean = backing.removeEntry(element) override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean = backing.removeEntry(element)
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = backing.entriesIterator() override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = backing.entriesIterator()
override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.containsAllEntries(elements) override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.containsAllEntries(elements)
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.putAllEntries(elements)
override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
backing.checkIsMutable()
return super.removeAll(elements)
}
override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
backing.checkIsMutable()
return super.retainAll(elements)
}
} }
@@ -5,7 +5,6 @@
package kotlin.collections.builders package kotlin.collections.builders
@PublishedApi
internal class SetBuilder<E> internal constructor( internal class SetBuilder<E> internal constructor(
private val backing: MapBuilder<E, *> private val backing: MapBuilder<E, *>
) : MutableSet<E>, AbstractMutableSet<E>() { ) : MutableSet<E>, AbstractMutableSet<E>() {
@@ -26,4 +25,19 @@ internal class SetBuilder<E> internal constructor(
override fun add(element: E): Boolean = backing.addKey(element) >= 0 override fun add(element: E): Boolean = backing.addKey(element) >= 0
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0 override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
override fun iterator(): MutableIterator<E> = backing.keysIterator() override fun iterator(): MutableIterator<E> = backing.keysIterator()
override fun addAll(elements: Collection<E>): Boolean {
backing.checkIsMutable()
return super.addAll(elements)
}
override fun removeAll(elements: Collection<E>): Boolean {
backing.checkIsMutable()
return super.removeAll(elements)
}
override fun retainAll(elements: Collection<E>): Boolean {
backing.checkIsMutable()
return super.retainAll(elements)
}
} }
@@ -11,7 +11,6 @@ package kotlin.collections
import kotlin.contracts.* import kotlin.contracts.*
import kotlin.random.Random import kotlin.random.Random
import kotlin.collections.builders.*
internal object EmptyIterator : ListIterator<Nothing> { internal object EmptyIterator : ListIterator<Nothing> {
override fun hasNext(): Boolean = false override fun hasNext(): Boolean = false
@@ -170,9 +169,15 @@ public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableLi
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> { public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return ListBuilder<E>().apply(builderAction).build() return buildListInternal(builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E>
/** /**
* Builds a new read-only [List] by populating a [MutableList] using the given [builderAction] * Builds a new read-only [List] by populating a [MutableList] using the given [builderAction]
* and returning a read-only list with the same elements. * and returning a read-only list with the same elements.
@@ -191,9 +196,14 @@ public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <E> buildList(capacity: Int, @BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> { public inline fun <E> buildList(capacity: Int, @BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return ListBuilder<E>(capacity).apply(builderAction).build() return buildListInternal(capacity, builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E>
/** /**
* Returns an [IntRange] of the valid indices for this collection. * Returns an [IntRange] of the valid indices for this collection.
+14 -11
View File
@@ -9,7 +9,6 @@
package kotlin.collections package kotlin.collections
import kotlin.collections.builders.MapBuilder
import kotlin.contracts.* import kotlin.contracts.*
private object EmptyMap : Map<Any?, Nothing>, Serializable { private object EmptyMap : Map<Any?, Nothing>, Serializable {
@@ -140,9 +139,15 @@ public fun <K, V> linkedMapOf(vararg pairs: Pair<K, V>): LinkedHashMap<K, V> = p
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <K, V> buildMap(@BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> { public inline fun <K, V> buildMap(@BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return MapBuilder<K, V>().apply(builderAction).build() return buildMapInternal(builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V>
/** /**
* Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction] * Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction]
* and returning a read-only map with the same key-value pairs. * and returning a read-only map with the same key-value pairs.
@@ -163,23 +168,21 @@ public inline fun <K, V> buildMap(@BuilderInference builderAction: MutableMap<K,
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <K, V> buildMap(capacity: Int, @BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> { public inline fun <K, V> buildMap(capacity: Int, @BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return MapBuilder<K, V>(capacity).apply(builderAction).build() return buildMapInternal(capacity, builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V>
/** /**
* Calculate the initial capacity of a map. * Calculate the initial capacity of a map.
*/ */
@PublishedApi @PublishedApi
internal expect fun mapCapacity(expectedSize: Int): Int internal expect fun mapCapacity(expectedSize: Int): Int
/**
* Checks a collection builder function capacity argument.
*/
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@PublishedApi
internal expect fun checkBuilderCapacity(capacity: Int)
/** /**
* Returns `true` if this map is not empty. * Returns `true` if this map is not empty.
* @sample samples.collections.Maps.Usage.mapIsNotEmpty * @sample samples.collections.Maps.Usage.mapIsNotEmpty
@@ -10,7 +10,6 @@
package kotlin.collections package kotlin.collections
import kotlin.contracts.* import kotlin.contracts.*
import kotlin.collections.builders.*
internal object EmptySet : Set<Nothing>, Serializable { internal object EmptySet : Set<Nothing>, Serializable {
private const val serialVersionUID: Long = 3406603774387020532 private const val serialVersionUID: Long = 3406603774387020532
@@ -126,9 +125,15 @@ public fun <T : Any> setOfNotNull(vararg elements: T?): Set<T> {
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> { public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return SetBuilder<E>().apply(builderAction).build() return buildSetInternal(builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E>
/** /**
* Builds a new read-only [Set] by populating a [MutableSet] using the given [builderAction] * Builds a new read-only [Set] by populating a [MutableSet] using the given [builderAction]
* and returning a read-only set with the same elements. * and returning a read-only set with the same elements.
@@ -149,9 +154,15 @@ public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.()
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
public inline fun <E> buildSet(capacity: Int, @BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> { public inline fun <E> buildSet(capacity: Int, @BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return SetBuilder<E>(capacity).apply(builderAction).build() return buildSetInternal(capacity, builderAction)
} }
@PublishedApi
@SinceKotlin("1.3")
@ExperimentalStdlibApi
@kotlin.internal.InlineOnly
internal expect inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E>
/** Returns this Set if it's not `null` and the empty set otherwise. */ /** Returns this Set if it's not `null` and the empty set otherwise. */
@kotlin.internal.InlineOnly @kotlin.internal.InlineOnly
@@ -6,35 +6,55 @@ import test.collections.behaviors.setBehavior
import kotlin.test.* import kotlin.test.*
class ContainerBuilderTest { class ContainerBuilderTest {
private fun <E> mutableCollectionOperations(e: E) = listOf<MutableCollection<E>.() -> Unit>( private fun <E> mutableCollectionOperations(present: E, absent: E) = listOf<Pair<String, MutableCollection<E>.() -> Unit>>(
{ add(e) }, "add(present)" to { add(present) },
{ addAll(listOf(e)) }, "add(absent)" to { add(absent) },
{ remove(e) },
{ removeAll(listOf(e)) }, "addAll(listOf(present))" to { addAll(listOf(present)) },
{ retainAll(listOf(e)) }, "addAll(listOf(absent))" to { addAll(listOf(absent)) },
{ clear() }, "addAll(emptyList())" to { addAll(emptyList()) },
{ iterator().apply { next() }.remove() }
"remove(present)" to { remove(present) },
"remove(absent)" to { remove(absent) },
"removeAll(listOf(present))" to { removeAll(listOf(present)) },
"removeAll(emptyList())" to { removeAll(emptyList()) },
"removeAll(this.toList())" to { removeAll(this.toList()) },
"retainAll(listOf(present))" to { retainAll(listOf(present)) },
"retainAll(emptyList())" to { retainAll(emptyList()) },
"retainAll(this.toList())" to { retainAll(this.toList()) },
"clear()" to { clear() },
"iterator().apply { next() }.remove()" to { iterator().apply { next() }.remove() }
) )
private fun <E> mutableListOperations(e: E) = mutableCollectionOperations(e) + listOf<MutableList<E>.() -> Unit>( private fun <E> mutableListOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableList<E>.() -> Unit>>(
{ add(0, e) }, "add(0, present)" to { add(0, present) },
{ addAll(0, listOf(e)) }, "addAll(0, listOf(present))" to { addAll(0, listOf(present)) },
{ removeAt(0) }, "addAll(0, emptyList())" to { addAll(0, emptyList()) },
{ set(0, e) }, "removeAt(0)" to { removeAt(0) },
{ listIterator().apply { next() }.remove() }, "set(0, present)" to { set(0, present) },
{ listIterator(0).apply { next() }.remove() }, "listIterator().apply { next() }.remove()" to { listIterator().apply { next() }.remove() },
{ listIterator().add(e) } "listIterator(0).apply { next() }.remove()" to { listIterator(0).apply { next() }.remove() },
"listIterator().apply { next() }.set(present)" to { listIterator().apply { next() }.set(present) },
"listIterator().add(present)" to { listIterator().add(present) }
) )
private fun <E> mutableSetOperations(e: E): List<MutableSet<E>.() -> Unit> = mutableCollectionOperations(e) private fun <E> mutableSetOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableSet<E>.() -> Unit>>(
// check java.util.AbstractSet.removeAll optimisation
"removeAll(List(this.size) { absent })" to { removeAll(List(this.size) { absent }) }
)
private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<MutableMap<K, V>.() -> Unit>( private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<Pair<String, MutableMap<K, V>.() -> Unit>>(
{ put(k, v) }, "put(k, v)" to { put(k, v) },
{ remove(k) }, "remove(k)" to { remove(k) },
{ putAll(mapOf(k to v)) }, "putAll(mapOf(k to v))" to { putAll(mapOf(k to v)) },
{ clear() }, "putAll(emptyMap())" to { putAll(emptyMap()) },
{ entries.first().setValue(v) }, "clear()" to { clear() },
{ entries.iterator().next().setValue(v) } "entries.first().setValue(v)" to { entries.first().setValue(v) },
"entries.iterator().next().setValue(v)" to { entries.iterator().next().setValue(v) }
) )
@Test @Test
@@ -44,10 +64,14 @@ class ContainerBuilderTest {
add('c') add('c')
} }
val y = buildList(4) { val subList: MutableList<Char>
val y = buildList<Char>(4) {
add('a') add('a')
addAll(x) addAll(x)
add('d') add('d')
subList = subList(0, 4)
} }
compare(listOf('a', 'b', 'c', 'd'), y) { listBehavior() } compare(listOf('a', 'b', 'c', 'd'), y) { listBehavior() }
@@ -60,9 +84,10 @@ class ContainerBuilderTest {
} }
assertTrue(y is MutableList<Char>) assertTrue(y is MutableList<Char>)
for (operation in mutableListOperations('a')) { for ((fName, operation) in mutableListOperations('b', 'x')) {
assertFailsWith<UnsupportedOperationException> { y.operation() } assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
assertFailsWith<UnsupportedOperationException> { y.subList(1, 3).operation() } assertFailsWith<UnsupportedOperationException>("y.subList(1, 3).$fName") { y.subList(1, 3).operation() }
assertFailsWith<UnsupportedOperationException>("subList.$fName") { subList.operation() }
} }
} }
@@ -90,10 +115,12 @@ class ContainerBuilderTest {
val subSubList = subList.subList(2, 4) val subSubList = subList.subList(2, 4)
// buffer reallocation should happen // buffer reallocation should happen
repeat(20) { subSubList.add('x') } repeat(20) { subSubList.add('x') }
repeat(20) { subSubList.add(subSubList.size - 2 * it, 'y') }
compare("ab123${"x".repeat(20)}e".toList(), this) { listBehavior() } val addedChars = "xy".repeat(20)
compare("b123${"x".repeat(20)}".toList(), subList) { listBehavior() } compare("ab123${addedChars}e".toList(), this) { listBehavior() }
compare("23${"x".repeat(20)}".toList(), subSubList) { listBehavior() } compare("b123$addedChars".toList(), subList) { listBehavior() }
compare("23$addedChars".toList(), subSubList) { listBehavior() }
} }
} }
@@ -118,8 +145,8 @@ class ContainerBuilderTest {
} }
assertTrue(y is MutableSet<Char>) assertTrue(y is MutableSet<Char>)
for (operation in mutableSetOperations('b')) { for ((fName, operation) in mutableSetOperations('b', 'x')) {
assertFailsWith<UnsupportedOperationException> { y.operation() } assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
} }
} }
@@ -145,17 +172,23 @@ class ContainerBuilderTest {
} }
assertTrue(y is MutableMap<Char, Int>) assertTrue(y is MutableMap<Char, Int>)
for (operation in mutableMapOperations('a', 0)) { for ((fName, operation) in mutableMapOperations('a', 1) + mutableMapOperations('x', 10)) {
assertFailsWith<UnsupportedOperationException> { y.operation() } assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
} }
for (operation in mutableSetOperations('a')) { for ((fName, operation) in mutableSetOperations('a', 'x')) {
assertFailsWith<UnsupportedOperationException> { y.keys.operation() } assertFailsWith<UnsupportedOperationException>("y.keys.$fName") { y.keys.operation() }
} }
for (operation in mutableCollectionOperations(1)) { for ((fName, operation) in mutableCollectionOperations(1, 10)) {
assertFailsWith<UnsupportedOperationException> { y.values.operation() } assertFailsWith<UnsupportedOperationException>("y.values.$fName") { y.values.operation() }
} }
for (operation in mutableSetOperations(y.entries.first())) { val presentEntry = y.entries.first()
assertFailsWith<UnsupportedOperationException> { y.entries.operation() } val absentEntry: MutableMap.MutableEntry<Char, Int> = object : MutableMap.MutableEntry<Char, Int> {
override val key: Char get() = 'x'
override val value: Int get() = 10
override fun setValue(newValue: Int): Int = fail("Unreachable")
}
for ((fName, operation) in mutableSetOperations(presentEntry, absentEntry)) {
assertFailsWith<UnsupportedOperationException>("y.entries.$fName") { y.entries.operation() }
} }
} }
} }
@@ -2082,6 +2082,7 @@ public final class kotlin/collections/CollectionsKt {
public static synthetic fun binarySearch$default (Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;IIILjava/lang/Object;)I public static synthetic fun binarySearch$default (Ljava/util/List;Ljava/lang/Object;Ljava/util/Comparator;IIILjava/lang/Object;)I
public static final fun binarySearchBy (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;)I public static final fun binarySearchBy (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;)I
public static synthetic fun binarySearchBy$default (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I public static synthetic fun binarySearchBy$default (Ljava/util/List;Ljava/lang/Comparable;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
public static final fun build (Ljava/util/List;)Ljava/util/List;
public static final fun chunked (Ljava/lang/Iterable;I)Ljava/util/List; public static final fun chunked (Ljava/lang/Iterable;I)Ljava/util/List;
public static final fun chunked (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun chunked (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun collectionSizeOrDefault (Ljava/lang/Iterable;I)I public static final fun collectionSizeOrDefault (Ljava/lang/Iterable;I)I
@@ -2089,6 +2090,8 @@ public final class kotlin/collections/CollectionsKt {
public static final fun contains (Ljava/lang/Iterable;Ljava/lang/Object;)Z public static final fun contains (Ljava/lang/Iterable;Ljava/lang/Object;)Z
public static final fun count (Ljava/lang/Iterable;)I public static final fun count (Ljava/lang/Iterable;)I
public static final fun count (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)I public static final fun count (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)I
public static final fun createListBuilder ()Ljava/util/List;
public static final fun createListBuilder (I)Ljava/util/List;
public static final fun distinct (Ljava/lang/Iterable;)Ljava/util/List; public static final fun distinct (Ljava/lang/Iterable;)Ljava/util/List;
public static final fun distinctBy (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun distinctBy (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun drop (Ljava/lang/Iterable;I)Ljava/util/List; public static final fun drop (Ljava/lang/Iterable;I)Ljava/util/List;
@@ -2369,7 +2372,10 @@ public final class kotlin/collections/MapsKt {
public static final fun any (Ljava/util/Map;)Z public static final fun any (Ljava/util/Map;)Z
public static final fun any (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Z public static final fun any (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Z
public static final fun asSequence (Ljava/util/Map;)Lkotlin/sequences/Sequence; public static final fun asSequence (Ljava/util/Map;)Lkotlin/sequences/Sequence;
public static final fun build (Ljava/util/Map;)Ljava/util/Map;
public static final fun count (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)I public static final fun count (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)I
public static final fun createMapBuilder ()Ljava/util/Map;
public static final fun createMapBuilder (I)Ljava/util/Map;
public static final fun emptyMap ()Ljava/util/Map; public static final fun emptyMap ()Ljava/util/Map;
public static final fun filter (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun filter (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
public static final fun filterKeys (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun filterKeys (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
@@ -2434,6 +2440,9 @@ public final class kotlin/collections/MapsKt {
} }
public final class kotlin/collections/SetsKt { public final class kotlin/collections/SetsKt {
public static final fun build (Ljava/util/Set;)Ljava/util/Set;
public static final fun createSetBuilder ()Ljava/util/Set;
public static final fun createSetBuilder (I)Ljava/util/Set;
public static final fun emptySet ()Ljava/util/Set; public static final fun emptySet ()Ljava/util/Set;
public static final fun hashSetOf ([Ljava/lang/Object;)Ljava/util/HashSet; public static final fun hashSetOf ([Ljava/lang/Object;)Ljava/util/HashSet;
public static final fun linkedSetOf ([Ljava/lang/Object;)Ljava/util/LinkedHashSet; public static final fun linkedSetOf ([Ljava/lang/Object;)Ljava/util/LinkedHashSet;
@@ -2505,72 +2514,6 @@ public abstract class kotlin/collections/UShortIterator : java/util/Iterator, ko
public fun remove ()V public fun remove ()V
} }
public final class kotlin/collections/builders/ListBuilder : kotlin/collections/AbstractMutableList, java/util/List, java/util/RandomAccess, kotlin/jvm/internal/markers/KMutableList {
public fun <init> ()V
public fun <init> (I)V
public fun add (ILjava/lang/Object;)V
public fun add (Ljava/lang/Object;)Z
public fun addAll (ILjava/util/Collection;)Z
public fun addAll (Ljava/util/Collection;)Z
public final fun build ()Ljava/util/List;
public fun clear ()V
public fun equals (Ljava/lang/Object;)Z
public fun get (I)Ljava/lang/Object;
public fun getSize ()I
public fun hashCode ()I
public fun indexOf (Ljava/lang/Object;)I
public fun isEmpty ()Z
public fun iterator ()Ljava/util/Iterator;
public fun lastIndexOf (Ljava/lang/Object;)I
public fun listIterator ()Ljava/util/ListIterator;
public fun listIterator (I)Ljava/util/ListIterator;
public fun remove (Ljava/lang/Object;)Z
public fun removeAll (Ljava/util/Collection;)Z
public fun removeAt (I)Ljava/lang/Object;
public fun retainAll (Ljava/util/Collection;)Z
public fun set (ILjava/lang/Object;)Ljava/lang/Object;
public fun subList (II)Ljava/util/List;
public fun toString ()Ljava/lang/String;
}
public final class kotlin/collections/builders/MapBuilder : java/util/Map, kotlin/jvm/internal/markers/KMutableMap {
public fun <init> ()V
public fun <init> (I)V
public final fun build ()Ljava/util/Map;
public fun clear ()V
public fun containsKey (Ljava/lang/Object;)Z
public fun containsValue (Ljava/lang/Object;)Z
public final fun entrySet ()Ljava/util/Set;
public fun equals (Ljava/lang/Object;)Z
public fun get (Ljava/lang/Object;)Ljava/lang/Object;
public fun getEntries ()Ljava/util/Set;
public fun getKeys ()Ljava/util/Set;
public fun getSize ()I
public fun getValues ()Ljava/util/Collection;
public fun hashCode ()I
public fun isEmpty ()Z
public final fun keySet ()Ljava/util/Set;
public fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
public fun putAll (Ljava/util/Map;)V
public fun remove (Ljava/lang/Object;)Ljava/lang/Object;
public final fun size ()I
public fun toString ()Ljava/lang/String;
public final fun values ()Ljava/util/Collection;
}
public final class kotlin/collections/builders/SetBuilder : kotlin/collections/AbstractMutableSet, java/util/Set, kotlin/jvm/internal/markers/KMutableSet {
public fun <init> ()V
public fun <init> (I)V
public fun add (Ljava/lang/Object;)Z
public final fun build ()Ljava/util/Set;
public fun clear ()V
public fun contains (Ljava/lang/Object;)Z
public fun getSize ()I
public fun isEmpty ()Z
public fun iterator ()Ljava/util/Iterator;
public fun remove (Ljava/lang/Object;)Z
}
public final class kotlin/collections/unsigned/UArraysKt { public final class kotlin/collections/unsigned/UArraysKt {
public static final fun asList--ajY-9A ([I)Ljava/util/List; public static final fun asList--ajY-9A ([I)Ljava/util/List;
public static final fun asList-GBYM_sE ([B)Ljava/util/List; public static final fun asList-GBYM_sE ([B)Ljava/util/List;