Correct abstract mutable collections declarations in kotlin-stdlib-common
Add SinceKotlin(1.3) to the new and substantially changed common declarations #KT-28091
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.collections
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a skeletal implementation of the [MutableCollection] interface.
|
||||||
|
*
|
||||||
|
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public expect abstract class AbstractMutableCollection<E> : MutableCollection<E> {
|
||||||
|
protected constructor()
|
||||||
|
|
||||||
|
abstract override val size: Int
|
||||||
|
abstract override fun iterator(): MutableIterator<E>
|
||||||
|
abstract override fun add(element: E): Boolean
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean
|
||||||
|
override fun contains(element: @UnsafeVariance E): Boolean
|
||||||
|
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
|
||||||
|
|
||||||
|
|
||||||
|
override fun addAll(elements: Collection<E>): Boolean
|
||||||
|
override fun remove(element: E): Boolean
|
||||||
|
override fun removeAll(elements: Collection<E>): Boolean
|
||||||
|
override fun retainAll(elements: Collection<E>): Boolean
|
||||||
|
override fun clear(): Unit
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,7 +5,12 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
expect abstract class AbstractMutableList<E> : MutableList<E> {
|
/**
|
||||||
|
* Provides a skeletal implementation of the [MutableList] interface.
|
||||||
|
*
|
||||||
|
* @param E the type of elements contained in the list. The list is invariant on its element type.
|
||||||
|
*/
|
||||||
|
public expect abstract class AbstractMutableList<E> : MutableList<E> {
|
||||||
protected constructor()
|
protected constructor()
|
||||||
|
|
||||||
// From List
|
// From List
|
||||||
|
|||||||
@@ -5,8 +5,16 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
expect abstract class AbstractMutableMap<K, V> : MutableMap<K, V> {
|
/**
|
||||||
|
* 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.3")
|
||||||
|
public expect abstract class AbstractMutableMap<K, V> : MutableMap<K, V> {
|
||||||
protected constructor()
|
protected constructor()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,4 +26,17 @@ expect abstract class AbstractMutableMap<K, V> : MutableMap<K, V> {
|
|||||||
* @return the previous value associated with the key, or `null` if the key was not present in the map.
|
* @return the previous value associated with the key, or `null` if the key was not present in the map.
|
||||||
*/
|
*/
|
||||||
abstract override fun put(key: K, value: V): V?
|
abstract override fun put(key: K, value: V): V?
|
||||||
|
|
||||||
|
abstract override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
|
|
||||||
|
override val keys: MutableSet<K>
|
||||||
|
override val size: Int
|
||||||
|
override val values: MutableCollection<V>
|
||||||
|
override fun clear()
|
||||||
|
override fun containsKey(key: K): Boolean
|
||||||
|
override fun containsValue(value: V): Boolean
|
||||||
|
override fun get(key: K): V?
|
||||||
|
override fun isEmpty(): Boolean
|
||||||
|
override fun putAll(from: Map<out K, V>)
|
||||||
|
override fun remove(key: K): V?
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,27 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
expect abstract class AbstractMutableSet<E> : MutableSet<E> {
|
/**
|
||||||
|
* 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.3")
|
||||||
|
public expect abstract class AbstractMutableSet<E> : MutableSet<E> {
|
||||||
protected constructor()
|
protected constructor()
|
||||||
|
|
||||||
|
abstract override val size: Int
|
||||||
|
abstract override fun iterator(): MutableIterator<E>
|
||||||
abstract override fun add(element: E): Boolean
|
abstract override fun add(element: E): Boolean
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean
|
||||||
|
override fun contains(element: @UnsafeVariance E): Boolean
|
||||||
|
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
|
||||||
|
|
||||||
|
|
||||||
|
override fun addAll(elements: Collection<E>): Boolean
|
||||||
|
override fun remove(element: E): Boolean
|
||||||
|
override fun removeAll(elements: Collection<E>): Boolean
|
||||||
|
override fun retainAll(elements: Collection<E>): Boolean
|
||||||
|
override fun clear(): Unit
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,11 @@ package kotlin.collections
|
|||||||
*
|
*
|
||||||
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
|
* @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() : AbstractCollection<E>(), MutableCollection<E> {
|
public actual abstract class AbstractMutableCollection<E> protected actual constructor() : AbstractCollection<E>(), MutableCollection<E> {
|
||||||
|
|
||||||
abstract override fun add(element: E): Boolean
|
actual abstract override fun add(element: E): Boolean
|
||||||
|
|
||||||
override fun remove(element: E): Boolean {
|
actual override fun remove(element: E): Boolean {
|
||||||
val iterator = iterator()
|
val iterator = iterator()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
if (iterator.next() == element) {
|
if (iterator.next() == element) {
|
||||||
@@ -25,7 +25,7 @@ public abstract class AbstractMutableCollection<E> protected constructor() : Abs
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addAll(elements: Collection<E>): Boolean {
|
actual override fun addAll(elements: Collection<E>): Boolean {
|
||||||
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 +33,10 @@ public abstract class AbstractMutableCollection<E> protected constructor() : Abs
|
|||||||
return modified
|
return modified
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements }
|
actual override fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements }
|
||||||
override fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it !in elements }
|
actual override fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it !in elements }
|
||||||
|
|
||||||
override fun clear(): Unit {
|
actual override fun clear(): Unit {
|
||||||
val iterator = this.iterator()
|
val iterator = this.iterator()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
iterator.next()
|
iterator.next()
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
actual override fun clear() {
|
||||||
entries.clear()
|
entries.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _keys: MutableSet<K>? = null
|
private var _keys: MutableSet<K>? = null
|
||||||
override val keys: MutableSet<K>
|
actual override val keys: MutableSet<K>
|
||||||
get() {
|
get() {
|
||||||
if (_keys == null) {
|
if (_keys == null) {
|
||||||
_keys = object : AbstractMutableSet<K>() {
|
_keys = object : AbstractMutableSet<K>() {
|
||||||
@@ -82,14 +82,14 @@ 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?
|
||||||
|
|
||||||
override fun putAll(from: Map<out K, V>) {
|
actual override fun putAll(from: Map<out K, V>) {
|
||||||
for ((key, value) in from) {
|
for ((key, value) in from) {
|
||||||
put(key, value)
|
put(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _values: MutableCollection<V>? = null
|
private var _values: MutableCollection<V>? = null
|
||||||
override val values: MutableCollection<V>
|
actual override val values: MutableCollection<V>
|
||||||
get() {
|
get() {
|
||||||
if (_values == null) {
|
if (_values == null) {
|
||||||
_values = object : AbstractMutableCollection<V>() {
|
_values = object : AbstractMutableCollection<V>() {
|
||||||
@@ -122,10 +122,10 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
|||||||
return _values!!
|
return _values!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K): V? {
|
actual override fun remove(key: K): V? {
|
||||||
val iter = entries.iterator()
|
val iter = entries.iterator()
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
var entry = iter.next()
|
val entry = iter.next()
|
||||||
val k = entry.key
|
val k = entry.key
|
||||||
if (key == k) {
|
if (key == k) {
|
||||||
val value = entry.value
|
val value = entry.value
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.util.AbstractCollection
|
|||||||
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
|
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
|
||||||
*/
|
*/
|
||||||
@SinceKotlin("1.1")
|
@SinceKotlin("1.1")
|
||||||
public abstract class AbstractMutableCollection<E> protected constructor() : MutableCollection<E>, AbstractCollection<E>() {
|
public actual abstract class AbstractMutableCollection<E> protected actual constructor() : MutableCollection<E>, AbstractCollection<E>() {
|
||||||
/**
|
/**
|
||||||
* Adds the specified element to the collection.
|
* Adds the specified element to the collection.
|
||||||
*
|
*
|
||||||
@@ -23,5 +23,5 @@ public abstract class AbstractMutableCollection<E> protected constructor() : Mut
|
|||||||
* @return `true` if the element has been added, `false` if the collection does not support duplicates
|
* @return `true` if the element has been added, `false` if the collection does not support duplicates
|
||||||
* and the element is already contained in the collection.
|
* and the element is already contained in the collection.
|
||||||
*/
|
*/
|
||||||
abstract override fun add(element: E): Boolean
|
actual abstract override fun add(element: E): Boolean
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package test.collections
|
||||||
|
|
||||||
|
import test.collections.behaviors.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class AbstractCollectionsTest {
|
||||||
|
|
||||||
|
class ReadOnlyCollection : AbstractCollection<String>() {
|
||||||
|
private val data = arrayOf("ok")
|
||||||
|
override val size: Int get() = 1
|
||||||
|
override fun iterator(): Iterator<String> = data.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReadOnlySet : AbstractSet<String>() {
|
||||||
|
private val data = arrayOf("ok")
|
||||||
|
override val size: Int get() = 1
|
||||||
|
override fun iterator(): Iterator<String> = data.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReadOnlyList(override val size: Int = 1) : AbstractList<String>() {
|
||||||
|
override fun get(index: Int): String = index.takeIf { it in indices }?.let { "ok" } ?: throw IndexOutOfBoundsException()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReadOnlyMap : AbstractMap<String, Int>() {
|
||||||
|
override val entries: Set<Map.Entry<String, Int>> = mapOf("ok" to 42).entries
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractCollection() {
|
||||||
|
val coll = ReadOnlyCollection()
|
||||||
|
assertEquals(listOf("ok"), coll.toList())
|
||||||
|
|
||||||
|
compare(coll.toList(), coll) {
|
||||||
|
collectionBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractSet() {
|
||||||
|
val set = ReadOnlySet()
|
||||||
|
assertEquals(1, set.size)
|
||||||
|
assertTrue("ok" in set)
|
||||||
|
|
||||||
|
compare(set.toSet(), set) {
|
||||||
|
setBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractList() {
|
||||||
|
val list = ReadOnlyList(4)
|
||||||
|
assertEquals(listOf("ok", "ok", "ok", "ok"), list)
|
||||||
|
|
||||||
|
compare(list.toList(), list) {
|
||||||
|
listBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractMap() {
|
||||||
|
val map = ReadOnlyMap()
|
||||||
|
assertEquals(1, map.size)
|
||||||
|
assertTrue(map.contains("ok"))
|
||||||
|
assertTrue(map.containsValue(42))
|
||||||
|
assertEquals(setOf("ok"), map.keys)
|
||||||
|
assertEquals(listOf(42), map.values.toList())
|
||||||
|
|
||||||
|
compare(map.toMap(), map) {
|
||||||
|
mapBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutColl(val storage: MutableCollection<String> = mutableListOf()) : AbstractMutableCollection<String>() {
|
||||||
|
override val size: Int get() = storage.size
|
||||||
|
override fun iterator(): MutableIterator<String> = storage.iterator()
|
||||||
|
override fun add(element: String): Boolean = storage.add(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutList(val storage: MutableList<String> = mutableListOf()) : AbstractMutableList<String>() {
|
||||||
|
override val size: Int get() = storage.size
|
||||||
|
override fun get(index: Int): String = storage.get(index)
|
||||||
|
override fun add(index: Int, element: String) = storage.add(index, element)
|
||||||
|
override fun removeAt(index: Int): String = storage.removeAt(index)
|
||||||
|
override fun set(index: Int, element: String): String = storage.set(index, element)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutSet(val storage: MutableSet<String> = mutableSetOf<String>()) : AbstractMutableSet<String>() {
|
||||||
|
override val size: Int get() = storage.size
|
||||||
|
override fun iterator(): MutableIterator<String> = storage.iterator()
|
||||||
|
override fun add(element: String): Boolean = storage.add(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutMap(val storage: MutableMap<String, Int> = mutableMapOf()) : AbstractMutableMap<String, Int>() {
|
||||||
|
override fun put(key: String, value: Int): Int? = storage.put(key, value)
|
||||||
|
override val entries: MutableSet<MutableMap.MutableEntry<String, Int>> get() = storage.entries
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractMutableCollection() {
|
||||||
|
val coll = MutColl()
|
||||||
|
coll += "ok"
|
||||||
|
coll += "test"
|
||||||
|
coll.removeAll { it.length > 2 }
|
||||||
|
assertEquals(1, coll.size)
|
||||||
|
assertEquals(listOf("ok"), coll.toList())
|
||||||
|
|
||||||
|
compare(coll.storage, coll) {
|
||||||
|
collectionBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractMutableList() {
|
||||||
|
val list = MutList()
|
||||||
|
list += "test"
|
||||||
|
list += "ok"
|
||||||
|
list += "element"
|
||||||
|
|
||||||
|
val subList = list.subList(0, 2)
|
||||||
|
subList.retainAll { it.length <= 2 }
|
||||||
|
|
||||||
|
assertEquals(listOf("ok", "element"), list)
|
||||||
|
|
||||||
|
compare(list.storage, list) {
|
||||||
|
listBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractMutableSet() {
|
||||||
|
val set = MutSet()
|
||||||
|
set.addAll(listOf("ok", "test", "element", "test"))
|
||||||
|
set.removeAll { it.length < 4 }
|
||||||
|
|
||||||
|
assertEquals(2, set.size)
|
||||||
|
assertEquals(setOf("element", "test"), set)
|
||||||
|
|
||||||
|
compare(set.storage, set) {
|
||||||
|
setBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun abstractMutableMap() {
|
||||||
|
val map = MutMap()
|
||||||
|
for (e in 'a'..'z') map[e.toString()] = e.toInt()
|
||||||
|
assertEquals(26, map.size)
|
||||||
|
|
||||||
|
map.remove("a")
|
||||||
|
map.keys.remove("b")
|
||||||
|
map.keys.removeAll { it == "c" }
|
||||||
|
|
||||||
|
map.values.remove('d'.toInt())
|
||||||
|
assertTrue(map.containsKey("e"))
|
||||||
|
assertTrue(map.containsValue('f'.toInt()))
|
||||||
|
|
||||||
|
compare(map.storage, map) {
|
||||||
|
mapBehavior()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user