From ef1d72ca10c361d2eead443d99241a088e130174 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Sat, 22 Mar 2025 14:29:45 +0300 Subject: [PATCH] Extracted to separate library, 'tryFinallyChain' --- .gitignore | 9 +++++ build.gradle.kts | 36 +++++++++++++++++++ gradle.properties | 1 + settings.gradle.kts | 1 + .../TryFinallyChainScope.kt | 25 +++++++++++++ .../highlevel_try_finally/safe_autoclose.kt | 7 ++-- .../try_finally_chain.kt | 22 ++++++++++++ 7 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 settings.gradle.kts create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/TryFinallyChainScope.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/try_finally_chain.kt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2e4e0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/.idea/ +gradle/ +.gradle/ +build/ +*.class +*.jar +/out/ +/gradlew* +.kotlin/ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..687fa55 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,36 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.* +import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.plugin.xomrk + +buildscript { + repositories { + mavenCentral() + maven("https://maven.landgrafhomyak.ru/") + } + + dependencies { + classpath("ru.landgrafhomyak.kotlin:kotlin-mpp-gradle-build:v0.3k2.1.10") + } +} + +group = "ru.landgrafhomyak.utility" +version = "0.4" + +repositories { + mavenCentral() +} + +xomrk { + kotlin { + setCompatibilityWithKotlin(KotlinVersion.KOTLIN_2_0) + optInContracts() + + defineAllMultiplatformTargets() + } + + publishing { + repositories { + defineXomrkGiteaMavenRepo() + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..7fc6f1f --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +kotlin.code.style=official diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..55661f8 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "highlevel-try-finally" \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/TryFinallyChainScope.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/TryFinallyChainScope.kt new file mode 100644 index 0000000..91c2ced --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/TryFinallyChainScope.kt @@ -0,0 +1,25 @@ +package ru.landgrafhomyak.utility.highlevel_try_finally + +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +class TryFinallyChainScope @PublishedApi internal constructor() { + @PublishedApi + internal var _actualException: Throwable? = null + + @PublishedApi + internal fun _throw() { + this._actualException?.let { e -> throw e } + } + + inline fun action(fn: () -> Unit) { + contract { + callsInPlace(fn, InvocationKind.EXACTLY_ONCE) + } + safeAutoClose3e( + onCrossReturn = { throw Error("Cross return not allowed in tryFinallyChain{action{}}") }, + onError = { err -> this._actualException?.addSuppressed(err) ?: run { this._actualException = err } }, + action = fn + ) + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/safe_autoclose.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/safe_autoclose.kt index 14c50cf..048ae74 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/safe_autoclose.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/safe_autoclose.kt @@ -1,7 +1,11 @@ +@file:Suppress("unused") +@file:JvmName("SafeAutocloseKt") + package ru.landgrafhomyak.utility.highlevel_try_finally import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.jvm.JvmName @Suppress("WRONG_INVOCATION_KIND") inline fun safeAutoClose1( @@ -43,7 +47,6 @@ inline fun safeAutoClose2e( return safeAutoClose3e(onError = onError, onSuccess = onSuccess, onCrossReturn = onSuccess, action = action) } - inline fun safeAutoClose3( onError: () -> Unit = {}, onSuccess: () -> Unit = {}, @@ -95,4 +98,4 @@ inline fun safeAutoClose3e( } } return ret -} +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/try_finally_chain.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/try_finally_chain.kt new file mode 100644 index 0000000..684d568 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/highlevel_try_finally/try_finally_chain.kt @@ -0,0 +1,22 @@ +@file:Suppress("unused") +@file:JvmName("TryFinallyChainKt") + +package ru.landgrafhomyak.utility.highlevel_try_finally + +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName + +inline fun tryFinallyChain(chains: TryFinallyChainScope.() -> Unit) { + contract { + callsInPlace(chains, InvocationKind.EXACTLY_ONCE) + } + + val scope = TryFinallyChainScope() + safeAutoClose3e( + onCrossReturn = { throw Error("Cross return not allowed in tryFinallyChain{}") }, + onError = { err -> throw Error("Unexpected exception in tryFinallyChain{}; calling anything outside action{} block isn't allowed", err) }, + onSuccess = { scope._throw() }, + action = { chains(scope) } + ) +} \ No newline at end of file