Add extensions from kotlinx.support libraries:
use for AutoCloseables: #KT-5899, extensions for java.util.Stream.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
@file:JvmName("StandardJRE7Kt")
|
||||
package kotlin
|
||||
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
|
||||
var closed = false
|
||||
try {
|
||||
return block(this)
|
||||
} catch (e: Throwable) {
|
||||
closed = true
|
||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||
closeSuppressed(e)
|
||||
throw e
|
||||
} finally {
|
||||
if (!closed) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this [AutoCloseable] suppressing possible exception or error thrown by [AutoCloseable.close] function.
|
||||
* The suppressed exception is added to the list of suppressed exceptions of [cause] exception.
|
||||
*/
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@kotlin.internal.InlineExposed
|
||||
internal fun AutoCloseable.closeSuppressed(cause: Throwable) {
|
||||
try {
|
||||
close()
|
||||
} catch (closeException: Throwable) {
|
||||
cause.addSuppressed(closeException)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package kotlin.jdk7.test
|
||||
|
||||
import java.io.*
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
class TryWithResourcesAutoCloseableTest {
|
||||
|
||||
class Resource(val faultyClose: Boolean = false) : AutoCloseable {
|
||||
|
||||
var isClosed = false
|
||||
private set
|
||||
|
||||
override fun close() {
|
||||
if (faultyClose)
|
||||
throw IOException("Close failed")
|
||||
isClosed = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test fun success() {
|
||||
val resource = Resource()
|
||||
val result = resource.use { "ok" }
|
||||
assertEquals("ok", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
@Test fun closeFails() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { "" }
|
||||
}
|
||||
assertTrue(e is IOException)
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseSuccess() {
|
||||
val e = assertFails {
|
||||
Resource().use { error("op fail") }
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
assertTrue(e.suppressed.isEmpty())
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseFails() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { error("op fail") }
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
assertTrue(e.suppressed.single() is IOException)
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseFailsTwice() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { res1 ->
|
||||
Resource(faultyClose = true).use { res2 ->
|
||||
error("op fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
val suppressed = e.suppressed
|
||||
assertEquals(2, suppressed.size)
|
||||
assertTrue(suppressed.all { it is IOException })
|
||||
}
|
||||
|
||||
@Test fun nonLocalReturnInBlock() {
|
||||
fun Resource.operation(nonLocal: Boolean): String {
|
||||
return use { if (nonLocal) return "nonLocal" else "local" }
|
||||
}
|
||||
|
||||
Resource().let { resource ->
|
||||
val result = resource.operation(nonLocal = false)
|
||||
assertEquals("local", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
Resource().let { resource ->
|
||||
val result = resource.operation(nonLocal = true)
|
||||
assertEquals("nonLocal", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package kotlin.jdk7.test
|
||||
|
||||
import java.io.*
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
|
||||
class TryWithResourcesCloseableTest {
|
||||
|
||||
class Resource(val faultyClose: Boolean = false) : Closeable {
|
||||
|
||||
var isClosed = false
|
||||
private set
|
||||
|
||||
override fun close() {
|
||||
if (faultyClose)
|
||||
throw IOException("Close failed")
|
||||
isClosed = true
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun success() {
|
||||
val resource = Resource()
|
||||
val result = resource.use { "ok" }
|
||||
assertEquals("ok", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
@Test fun closeFails() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { "" }
|
||||
}
|
||||
assertTrue(e is IOException)
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseSuccess() {
|
||||
val e = assertFails {
|
||||
Resource().use { error("op fail") }
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
assertTrue(e.suppressed.isEmpty())
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseFails() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { error("op fail") }
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
assertTrue(e.suppressed.single() is IOException)
|
||||
}
|
||||
|
||||
@Test fun opFailsCloseFailsTwice() {
|
||||
val e = assertFails {
|
||||
Resource(faultyClose = true).use { res1 ->
|
||||
Resource(faultyClose = true).use { res2 ->
|
||||
error("op fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(e is IllegalStateException)
|
||||
val suppressed = e.suppressed
|
||||
assertEquals(2, suppressed.size)
|
||||
assertTrue(suppressed.all { it is IOException })
|
||||
}
|
||||
|
||||
@Test fun nonLocalReturnInBlock() {
|
||||
fun Resource.operation(nonLocal: Boolean): String {
|
||||
return use { if (nonLocal) return "nonLocal" else "local" }
|
||||
}
|
||||
|
||||
Resource().let { resource ->
|
||||
val result = resource.operation(nonLocal = false)
|
||||
assertEquals("local", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
Resource().let { resource ->
|
||||
val result = resource.operation(nonLocal = true)
|
||||
assertEquals("nonLocal", result)
|
||||
assertTrue(resource.isClosed)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
@file:Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
@file:JvmName("CollectionsJRE8Kt")
|
||||
package kotlin.collections
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, or
|
||||
* [defaultValue] if this map contains no mapping for the key.
|
||||
*/
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.getOrDefault(key: K, defaultValue: V): V
|
||||
= getOrDefault(key, defaultValue)
|
||||
|
||||
|
||||
/**
|
||||
* Removes the entry for the specified key only if it is currently
|
||||
* mapped to the specified value.
|
||||
*/
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <@kotlin.internal.OnlyInputTypes K, @kotlin.internal.OnlyInputTypes V> MutableMap<out K, out V>.remove(key: K, value: V): Boolean
|
||||
= (this as MutableMap<K, V>).remove(key, value)
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
@file:JvmName("StreamsKt")
|
||||
package kotlin.streams
|
||||
|
||||
import java.util.*
|
||||
import java.util.stream.*
|
||||
|
||||
/**
|
||||
* Creates a [Sequence] instance that wraps the original stream iterating through its elements.
|
||||
*/
|
||||
public fun <T> Stream<T>.asSequence(): Sequence<T> = Sequence { iterator() }
|
||||
|
||||
/**
|
||||
* Creates a [Sequence] instance that wraps the original stream iterating through its elements.
|
||||
*/
|
||||
public fun IntStream.asSequence(): Sequence<Int> = Sequence { iterator() }
|
||||
|
||||
/**
|
||||
* Creates a [Sequence] instance that wraps the original stream iterating through its elements.
|
||||
*/
|
||||
public fun LongStream.asSequence(): Sequence<Long> = Sequence { iterator() }
|
||||
|
||||
/**
|
||||
* Creates a [Sequence] instance that wraps the original stream iterating through its elements.
|
||||
*/
|
||||
public fun DoubleStream.asSequence(): Sequence<Double> = Sequence { iterator() }
|
||||
|
||||
/**
|
||||
* Creates a sequential [Stream] instance that produces elements from the original sequence.
|
||||
*/
|
||||
public fun <T> Sequence<T>.asStream(): Stream<T> = StreamSupport.stream({ Spliterators.spliteratorUnknownSize(iterator(), 0) }, 0, false)
|
||||
|
||||
/**
|
||||
* Returns a [List] containing all elements produced by this stream.
|
||||
*/
|
||||
public fun <T> Stream<T>.toList(): List<T> = collect(Collectors.toList<T>())
|
||||
|
||||
/**
|
||||
* Returns a [List] containing all elements produced by this stream.
|
||||
*/
|
||||
public fun IntStream.toList(): List<Int> = toArray().asList()
|
||||
|
||||
/**
|
||||
* Returns a [List] containing all elements produced by this stream.
|
||||
*/
|
||||
public fun LongStream.toList(): List<Long> = toArray().asList()
|
||||
|
||||
/**
|
||||
* Returns a [List] containing all elements produced by this stream.
|
||||
*/
|
||||
public fun DoubleStream.toList(): List<Double> = toArray().asList()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package kotlin.jdk8.collections.test
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
import java.util.function.Predicate
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.streams.*
|
||||
|
||||
class CollectionTest {
|
||||
|
||||
val data = listOf("abc", "fo", "baar")
|
||||
|
||||
@Test fun stream() {
|
||||
assertEquals(
|
||||
data.flatMap { it.asIterable() },
|
||||
data.stream()
|
||||
.flatMap { it.chars().boxed().map { it.toChar() } }
|
||||
.collect(Collectors.toList()))
|
||||
|
||||
assertEquals(data, data.parallelStream().toList())
|
||||
}
|
||||
|
||||
|
||||
@Test fun removeIf() {
|
||||
val coll: MutableCollection<String> = data.toMutableList()
|
||||
assertTrue(coll.removeIf { it.length < 3 })
|
||||
assertEquals(listOf("abc", "baar"), coll as Collection<String>)
|
||||
assertFalse(coll.removeIf(Predicate { it.length > 4 }))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package kotlin.jdk8.collections.test
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
import java.util.function.*
|
||||
|
||||
|
||||
|
||||
class IterableTest {
|
||||
|
||||
val data = listOf("foo", "bar")
|
||||
val iterable = Iterable { data.iterator() }
|
||||
|
||||
@Test fun spliterator() {
|
||||
val spliterator = iterable.spliterator()
|
||||
|
||||
assertEquals(-1, spliterator.exactSizeIfKnown)
|
||||
val expected = data.toMutableList()
|
||||
spliterator.forEachRemaining {
|
||||
assertEquals(expected.removeAt(0), it)
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun forEach() {
|
||||
val expected = data.toMutableList()
|
||||
iterable.forEach(Consumer {
|
||||
assertEquals(expected.removeAt(0), it)
|
||||
})
|
||||
}
|
||||
|
||||
@Test fun forEachRemaining() {
|
||||
val expected = data.toMutableList()
|
||||
val iterator = iterable.iterator()
|
||||
iterator.forEachRemaining(Consumer {
|
||||
assertEquals(expected.removeAt(0), it)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package kotlin.jdk8.collections.test
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
import java.util.function.UnaryOperator
|
||||
|
||||
|
||||
class ListTest {
|
||||
|
||||
@Test fun replaceAll() {
|
||||
val list = mutableListOf("ab", "cde", "x")
|
||||
list.replaceAll { it.length.toString() }
|
||||
|
||||
val expected = listOf("2", "3", "1")
|
||||
assertEquals(expected, list)
|
||||
|
||||
list.replaceAll(UnaryOperator.identity())
|
||||
assertEquals(expected, list)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package kotlin.jdk8.collections.test
|
||||
|
||||
import org.junit.Test
|
||||
import java.util.function.BiFunction
|
||||
import kotlin.test.*
|
||||
import kotlin.jdk8.collections.*
|
||||
|
||||
class MapTest {
|
||||
|
||||
@Test fun getOrDefault() {
|
||||
val map = mapOf("x" to 1, "z" to null)
|
||||
assertEquals(1, map.getOrDefault("x", 0))
|
||||
assertEquals(0, map.getOrDefault("y", 0))
|
||||
assertEquals(null, map.getOrDefault("z", 0))
|
||||
assertEquals(null, map.getOrDefault("y" as CharSequence, null))
|
||||
}
|
||||
|
||||
@Test fun forEach() {
|
||||
val map = mapOf("k" to "v")
|
||||
map.forEach { k, v ->
|
||||
assertEquals("k", k)
|
||||
assertEquals("v", v)
|
||||
}
|
||||
map.forEach {
|
||||
assertEquals("k", it.key)
|
||||
assertEquals("v", it.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun replaceAll() {
|
||||
val map: MutableMap<String, CharSequence> = mutableMapOf("a" to "b", "c" to "d")
|
||||
|
||||
map.replaceAll { k, v -> k + v }
|
||||
assertEquals(mapOf<String, CharSequence>("a" to "ab", "c" to "cd"), map)
|
||||
|
||||
val operator = BiFunction<Any, Any, String> { k, v -> k.toString() + v.toString() }
|
||||
map.replaceAll(operator)
|
||||
assertEquals(mapOf<String, CharSequence>("a" to "aab", "c" to "ccd"), map)
|
||||
}
|
||||
|
||||
@Test fun putIfAbsent() {
|
||||
val map = mutableMapOf(1 to "a")
|
||||
|
||||
assertEquals("a", map.putIfAbsent(1, "b"))
|
||||
assertEquals("a", map[1])
|
||||
|
||||
assertEquals(null, map.putIfAbsent(2, "b"))
|
||||
assertEquals("b", map[2])
|
||||
}
|
||||
|
||||
|
||||
@Test fun removeKeyValue() {
|
||||
val map = mutableMapOf(1 to "a")
|
||||
|
||||
assertEquals(false, map.remove(1 as Number, null as Any?)) // requires import
|
||||
assertEquals(true, map.remove(1, "a"))
|
||||
}
|
||||
|
||||
@Test fun replace() {
|
||||
val map = mutableMapOf(1 to "a", 2 to null)
|
||||
assertTrue(map.replace(2, null, "x"))
|
||||
assertEquals("x", map[2])
|
||||
|
||||
assertFalse(map.replace(2, null, "x"))
|
||||
|
||||
assertEquals("a", map.replace(1, "b"))
|
||||
assertEquals(null, map.replace(3, "c"))
|
||||
|
||||
}
|
||||
|
||||
@Test fun computeIfAbsent() {
|
||||
val map = mutableMapOf(2 to "x", 3 to null)
|
||||
assertEquals("x", map.computeIfAbsent(2) { it.toString() })
|
||||
assertEquals("3", map.computeIfAbsent(3) { it.toString() })
|
||||
assertEquals(null, map.computeIfAbsent(0) { null })
|
||||
}
|
||||
|
||||
@Test fun computeIfPresent() {
|
||||
val map = mutableMapOf(2 to "x")
|
||||
assertEquals("2x", map.computeIfPresent(2) { k, v -> k.toString() + v })
|
||||
assertEquals(null, map.computeIfPresent(3) { k, v -> k.toString() + v })
|
||||
// fails due to KT-12144
|
||||
// assertEquals(null, map.computeIfPresent(2) { k, v -> null })
|
||||
// assertFalse(2 in map)
|
||||
}
|
||||
|
||||
@Test fun compute() {
|
||||
val map = mutableMapOf(2 to "x")
|
||||
assertEquals("2x", map.compute(2) { k, v -> k.toString() + v })
|
||||
// fails due to KT-12144
|
||||
// assertEquals(null, map.compute(2) { k, v -> null })
|
||||
// assertFalse { 2 in map }
|
||||
assertEquals("1null", map.compute(1) { k, v -> k.toString() + v })
|
||||
}
|
||||
|
||||
@Test fun merge() {
|
||||
val map = mutableMapOf(2 to "x")
|
||||
// fails due to KT-12144
|
||||
// assertEquals("y", map.merge(3, "y") { old, new -> null })
|
||||
// assertEquals(null, map.merge(3, "z") { old, new ->
|
||||
// assertEquals("y", old)
|
||||
// assertEquals("z", new)
|
||||
// null
|
||||
// })
|
||||
// assertFalse(3 in map)
|
||||
|
||||
val map2 = mutableMapOf<Int, Any?>(1 to null)
|
||||
// new value must be V!!
|
||||
assertFails { map2.merge(1, null) { k, v -> 2 } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package kotlin.jdk8.streams.test
|
||||
|
||||
import kotlin.streams.*
|
||||
import org.junit.Test
|
||||
import java.util.stream.*
|
||||
import kotlin.test.*
|
||||
|
||||
class StreamsTest {
|
||||
|
||||
@Test fun toList() {
|
||||
val data = arrayOf(1, 2L, 1.23, null)
|
||||
val streamBuilder = { Stream.of(*data) }
|
||||
|
||||
assertEquals(data.asList(), streamBuilder().toList())
|
||||
assertEquals(listOf(1), streamBuilder().filter { it is Int }.mapToInt { it as Int }.toList())
|
||||
assertEquals(listOf(2L), streamBuilder().filter { it is Long }.mapToLong { it as Long }.toList())
|
||||
assertEquals(listOf(1.23), streamBuilder().filter { it is Double }.mapToDouble { it as Double }.toList())
|
||||
}
|
||||
|
||||
|
||||
@Test fun asSequence() {
|
||||
val data = arrayOf(1, 2L, 1.23, null)
|
||||
|
||||
fun<T> assertSequenceContent(expected: List<T>, actual: Sequence<T>) {
|
||||
assertEquals(expected, actual.toList())
|
||||
assertFailsWith<IllegalStateException> ("Second iteration fails") { actual.toList() }
|
||||
|
||||
}
|
||||
|
||||
assertSequenceContent(data.asList(), Stream.of(*data).asSequence())
|
||||
assertSequenceContent(listOf(1, 2), IntStream.of(1, 2).asSequence())
|
||||
assertSequenceContent(listOf(1L, 2L), LongStream.of(1L, 2L).asSequence())
|
||||
assertSequenceContent(listOf(1.0, 2.0), DoubleStream.of(1.0, 2.0).asSequence())
|
||||
}
|
||||
|
||||
@Test fun asStream() {
|
||||
val sequence = generateSequence(0) { it -> it * it + 1 }
|
||||
val stream = sequence.asStream()
|
||||
val expected = Stream.iterate(0) { it -> it * it + 1 }
|
||||
|
||||
assertEquals(expected.limit(7).toList(), stream.limit(7).toList())
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user