diff --git a/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt new file mode 100644 index 00000000000..8fd4b5636e4 --- /dev/null +++ b/libraries/stdlib/jre7/src/kotlin/AutoCloseable.kt @@ -0,0 +1,61 @@ +/* + * 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. + */ + +@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 closed = false + try { + return block(this) + } catch (e: Throwable) { + closed = true + this?.closeSuppressed(e) + throw e + } finally { + if (this != null && !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. + */ +@SinceKotlin("1.1") +@PublishedApi +internal fun AutoCloseable.closeSuppressed(cause: Throwable) { + try { + close() + } catch (closeException: Throwable) { + cause.addSuppressed(closeException) + } +} + diff --git a/libraries/stdlib/jre7/src/kotlin/Standard.kt b/libraries/stdlib/jre7/src/kotlin/Standard.kt index 332b65f746a..4d7f92462bd 100644 --- a/libraries/stdlib/jre7/src/kotlin/Standard.kt +++ b/libraries/stdlib/jre7/src/kotlin/Standard.kt @@ -1,45 +1,10 @@ @file:JvmName("StandardJRE7Kt") 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 closed = false - try { - return block(this) - } catch (e: Throwable) { - closed = true - this?.closeSuppressed(e) - throw e - } finally { - if (this != null && !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. - */ +// TODO: Drop before 1.1 @SinceKotlin("1.1") @PublishedApi -internal fun AutoCloseable.closeSuppressed(cause: Throwable) { - try { - close() - } catch (closeException: Throwable) { - cause.addSuppressed(closeException) - } -} +@Deprecated("Provided for binary compatibility") +@JvmName("closeSuppressed") +internal fun AutoCloseable.closeSuppressedDeprecated(cause: Throwable) = closeSuppressed(cause) diff --git a/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt index 4a14282b7c8..5dae5560a66 100644 --- a/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt +++ b/libraries/stdlib/jre7/src/kotlin/internal/JRE7PlatformImplementations.kt @@ -1,8 +1,9 @@ package kotlin.internal -import java.io.Closeable @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "CANNOT_OVERRIDE_INVISIBLE_MEMBER") internal open class JRE7PlatformImplementations : PlatformImplementations() { - override fun closeSuppressed(instance: Closeable, cause: Throwable) = instance.closeSuppressed(cause) + + override fun addSuppressed(cause: Throwable, exception: Throwable) = cause.addSuppressed(exception) + } diff --git a/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt index 6d0de8a18a8..f13ba7d7d92 100644 --- a/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt +++ b/libraries/stdlib/src/kotlin/internal/PlatformImplementations.kt @@ -6,15 +6,8 @@ import java.util.regex.MatchResult internal open class PlatformImplementations { - public open fun closeSuppressed(instance: Closeable, cause: Throwable) { - try { - instance.close() - } catch (closeException: Throwable) { - // eat the closeException as we are already throwing the original cause - // and we don't want to mask the real exception; - // on Java 7 we should call - // e.addSuppressed(closeException) - } + public open fun addSuppressed(cause: Throwable, exception: Throwable) { + // do nothing } public open fun getMatchResultNamedGroup(matchResult: MatchResult, name: String): MatchGroup? { @@ -22,9 +15,11 @@ internal open class PlatformImplementations { } } +// TODO: drop before 1.1 @SinceKotlin("1.1") @PublishedApi -internal fun platformCloseSuppressed(instance: Closeable, cause: Throwable) = IMPLEMENTATIONS.closeSuppressed(instance, cause) +@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN) +internal fun platformCloseSuppressed(instance: Closeable, cause: Throwable) = instance.closeSuppressed(cause) @JvmField diff --git a/libraries/stdlib/src/kotlin/io/Closeable.kt b/libraries/stdlib/src/kotlin/io/Closeable.kt new file mode 100644 index 00000000000..4527e419be6 --- /dev/null +++ b/libraries/stdlib/src/kotlin/io/Closeable.kt @@ -0,0 +1,56 @@ +/* + * 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. + */ + +@file:JvmName("CloseableKt") +@file:JvmVersion +package kotlin.io + +import java.io.Closeable +import kotlin.internal.* + +/** + * Executes the given [block] function on this resource and then closes it down correctly whether an exception + * is thrown or not. + * + * @param block a function to process this [Closeable] resource. + * @return the result of [block] function invoked on this resource. + */ +@InlineOnly +public inline fun T.use(block: (T) -> R): R { + var closed = false + try { + return block(this) + } catch (e: Throwable) { + closed = true + this?.closeSuppressed(e) + throw e + } finally { + if (this != null && !closed) { + close() + } + } +} + +@SinceKotlin("1.1") +@PublishedApi +internal fun Closeable.closeSuppressed(cause: Throwable) { + try { + close() + } catch (closeException: Throwable) { + // on Java 7 we should call + IMPLEMENTATIONS.addSuppressed(cause, closeException) + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/io/ReadWrite.kt b/libraries/stdlib/src/kotlin/io/ReadWrite.kt index 86210b6eeea..28f66d57241 100644 --- a/libraries/stdlib/src/kotlin/io/ReadWrite.kt +++ b/libraries/stdlib/src/kotlin/io/ReadWrite.kt @@ -143,25 +143,3 @@ public inline fun URL.readText(charset: Charset = Charsets.UTF_8): String = read */ public fun URL.readBytes(): ByteArray = openStream().use { it.readBytes() } -/** - * Executes the given [block] function on this resource and then closes it down correctly whether an exception - * is thrown or not. - * - * @param block a function to process this [Closeable] resource. - * @return the result of [block] function invoked on this resource. - */ -@kotlin.internal.InlineOnly -public inline fun T.use(block: (T) -> R): R { - var closed = false - try { - return block(this) - } catch (e: Throwable) { - closed = true - if (this != null) platformCloseSuppressed(this, e) - throw e - } finally { - if (this != null && !closed) { - close() - } - } -} diff --git a/libraries/stdlib/src/kotlin/util/Exceptions.kt b/libraries/stdlib/src/kotlin/util/Exceptions.kt index 0eebfea4b54..e17f1270610 100644 --- a/libraries/stdlib/src/kotlin/util/Exceptions.kt +++ b/libraries/stdlib/src/kotlin/util/Exceptions.kt @@ -6,6 +6,7 @@ package kotlin import java.io.PrintStream import java.io.PrintWriter +import kotlin.internal.* /** * Prints the stack trace of this throwable to the standard output. @@ -32,3 +33,9 @@ public inline fun Throwable.printStackTrace(stream: PrintStream): Unit = (this a @Suppress("ConflictingExtensionProperty") public val Throwable.stackTrace: Array get() = (this as java.lang.Throwable).stackTrace!! + +/** + * When supported by the platform adds the specified exception to the list of exceptions that were + * suppressed in order to deliver this exception. + */ +public fun Throwable.addSuppressed(exception: Throwable) = IMPLEMENTATIONS.addSuppressed(this, exception) \ No newline at end of file diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt index e0567b89c24..ac8da4ed960 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt @@ -1,4 +1,5 @@ public final class kotlin/ExceptionsKt { + public static final fun addSuppressed (Ljava/lang/Throwable;Ljava/lang/Throwable;)V public static final fun getStackTrace (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement; } @@ -1740,7 +1741,7 @@ public final class kotlin/coroutines/SafeContinuation$Companion { } public final class kotlin/internal/PlatformImplementationsKt { - public static final fun platformCloseSuppressed (Ljava/io/Closeable;Ljava/lang/Throwable;)V + public static final synthetic fun platformCloseSuppressed (Ljava/io/Closeable;Ljava/lang/Throwable;)V } public final class kotlin/io/AccessDeniedException : kotlin/io/FileSystemException { @@ -1756,6 +1757,10 @@ public final class kotlin/io/ByteStreamsKt { public static synthetic fun readBytes$default (Ljava/io/InputStream;IILjava/lang/Object;)[B } +public final class kotlin/io/CloseableKt { + public static final fun closeSuppressed (Ljava/io/Closeable;Ljava/lang/Throwable;)V +} + public final class kotlin/io/ConsoleKt { public static final fun readLine ()Ljava/lang/String; }