diff --git a/libraries/stdlib/jre7/build.gradle b/libraries/stdlib/jre7/build.gradle new file mode 100644 index 00000000000..c984aeb53cf --- /dev/null +++ b/libraries/stdlib/jre7/build.gradle @@ -0,0 +1,82 @@ +description = 'Kotlin Standard Library JRE 7 extension (deprecated)' + +apply plugin: 'kotlin' + +configureJvm6Project(project) +configurePublishing(project) +ext.javaHome = JDK_17 + +dependencies { + compile project(':kotlin-stdlib') + testCompile project(':kotlin-test:kotlin-test-junit') +} + +sourceSets { + main { + kotlin { + srcDir 'src' + } + } + test { + kotlin { + srcDir 'test' + if(!System.properties.'idea.active') { + srcDir '../test' + } + } + } +} + +jar { + manifestAttributes(manifest, project, 'Main') +} + +artifacts { + archives sourcesJar + archives javadocJar +} + +dist { + from (jar, sourcesJar) +} + + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions.jdkHome = JDK_17 +} + +compileKotlin { + kotlinOptions.freeCompilerArgs = [ + "-Xallow-kotlin-package", + "-Xmultifile-parts-inherit", + "-Xdump-declarations-to", "${buildDir}/stdlib-jre7-declarations.json", + "-module-name", project.name + ] +} + +compileTestKotlin { + kotlinOptions.freeCompilerArgs = ["-Xallow-kotlin-package"] +} + +kotlin.experimental.coroutines 'enable' + +test { + executable = "$JDK_17/bin/java" +} + +task testJre6Tests(type: Test) { + dependsOn(':kotlin-stdlib:testClasses') + group = "verification" + + executable = "$JDK_17/bin/java" + + doFirst { + testClassesDirs = project(':kotlin-stdlib').sourceSets.test.output + classpath = files( + testClassesDirs, + configurations.testCompile + ) + } +} + +check.dependsOn testJre6Tests \ No newline at end of file diff --git a/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt new file mode 100644 index 00000000000..cf47b37dea9 --- /dev/null +++ b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2017 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. + */ + +@file:JvmName("AutoCloseableKt") +package kotlin + +/** + * Executes the given [block] function on this resource and then closes it down correctly whether an exception + * is thrown or not. + * + * In case if the resource is being closed due to an exception occurred in [block], and the closing also fails with an exception, + * the latter is added to the [suppressed][java.lang.Throwable.addSuppressed] exceptions of the former. + * + * @param block a function to process this [AutoCloseable] resource. + * @return the result of [block] function invoked on this resource. + */ +@SinceKotlin("1.1") +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@kotlin.internal.InlineOnly +public inline fun T.use(block: (T) -> R): R { + var exception: Throwable? = null + try { + return block(this) + } catch (e: Throwable) { + exception = e + throw e + } finally { + this.closeFinally(exception) + } +} + +/** + * Closes this [AutoCloseable], suppressing possible exception or error thrown by [AutoCloseable.close] function when + * it's being closed due to some other [cause] exception occurred. + * + * The suppressed exception is added to the list of suppressed exceptions of [cause] exception. + */ +@SinceKotlin("1.1") +@PublishedApi +internal fun AutoCloseable?.closeFinally(cause: Throwable?) = when { + this == null -> {} + cause == null -> close() + else -> + try { + close() + } catch (closeException: Throwable) { + cause.addSuppressed(closeException) + } +} diff --git a/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt new file mode 100644 index 00000000000..136116e4840 --- /dev/null +++ b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2017 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.internal + +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") +internal open class JRE7PlatformImplementations : PlatformImplementations() { + + override fun addSuppressed(cause: Throwable, exception: Throwable) = cause.addSuppressed(exception) + +} diff --git a/libraries/stdlib/jre7/test/TryWithResourcesAutoCloseableTest.kt b/libraries/stdlib/jre7/test/TryWithResourcesAutoCloseableTest.kt new file mode 100644 index 00000000000..9d60ffd7f56 --- /dev/null +++ b/libraries/stdlib/jre7/test/TryWithResourcesAutoCloseableTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright 2010-2017 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.jdk7.test + +import java.io.* +import org.junit.Test +import java.util.* +import kotlin.test.* + +class TryWithResourcesAutoCloseableTest { + + @Suppress("HasPlatformType") fun platformNull() = Collections.singletonList(null as T).first() + + 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 { _ -> + Resource(faultyClose = true).use { _ -> + 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) + } + } + + + @Test fun nullableResourceSuccess() { + val resource: Resource? = null + val result = resource.use { "ok" } + assertEquals("ok", result) + } + + @Test fun nullableResourceOpFails() { + val resource: Resource? = null + val e = assertFails { + resource.use { requireNotNull(it) } + } + assertTrue(e is IllegalArgumentException) + assertTrue(e.suppressed.isEmpty()) + } + + @Test fun platformResourceOpFails() { + val resource = platformNull() + val e = assertFails { + resource.use { requireNotNull(it) } + } + assertTrue(e is IllegalArgumentException) + assertTrue(e.suppressed.isEmpty()) + } + +} diff --git a/libraries/stdlib/jre7/test/TryWithResourcesCloseableTest.kt b/libraries/stdlib/jre7/test/TryWithResourcesCloseableTest.kt new file mode 100644 index 00000000000..46425c363ab --- /dev/null +++ b/libraries/stdlib/jre7/test/TryWithResourcesCloseableTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2017 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.jdk7.test + +import org.junit.Ignore +import java.io.* +import org.junit.Test +import java.util.* +import kotlin.test.* + +class TryWithResourcesCloseableTest { + + @Suppress("HasPlatformType") fun platformNull() = Collections.singletonList(null as T).first() + + 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()) + } + + @Ignore + @Test fun opFailsCloseFails() { + val e = assertFails { + Resource(faultyClose = true).use { error("op fail") } + } + assertTrue(e is IllegalStateException) + assertTrue(e.suppressed.single() is IOException) + } + + @Ignore + @Test fun opFailsCloseFailsTwice() { + val e = assertFails { + Resource(faultyClose = true).use { _ -> + Resource(faultyClose = true).use { _ -> + 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) + } + + } + + @Test fun nullableResourceSuccess() { + val resource: Resource? = null + val result = resource.use { "ok" } + assertEquals("ok", result) + } + + @Test fun nullableResourceOpFails() { + val resource: Resource? = null + val e = assertFails { + resource.use { requireNotNull(it) } + } + assertTrue(e is IllegalArgumentException) + assertTrue(e.suppressed.isEmpty()) + } + + @Test fun platformResourceOpFails() { + val resource = platformNull() + val e = assertFails { + resource.use { requireNotNull(it) } + } + assertTrue(e is IllegalArgumentException) + assertTrue(e.suppressed.isEmpty()) + } +} diff --git a/libraries/stdlib/jre7/test/internalAnnotations.kt b/libraries/stdlib/jre7/test/internalAnnotations.kt new file mode 100644 index 00000000000..9a1b933f996 --- /dev/null +++ b/libraries/stdlib/jre7/test/internalAnnotations.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2017 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. + */ + +@file:JvmVersion +package kotlin.jvm + +@Target(AnnotationTarget.FILE, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.SOURCE) +internal annotation class JvmVersion(public val minimum: Int = 6, public val maximum: Int = 100) diff --git a/libraries/stdlib/jre8/build.gradle b/libraries/stdlib/jre8/build.gradle new file mode 100644 index 00000000000..b773d395819 --- /dev/null +++ b/libraries/stdlib/jre8/build.gradle @@ -0,0 +1,86 @@ +description = 'Kotlin Standard Library JRE 8 extension (deprecated)' + +apply plugin: 'kotlin' + +configureJvm6Project(project) +configurePublishing(project) +ext.javaHome = JDK_18 +ext.jvmTarget = "1.8" + +dependencies { + compile project(':kotlin-stdlib') + compile project(':kotlin-stdlib-jre7') + testCompile project(':kotlin-test:kotlin-test-junit') +} + +sourceSets { + main { + kotlin { + srcDir 'src' + } + } + test { + kotlin { + srcDir 'test' + if(!System.properties.'idea.active') { + srcDir '../test' + srcDir '../jre7/test' + } + } + } +} + +jar { + manifestAttributes(manifest, project, 'Main') +} + +artifacts { + archives sourcesJar + archives javadocJar +} + +dist { + from (jar, sourcesJar) +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions.jdkHome = JDK_18 + kotlinOptions.jvmTarget = 1.8 +} + +compileKotlin { + kotlinOptions.freeCompilerArgs = [ + "-Xallow-kotlin-package", + "-Xmultifile-parts-inherit", + "-Xdump-declarations-to", "${buildDir}/stdlib-jre8-declarations.json", + "-module-name", project.name + ] +} + +compileTestKotlin { + kotlinOptions.freeCompilerArgs = ["-Xallow-kotlin-package"] +} + +kotlin.experimental.coroutines 'enable' + +test { + executable = "$JDK_18/bin/java" +} + + +task testJre6Tests(type: Test) { + dependsOn(':kotlin-stdlib:testClasses') + group = "verification" + + executable = "$JDK_18/bin/java" + + doFirst { + testClassesDirs = project(':kotlin-stdlib').sourceSets.test.output + classpath = files( + testClassesDirs, + configurations.testCompile + ) + } +} + +check.dependsOn testJre6Tests \ No newline at end of file diff --git a/libraries/stdlib/jre8/src/kotlin/collections/Collections.kt b/libraries/stdlib/jre8/src/kotlin/collections/Collections.kt new file mode 100644 index 00000000000..38870e5c550 --- /dev/null +++ b/libraries/stdlib/jre8/src/kotlin/collections/Collections.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2017 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. + */ + +@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. + */ +@SinceKotlin("1.1") +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes K, V> Map.getOrDefault(key: K, defaultValue: V): V + = (this as Map).getOrDefault(key, defaultValue) + + +/** + * Removes the entry for the specified key only if it is currently + * mapped to the specified value. + */ +@SinceKotlin("1.1") +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@kotlin.internal.InlineOnly +public inline fun <@kotlin.internal.OnlyInputTypes K, @kotlin.internal.OnlyInputTypes V> MutableMap.remove(key: K, value: V): Boolean + = (this as MutableMap).remove(key, value) diff --git a/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt b/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt new file mode 100644 index 00000000000..b4a0e12b322 --- /dev/null +++ b/libraries/stdlib/jre8/src/kotlin/internal/JRE8PlatformImplementations.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 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.internal + +import java.util.regex.MatchResult +import java.util.regex.Matcher + +@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") +internal open class JRE8PlatformImplementations : JRE7PlatformImplementations() { + + override fun getMatchResultNamedGroup(matchResult: MatchResult, name: String): MatchGroup? { + val matcher = matchResult as? Matcher ?: throw UnsupportedOperationException("Retrieving groups by name is not supported on this platform.") + + val range = matcher.start(name)..matcher.end(name)-1 + return if (range.start >= 0) + MatchGroup(matcher.group(name), range) + else + null + } + +} diff --git a/libraries/stdlib/jre8/src/kotlin/streams/Streams.kt b/libraries/stdlib/jre8/src/kotlin/streams/Streams.kt new file mode 100644 index 00000000000..28327fc7951 --- /dev/null +++ b/libraries/stdlib/jre8/src/kotlin/streams/Streams.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2017 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. + */ + +@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. + */ +@SinceKotlin("1.1") +public fun Stream.asSequence(): Sequence = Sequence { iterator() } + +/** + * Creates a [Sequence] instance that wraps the original stream iterating through its elements. + */ +@SinceKotlin("1.1") +public fun IntStream.asSequence(): Sequence = Sequence { iterator() } + +/** + * Creates a [Sequence] instance that wraps the original stream iterating through its elements. + */ +@SinceKotlin("1.1") +public fun LongStream.asSequence(): Sequence = Sequence { iterator() } + +/** + * Creates a [Sequence] instance that wraps the original stream iterating through its elements. + */ +@SinceKotlin("1.1") +public fun DoubleStream.asSequence(): Sequence = Sequence { iterator() } + +/** + * Creates a sequential [Stream] instance that produces elements from the original sequence. + */ +@SinceKotlin("1.1") +public fun Sequence.asStream(): Stream = StreamSupport.stream({ Spliterators.spliteratorUnknownSize(iterator(), Spliterator.ORDERED) }, Spliterator.ORDERED, false) + +/** + * Returns a [List] containing all elements produced by this stream. + */ +@SinceKotlin("1.1") +public fun Stream.toList(): List = collect(Collectors.toList()) + +/** + * Returns a [List] containing all elements produced by this stream. + */ +@SinceKotlin("1.1") +public fun IntStream.toList(): List = toArray().asList() + +/** + * Returns a [List] containing all elements produced by this stream. + */ +@SinceKotlin("1.1") +public fun LongStream.toList(): List = toArray().asList() + +/** + * Returns a [List] containing all elements produced by this stream. + */ +@SinceKotlin("1.1") +public fun DoubleStream.toList(): List = toArray().asList() diff --git a/libraries/stdlib/jre8/src/kotlin/text/RegexExtensions.kt b/libraries/stdlib/jre8/src/kotlin/text/RegexExtensions.kt new file mode 100644 index 00000000000..098ee02b9f7 --- /dev/null +++ b/libraries/stdlib/jre8/src/kotlin/text/RegexExtensions.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2017 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. + */ + +@file:JvmName("RegexExtensionsJRE8Kt") +package kotlin.text + +/** + * Returns a named group with the specified [name]. + * + * @return An instance of [MatchGroup] if the group with the specified [name] was matched or `null` otherwise. + * @throws [UnsupportedOperationException] if getting named groups isn't supported on the current platform. + */ +@SinceKotlin("1.1") +public operator fun MatchGroupCollection.get(name: String): MatchGroup? { + val namedGroups = this as? MatchNamedGroupCollection ?: + throw UnsupportedOperationException("Retrieving groups by name is not supported on this platform.") + + return namedGroups[name] +} diff --git a/libraries/stdlib/jre8/test/collections/CollectionTest.kt b/libraries/stdlib/jre8/test/collections/CollectionTest.kt new file mode 100644 index 00000000000..ef79925ef4c --- /dev/null +++ b/libraries/stdlib/jre8/test/collections/CollectionTest.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2017 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.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 = data.toMutableList() + assertTrue(coll.removeIf { it.length < 3 }) + assertEquals(listOf("abc", "baar"), coll as Collection) + assertFalse(coll.removeIf(Predicate { it.length > 4 })) + } + + +} diff --git a/libraries/stdlib/jre8/test/collections/IterableTest.kt b/libraries/stdlib/jre8/test/collections/IterableTest.kt new file mode 100644 index 00000000000..d1117205949 --- /dev/null +++ b/libraries/stdlib/jre8/test/collections/IterableTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 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.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) + }) + } + +} diff --git a/libraries/stdlib/jre8/test/collections/ListTest.kt b/libraries/stdlib/jre8/test/collections/ListTest.kt new file mode 100644 index 00000000000..6672287e3f0 --- /dev/null +++ b/libraries/stdlib/jre8/test/collections/ListTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 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.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) + } +} diff --git a/libraries/stdlib/jre8/test/collections/MapTest.kt b/libraries/stdlib/jre8/test/collections/MapTest.kt new file mode 100644 index 00000000000..6f1d49206af --- /dev/null +++ b/libraries/stdlib/jre8/test/collections/MapTest.kt @@ -0,0 +1,144 @@ +/* + * Copyright 2010-2017 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.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)) + + val nonNullMap = mapOf("x" to 1) + assertEquals(null, nonNullMap.getOrDefault("y" as CharSequence, null)) // should pass + assertEquals("none", nonNullMap.getOrDefault("y" as CharSequence, "none")) // should not compile + } + + @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 = mutableMapOf("a" to "b", "c" to "d") + + map.replaceAll { k, v -> k + v } + assertEquals(mapOf("a" to "ab", "c" to "cd"), map) + + val operator = BiFunction { k, v -> k.toString() + v.toString() } + map.replaceAll(operator) + assertEquals(mapOf("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") + assertEquals("x", map.computeIfAbsent(2) { it.toString() }) + assertEquals("3", map.computeIfAbsent(3) { it.toString() }) + // prohibited: map.computeIfAbsent(0) { null } + + val map2 = mutableMapOf(2 to "x", 3 to null) + assertEquals("x", map2.computeIfAbsent(2) { it.toString() }) + assertEquals("3", map2.computeIfAbsent(3) { it.toString() }) + assertEquals(null, map2.computeIfAbsent(0) { null }) + assertFalse(0 in map2) + } + + @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 }) + assertEquals(null, map.computeIfPresent(2) { _, _ -> null }) + assertFalse(2 in map) + + val map2 = mutableMapOf(2 to "x") + assertEquals("2x", map2.computeIfPresent(2) { k, v -> k.toString() + v }) + assertEquals(null, map2.computeIfPresent(3) { k, v -> k.toString() + v }) + assertEquals(null, map2.computeIfPresent(2) { _, _ -> null }) + assertFalse(2 in map2) + } + + @Test fun compute() { + val map = mutableMapOf(2 to "x") + assertEquals("2x", map.compute(2) { k, v -> k.toString() + v }) + assertEquals(null, map.compute(2) { _, _ -> null }) + assertFalse { 2 in map } + assertEquals("1null", map.compute(1) { k, v -> k.toString() + v }) + } + + @Test fun merge() { + val map = mutableMapOf(2 to "x") + assertEquals("y", map.merge(3, "y") { _, _ -> null }) + assertEquals(null, map.merge(3, "z") { old, new -> + assertEquals("y", old) + assertEquals("z", new) + null + }) + assertFalse(3 in map) + + // fails due to KT-12144 + val map2 = mutableMapOf(1 to null) + // new value must be V&Any + assertEquals("e", map2.merge(1, "e") { old, new -> (old.length + new.length).toString() ?: null }) + assertEquals("3", map2.merge(1, "fg") { old, new -> (old.length + new.length).toString() ?: null }) + assertEquals(null, map2.merge(1, "3") { _, _ -> null }) + assertFalse(1 in map) + } +} diff --git a/libraries/stdlib/jre8/test/collections/StreamsTest.kt b/libraries/stdlib/jre8/test/collections/StreamsTest.kt new file mode 100644 index 00000000000..86a122e9151 --- /dev/null +++ b/libraries/stdlib/jre8/test/collections/StreamsTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2017 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.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 assertSequenceContent(expected: List, actual: Sequence) { + assertEquals(expected, actual.toList()) + assertFailsWith ("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()) + } + + @Test fun asParallelStream() { + val sequence = generateSequence(0) { it + 2 } // even numbers + val stream = sequence.asStream().parallel().map { it / 2 } + + val n = 100000 + val expected = (0 until n).toList() + + assertEquals(expected, stream.limit(n.toLong()).toList()) + } + +} diff --git a/libraries/stdlib/jre8/test/text/RegexTest.kt b/libraries/stdlib/jre8/test/text/RegexTest.kt new file mode 100644 index 00000000000..f3d13fc556a --- /dev/null +++ b/libraries/stdlib/jre8/test/text/RegexTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2017 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.text.test + +import org.junit.Test +import kotlin.test.* + +class RegexTest { + @Test fun namedGroups() { + val input = "1a 2b 3c" + val regex = "(?\\d)(?\\w)".toRegex() + + val matches = regex.findAll(input).toList() + assertTrue(matches.all { it.groups.size == 3 }) + val m1 = matches[0] + + assertEquals("1", m1.groups["num"]?.value) + assertEquals(0..0, m1.groups["num"]?.range) + assertEquals("a", m1.groups["liter"]?.value) + assertEquals(1..1, m1.groups["liter"]?.range) + + val m2 = matches[1] + assertEquals("2", m2.groups["num"]?.value) + assertEquals(3..3, m2.groups["num"]?.range) + assertEquals("b", m2.groups["liter"]?.value) + assertEquals(4..4, m2.groups["liter"]?.range) + } +} diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre7.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre7.txt new file mode 100644 index 00000000000..5e9eb275b06 --- /dev/null +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre7.txt @@ -0,0 +1,4 @@ +public final class kotlin/AutoCloseableKt { + public static final fun closeFinally (Ljava/lang/AutoCloseable;Ljava/lang/Throwable;)V +} + diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre8.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre8.txt new file mode 100644 index 00000000000..cb60b69937b --- /dev/null +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-jre8.txt @@ -0,0 +1,16 @@ +public final class kotlin/streams/StreamsKt { + public static final fun asSequence (Ljava/util/stream/DoubleStream;)Lkotlin/sequences/Sequence; + public static final fun asSequence (Ljava/util/stream/IntStream;)Lkotlin/sequences/Sequence; + public static final fun asSequence (Ljava/util/stream/LongStream;)Lkotlin/sequences/Sequence; + public static final fun asSequence (Ljava/util/stream/Stream;)Lkotlin/sequences/Sequence; + public static final fun asStream (Lkotlin/sequences/Sequence;)Ljava/util/stream/Stream; + public static final fun toList (Ljava/util/stream/DoubleStream;)Ljava/util/List; + public static final fun toList (Ljava/util/stream/IntStream;)Ljava/util/List; + public static final fun toList (Ljava/util/stream/LongStream;)Ljava/util/List; + public static final fun toList (Ljava/util/stream/Stream;)Ljava/util/List; +} + +public final class kotlin/text/RegexExtensionsJRE8Kt { + public static final fun get (Lkotlin/text/MatchGroupCollection;Ljava/lang/String;)Lkotlin/text/MatchGroup; +} +