Make AbstractMutableCollections satisfy expect declarations from common

- Add actuals to AbstractMutableCollection
- Add hashCode/equals to AbstractMutableSet
- Take implementation of AbstractMutableMap from JS
This commit is contained in:
Ilya Gorbunov
2018-11-02 04:34:09 +03:00
committed by Vasily Levchenko
parent 91aba74f1d
commit 7d9ec09c9d
4 changed files with 173 additions and 54 deletions
@@ -10,7 +10,7 @@ package kotlin.collections
*
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
*/
public abstract class AbstractMutableCollection<E> protected constructor(): MutableCollection<E>, AbstractCollection<E>() {
public actual abstract class AbstractMutableCollection<E> protected actual constructor(): MutableCollection<E>, AbstractCollection<E>() {
// Bulk Modification Operations
/**
@@ -18,7 +18,7 @@ public abstract class AbstractMutableCollection<E> protected constructor(): Muta
*
* @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified.
*/
override public fun addAll(elements: Collection<E>): Boolean {
actual override public fun addAll(elements: Collection<E>): Boolean {
var changed = false
for (v in elements) {
if (add(v)) changed = true
@@ -32,7 +32,7 @@ public abstract class AbstractMutableCollection<E> protected constructor(): Muta
*
* @return `true` if the element has been successfully removed; `false` if it was not present in the collection.
*/
override fun remove(element: E): Boolean {
actual override fun remove(element: E): Boolean {
val it = iterator()
while (it.hasNext()) {
if (it.next() == element) {
@@ -48,19 +48,19 @@ public abstract class AbstractMutableCollection<E> protected constructor(): Muta
*
* @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified.
*/
override public fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements }
actual override public fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements }
/**
* Retains only the elements in this collection that are contained in the specified collection.
*
* @return `true` if any element was removed from the collection, `false` if the collection was not modified.
*/
override public fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).retainAll { it in elements }
actual override public fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).retainAll { it in elements }
/**
* Removes all elements from this collection.
*/
override fun clear(): Unit {
actual override fun clear(): Unit {
val it = iterator()
while (it.hasNext()) {
it.next()
@@ -0,0 +1,135 @@
package kotlin.collections
/**
* Provides a skeletal implementation of the [MutableMap] interface.
*
* The implementor is required to implement [entries] property, which should return mutable set of map entries, and [put] function.
*
* @param K the type of map keys. The map is invariant on its key type.
* @param V the type of map values. The map is invariant on its value type.
*/
@SinceKotlin("1.1")
public actual abstract class AbstractMutableMap<K, V> protected actual constructor() : AbstractMap<K, V>(), MutableMap<K, V> {
/**
* Associates the specified [value] with the specified [key] in the map.
*
* @return the previous value associated with the key, or `null` if the key was not present in the map.
*/
actual abstract override fun put(key: K, value: V): V?
/**
* A mutable [Map.Entry] shared by several [Map] implementations.
*/
internal open class SimpleEntry<K, V>(override val key: K, value: V) : MutableMap.MutableEntry<K, V> {
constructor(entry: Map.Entry<K, V>) : this(entry.key, entry.value)
private var _value = value
override val value: V get() = _value
override fun setValue(newValue: V): V {
val oldValue = this._value
this._value = newValue
return oldValue
}
override fun hashCode(): Int = entryHashCode(this)
override fun toString(): String = entryToString(this)
override fun equals(other: Any?): Boolean = entryEquals(this, other)
}
actual override fun putAll(from: Map<out K, V>) {
for ((key, value) in from) {
put(key, value)
}
}
actual override fun remove(key: K): V? {
val iter = entries.iterator()
while (iter.hasNext()) {
val entry = iter.next()
val k = entry.key
if (key == k) {
val value = entry.value
iter.remove()
return value
}
}
return null
}
actual override fun clear() {
entries.clear()
}
private var _keys: MutableSet<K>? = null
actual override val keys: MutableSet<K>
get() {
if (_keys == null) {
_keys = object : AbstractMutableSet<K>() {
override fun add(element: K): Boolean = throw UnsupportedOperationException("Add is not supported on keys")
override fun clear() {
this@AbstractMutableMap.clear()
}
override operator fun contains(element: K): Boolean = containsKey(element)
override operator fun iterator(): MutableIterator<K> {
val entryIterator = entries.iterator()
return object : MutableIterator<K> {
override fun hasNext(): Boolean = entryIterator.hasNext()
override fun next(): K = entryIterator.next().key
override fun remove() = entryIterator.remove()
}
}
override fun remove(element: K): Boolean {
if (containsKey(element)) {
this@AbstractMutableMap.remove(element)
return true
}
return false
}
override val size: Int get() = this@AbstractMutableMap.size
}
}
return _keys!!
}
private var _values: MutableCollection<V>? = null
actual override val values: MutableCollection<V>
get() {
if (_values == null) {
_values = object : AbstractMutableCollection<V>() {
override fun add(element: V): Boolean = throw UnsupportedOperationException("Add is not supported on values")
override fun clear() = this@AbstractMutableMap.clear()
override operator fun contains(element: V): Boolean = containsValue(element)
override operator fun iterator(): MutableIterator<V> {
val entryIterator = entries.iterator()
return object : MutableIterator<V> {
override fun hasNext(): Boolean = entryIterator.hasNext()
override fun next(): V = entryIterator.next().value
override fun remove() = entryIterator.remove()
}
}
override val size: Int get() = this@AbstractMutableMap.size
// TODO: should we implement them this way? Currently it's unspecified in JVM
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Collection<*>) return false
return AbstractList.orderedEquals(this, other)
}
override fun hashCode(): Int = AbstractList.orderedHashCode(this)
}
}
return _values!!
}
}
@@ -0,0 +1,32 @@
package kotlin.collections
/**
* Provides a skeletal implementation of the [MutableSet] interface.
*
* @param E the type of elements contained in the set. The set is invariant on its element type.
*/
@SinceKotlin("1.1")
public actual abstract class AbstractMutableSet<E> protected actual constructor() : AbstractMutableCollection<E>(), MutableSet<E> {
/**
* Adds the specified element to the set.
*
* @return `true` if the element has been added, `false` if the element is already contained in the set.
*/
actual abstract override fun add(element: E): Boolean
/**
* Compares this set with another set instance with the unordered structural equality.
*
* @return true, if [other] instance is a [Set] of the same size, all elements of which are contained in this set.
*/
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Set<*>) return false
return AbstractSet.setEquals(this, other)
}
/**
* Returns the hash code value for this set.
*/
override fun hashCode(): Int = AbstractSet.unorderedHashCode(this)
}
@@ -25,51 +25,3 @@ public actual fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Uni
}
}
}
/**
* Provides a skeletal implementation of the [MutableMap] interface.
*
* The implementor is required to implement [entries] property, which should return mutable set of map entries, and [put] function.
*
* @param K the type of map keys. The map is invariant on its key type.
* @param V the type of map values. The map is invariant on its value type.
*/
@SinceKotlin("1.1")
actual abstract class AbstractMutableMap<K, V> protected actual constructor() : AbstractMap<K, V>(), MutableMap<K, V> {
/**
* Associates the specified [value] with the specified [key] in the map.
*
* This method is redeclared as abstract, because it's not implemented in the base class,
* so it must be always overridden in the concrete mutable collection implementation.
*
* @return the previous value associated with the key, or `null` if the key was not present in the map.
*/
actual abstract override fun put(key: K, value: V): V?
/**
* Returns a [MutableSet] of all keys in this map.
*/
abstract override val keys: MutableSet<K>
/**
* Returns a [MutableCollection] of all values in this map. Note that this collection may contain duplicate values.
*/
abstract override val values: MutableCollection<V>
}
/**
* Provides a skeletal implementation of the [MutableSet] interface.
*
* @param E the type of elements contained in the set. The set is invariant on its element type.
*/
@SinceKotlin("1.1")
actual abstract class AbstractMutableSet<E> protected actual constructor() : AbstractSet<E>(), MutableSet<E> {
/**
* Adds the specified element to the set.
*
* This method is redeclared as abstract, because it's not implemented in the base class,
* so it must be always overridden in the concrete mutable collection implementation.
*
* @return `true` if the element has been added, `false` if the element is already contained in the set.
*/
actual abstract override fun add(element: E): Boolean
}