Rewrite ArrayList, AbstractList, AbstractCollection in kotlin.

AbstractList is imported from GWT.
#KT-12386
This commit is contained in:
Ilya Gorbunov
2016-08-19 22:18:32 +03:00
parent 0abf94c2f4
commit 75069143c7
17 changed files with 535 additions and 418 deletions
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,12 @@ package kotlin.collections
public fun <reified T> Collection<T>.toTypedArray(): Array<T> = noImpl
@library("copyToArrayImpl")
internal fun copyToArrayImpl(collection: Collection<*>): Array<Any?> = noImpl
@library("arrayToString")
internal fun arrayToString(array: Array<*>): String = noImpl
/**
* Returns an immutable list containing only the specified object [element].
*/
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.collections
public abstract class AbstractCollection<E> protected constructor() : MutableCollection<E> {
abstract override val size: Int
abstract override fun iterator(): MutableIterator<E>
override fun add(element: E): Boolean = throw UnsupportedOperationException()
override fun remove(element: E): Boolean {
val iterator = iterator()
while (iterator.hasNext()) {
if (iterator.next() == element) {
iterator.remove()
return true
}
}
return false
}
override fun isEmpty(): Boolean = size == 0
override fun contains(element: E): Boolean {
for (e in this) {
if (e == element) return true
}
return false
}
override fun containsAll(elements: Collection<E>): Boolean = elements.all { contains(it) }
override fun addAll(elements: Collection<E>): Boolean {
var modified = false
for (element in elements) {
if (add(element)) modified = true
}
return modified
}
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 }
override fun clear(): Unit {
val iterator = this.iterator()
while (iterator.hasNext()) {
iterator.next()
iterator.remove()
}
}
abstract override fun hashCode(): Int
abstract override fun equals(other: Any?): Boolean
override fun toString(): String = joinToString(", ", "[", "]") {
if (it === this) "(this Collection)" else it.toString()
}
protected open fun toArray(): Array<Any?> = copyToArrayImpl(this)
open fun toJSON(): Any = this.toArray()
}
@@ -0,0 +1,248 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Based on GWT AbstractList
* Copyright 2007 Google Inc.
*/
package kotlin.collections
public abstract class AbstractList<E> protected constructor() : AbstractCollection<E>(), MutableList<E> {
abstract override val size: Int
abstract override fun get(index: Int): E
protected var modCount: Int = 0
override fun add(index: Int, element: E): Unit = throw UnsupportedOperationException("Add not supported on this list")
override fun removeAt(index: Int): E = throw UnsupportedOperationException("Remove not supported on this list")
override fun set(index: Int, element: E): E = throw UnsupportedOperationException("Set not supported on this list")
override fun add(element: E): Boolean {
add(size, element)
return true
}
override fun addAll(index: Int, elements: Collection<E>): Boolean {
var index = index
var changed = false
for (e in elements) {
add(index++, e)
changed = true
}
return changed
}
override fun clear() {
removeRange(0, size)
}
override fun iterator(): MutableIterator<E> = IteratorImpl()
override fun indexOf(element: E): Int {
for (i in 0..lastIndex) {
if (get(i) == element) {
return i
}
}
return -1
}
override fun lastIndexOf(element: E): Int {
for (i in lastIndex downTo 0) {
if (get(i) == element) {
return i
}
}
return -1
}
override fun listIterator(): MutableListIterator<E> = listIterator(0)
override fun listIterator(from: Int): MutableListIterator<E> = ListIteratorImpl(from)
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> = SubList(this, fromIndex, toIndex)
protected open fun removeRange(fromIndex: Int, endIndex: Int) {
val iterator = listIterator(fromIndex)
for (i in fromIndex..endIndex - 1) {
iterator.next()
iterator.remove()
}
}
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is List<*>) return false
if (size != other.size) return false
val otherIterator = other.iterator()
for (elem in this) {
val elemOther = otherIterator.next()
if (elem != elemOther) {
return false
}
}
return true
}
override fun hashCode(): Int {
return Collections_hashCode(this)
}
private open inner class IteratorImpl : MutableIterator<E> {
/*
* i is the index of the item that will be returned on the next call to
* next() last is the index of the item that was returned on the previous
* call to next() or previous (for ListIterator), -1 if no such item exists.
*/
internal var i = 0
internal var last = -1
override fun hasNext(): Boolean = i < size
override fun next(): E {
if (!hasNext()) throw NoSuchElementException()
last = i++
return get(last)
}
override fun remove() {
check(last != -1)
removeAt(last)
i = last
last = -1
}
}
/**
* Implementation of `ListIterator` for abstract lists.
*/
private inner class ListIteratorImpl(start: Int) : IteratorImpl(), MutableListIterator<E> {
/*
* i is the index of the item that will be returned on the next call to
* next() last is the index of the item that was returned on the previous
* call to next() or previous (for ListIterator), -1 if no such item exists.
*/
init {
checkPositionIndex(start, this@AbstractList.size)
i = start
}
override fun add(o: E) {
add(i, o)
i++
last = -1
}
override fun hasPrevious(): Boolean = i > 0
override fun nextIndex(): Int = i
override fun previous(): E {
if (!hasPrevious()) throw NoSuchElementException()
last = --i
return get(last)
}
override fun previousIndex(): Int = i - 1
override fun set(o: E) {
require(last != -1)
this@AbstractList[last] = o
}
}
private class SubList<E>(private val wrapped: AbstractList<E>, private val fromIndex: Int, toIndex: Int) : AbstractList<E>() {
private var _size: Int = 0
init {
checkCriticalPositionIndexes(fromIndex, toIndex, wrapped.size)
this._size = toIndex - fromIndex
}
override fun add(index: Int, element: E) {
checkPositionIndex(index, _size)
wrapped.add(fromIndex + index, element)
_size++
}
override fun get(index: Int): E {
checkElementIndex(index, _size)
return wrapped[fromIndex + index]
}
override fun removeAt(index: Int): E {
checkElementIndex(index, _size)
val result = wrapped.removeAt(fromIndex + index)
_size--
return result
}
override fun set(index: Int, element: E): E {
checkElementIndex(index, _size)
return wrapped.set(fromIndex + index, element)
}
override val size: Int get() = _size
}
companion object {
internal fun checkElementIndex(index: Int, size: Int) {
if (index < 0 || index >= size) {
throw IndexOutOfBoundsException("Index: $index, Size: $size")
}
}
internal fun checkPositionIndex(index: Int, size: Int) {
if (index < 0 || index > size) {
throw IndexOutOfBoundsException("Index: $index, Size: $size")
}
}
internal fun checkCriticalPositionIndexes(start: Int, end: Int, size: Int) {
if (start < 0 || end > size) {
throw IndexOutOfBoundsException("fromIndex: $start, toIndex: $end, size: $size")
}
if (start > end) {
throw IllegalArgumentException("fromIndex: $start > toIndex: $end")
}
}
internal fun <T> Collections_hashCode(list: List<T>): Int {
var hashCode = 1
for (e in list) {
hashCode = 31 * hashCode + (e?.hashCode() ?: 0)
hashCode = hashCode or 0 // make sure we don't overflow
}
return hashCode
}
}
}
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.collections
//TODO: should be JS Array-like (https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects)
public open class ArrayList<E> internal constructor(private var array: Array<Any?>) : AbstractList<E>(), RandomAccess {
public constructor(capacity: Int = 0) : this(emptyArray()) {}
public constructor(elements: Collection<E>) : this(elements.toTypedArray<Any?>()) {}
override val size: Int get() = array.size
override fun get(index: Int): E = array[rangeCheck(index)] as E
override fun set(index: Int, element: E): E {
rangeCheck(index)
return array[index].apply { array[index] = element } as E
}
override fun add(element: E): Boolean {
array.asDynamic().push(element)
modCount++
return true
}
override fun add(index: Int, element: E): Unit {
array.asDynamic().splice(insertionRangeCheck(index), 0, element)
modCount++
}
override fun addAll(elements: Collection<E>): Boolean {
if (elements.isEmpty()) return false
array += elements.toTypedArray<Any?>()
modCount++
return true
}
override fun addAll(index: Int, elements: Collection<E>): Boolean {
insertionRangeCheck(index)
if (index == size) return addAll(elements)
if (elements.isEmpty()) return false
array = array.copyOfRange(0, index) + elements.toTypedArray<Any?>() + array.copyOfRange(index, size)
modCount++
return true
}
override fun removeAt(index: Int): E {
rangeCheck(index)
modCount++
return if (index == size)
array.asDynamic().pop()
else
array.asDynamic().splice(index, 1)[0]
}
override fun remove(element: E): Boolean {
for (index in array.indices) {
if (array[index] == element) {
array.asDynamic().splice(index, 1)
modCount++
return true
}
}
return false
}
override fun removeRange(fromIndex: Int, toIndex: Int) {
modCount++
array.asDynamic().splice(fromIndex, toIndex - fromIndex)
}
override fun clear() {
array = emptyArray()
modCount++
}
override fun contains(element: E): Boolean = indexOf(element) >= 0
override fun indexOf(element: E): Int = array.indexOf(element)
override fun lastIndexOf(element: E): Int = array.lastIndexOf(element)
override fun toString() = arrayToString(array)
override fun toArray(): Array<Any?> = array.copyOf()
private fun rangeCheck(index: Int) = index.apply {
if (index !in array.indices)
throw IndexOutOfBoundsException("Index: $index, Size: $size")
}
private fun insertionRangeCheck(index: Int) = index.apply {
if (index !in 0..size)
throw IndexOutOfBoundsException("Index: $index, Size: $size")
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.collections
public interface RandomAccess
+3
View File
@@ -34,6 +34,9 @@ public open class IllegalStateException(message: String? = null) : RuntimeExcept
@library
public open class IndexOutOfBoundsException(message: String? = null) : RuntimeException(message) {}
@library
public open class ConcurrentModificationException(message: String? = null) : RuntimeException(message) {}
@library
public open class UnsupportedOperationException(message: String? = null) : RuntimeException(message) {}
+10 -53
View File
@@ -31,67 +31,24 @@ public inline fun <T> Comparator(crossinline comparison: (T, T) -> Int): Compara
override fun compare(obj1: T, obj2: T): Int = comparison(obj1, obj2)
}
@library
public interface RandomAccess
@library
public abstract class AbstractCollection<E>() : MutableCollection<E> {
override fun isEmpty(): Boolean = noImpl
override fun contains(o: E): Boolean = noImpl
override fun iterator(): MutableIterator<E> = noImpl
// in lack of type aliases
/*
public abstract class AbstractCollection<E> : kotlin.collections.AbstractCollection<E>()
public abstract class AbstractList<E> : kotlin.collections.AbstractList<E>()
public open class ArrayList<E>(capacity: Int = 0) : kotlin.collections.ArrayList<E>(capacity)
*/
override fun add(e: E): Boolean = noImpl
override fun remove(o: E): Boolean = noImpl
override fun addAll(c: Collection<E>): Boolean = noImpl
override fun containsAll(c: Collection<E>): Boolean = noImpl
override fun removeAll(c: Collection<E>): Boolean = noImpl
override fun retainAll(c: Collection<E>): Boolean = noImpl
override fun clear(): Unit = noImpl
abstract override val size: Int
override fun hashCode(): Int = noImpl
override fun equals(other: Any?): Boolean = noImpl
}
@library
public abstract class AbstractList<E>() : AbstractCollection<E>(), MutableList<E> {
abstract override fun get(index: Int): E
override fun set(index: Int, element: E): E = noImpl
override fun add(e: E): Boolean = noImpl
override fun add(index: Int, element: E): Unit = noImpl
override fun addAll(index: Int, c: Collection<E>): Boolean = noImpl
override fun removeAt(index: Int): E = noImpl
override fun indexOf(o: E): Int = noImpl
override fun lastIndexOf(o: E): Int = noImpl
override fun listIterator(): MutableListIterator<E> = noImpl
override fun listIterator(index: Int): MutableListIterator<E> = noImpl
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> = noImpl
abstract override val size: Int
override fun equals(other: Any?): Boolean = noImpl
override fun toString(): String = noImpl
}
@library
public open class ArrayList<E>(capacity: Int = 0) : AbstractList<E>(), RandomAccess {
override fun get(index: Int): E = noImpl
override val size: Int get() = noImpl
}
@library
public open class HashSet<E>(
initialCapacity: Int = DEFAULT_INITIAL_CAPACITY, loadFactor: Float = DEFAULT_LOAD_FACTOR
) : AbstractCollection<E>(), MutableSet<E> {
override fun iterator(): MutableIterator<E> = noImpl
override val size: Int get() = noImpl
override fun equals(other: Any?): Boolean = noImpl
override fun hashCode(): Int = noImpl
}
@library
+1 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,3 @@ public fun <K, V> HashMap(m: Map<out K, V>): HashMap<K, V>
public fun <K, V> LinkedHashMap(m: Map<out K, V>): LinkedHashMap<K, V>
= LinkedHashMap<K, V>(m.size).apply { putAll(m) }
public fun <E> ArrayList(c: Collection<E>): ArrayList<E>
= ArrayList<E>().apply { asDynamic().array = c.toTypedArray<Any?>() } // black dynamic magic
+1 -3
View File
@@ -13,9 +13,7 @@ import java.util.Collections // TODO: it's temporary while we have java.util.Col
* Returns a [List] that wraps the original array.
*/
public fun <T> Array<out T>.asList(): List<T> {
val al = ArrayList<T>()
al.asDynamic().array = this // black dynamic magic
return al
return ArrayList<T>(this as Array<Any?>)
}
/**
+3 -3
View File
@@ -17,7 +17,7 @@
package kotlin.text
import kotlin.text.js.*
import java.util.ArrayList
import java.util.*
/**
* Provides enumeration values to use to set regular expression options.
@@ -149,7 +149,7 @@ public class Regex(pattern: String, options: Set<RegexOption>) {
public fun split(input: CharSequence, limit: Int = 0): List<String> {
require(limit >= 0) { "Limit must be non-negative, but was $limit" }
val matches = findAll(input).let { if (limit == 0) it else it.take(limit - 1) }
val result = ArrayList<String>()
val result = mutableListOf<String>()
var lastStart = 0
for (match in matches) {
@@ -216,7 +216,7 @@ private fun RegExp.findNext(input: String, from: Int): MatchResult? {
override val groupValues: List<String>
get() {
if (groupValues_ == null) {
groupValues_ = object : java.util.AbstractList<String>() {
groupValues_ = object : AbstractList<String>() {
override val size: Int get() = match.length
override fun get(index: Int): String = match[index] ?: ""
}