From b16fb559a14dcd77139fb907db213184581e6bd6 Mon Sep 17 00:00:00 2001 From: Tristan Hamilton Date: Fri, 7 Aug 2020 14:51:27 +0100 Subject: [PATCH] Move binding coroutine implementation to separate subproject --- README.md | 30 ++ build.gradle.kts | 261 +++++++----------- example/build.gradle.kts | 2 +- kotlin-result-coroutines/build.gradle.kts | 41 +++ .../coroutines/binding/SuspendableBinding.kt | 54 ++++ .../RunBlockingTest.kt | 2 +- .../binding}/SuspendableBindingTest.kt | 4 +- .../result/coroutines}/RunBlockingTest.kt | 2 +- .../binding/AsyncSuspendableBindingTest.kt | 79 ++++++ kotlin-result/build.gradle.kts | 75 +++++ .../com/github/michaelbull/result/And.kt | 0 .../com/github/michaelbull/result/Binding.kt | 0 .../com/github/michaelbull/result/Factory.kt | 0 .../com/github/michaelbull/result/Get.kt | 0 .../com/github/michaelbull/result/Iterable.kt | 0 .../com/github/michaelbull/result/Map.kt | 0 .../com/github/michaelbull/result/On.kt | 0 .../com/github/michaelbull/result/Or.kt | 0 .../com/github/michaelbull/result/Result.kt | 0 .../michaelbull/result/ResultIterator.kt | 0 .../com/github/michaelbull/result/Unwrap.kt | 0 .../com/github/michaelbull/result/Zip.kt | 0 .../result/coroutines/SuspendableBinding.kt | 6 + .../com/github/michaelbull/result/AndTest.kt | 0 .../github/michaelbull/result/BindingTest.kt | 0 .../github/michaelbull/result/FactoryTest.kt | 0 .../com/github/michaelbull/result/GetTest.kt | 0 .../github/michaelbull/result/IterableTest.kt | 0 .../com/github/michaelbull/result/MapTest.kt | 0 .../com/github/michaelbull/result/OnTest.kt | 0 .../com/github/michaelbull/result/OrTest.kt | 0 .../michaelbull/result/ResultIteratorTest.kt | 0 .../github/michaelbull/result/UnwrapTest.kt | 0 .../com/github/michaelbull/result/ZipTest.kt | 0 .../michaelbull/result/BindingBenchmark.kt | 0 .../michaelbull/result/BindException.kt | 0 settings.gradle.kts | 8 +- 37 files changed, 403 insertions(+), 161 deletions(-) create mode 100644 kotlin-result-coroutines/build.gradle.kts create mode 100644 kotlin-result-coroutines/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/binding/SuspendableBinding.kt rename {src/commonTest/kotlin/com/github/michaelbull/result => kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines}/RunBlockingTest.kt (86%) rename {src/commonTest/kotlin/com/github/michaelbull/result/coroutines => kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/binding}/SuspendableBindingTest.kt (96%) rename {src/jvmTest/kotlin/com/github/michaelbull/result => kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines}/RunBlockingTest.kt (79%) create mode 100644 kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/binding/AsyncSuspendableBindingTest.kt create mode 100644 kotlin-result/build.gradle.kts rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/And.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Binding.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Factory.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Get.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Iterable.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Map.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/On.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Or.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Result.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/ResultIterator.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Unwrap.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/Zip.kt (100%) rename {src => kotlin-result/src}/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt (71%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/AndTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/BindingTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/FactoryTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/GetTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/IterableTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/MapTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/OnTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/OrTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/ResultIteratorTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/UnwrapTest.kt (100%) rename {src => kotlin-result/src}/commonTest/kotlin/com/github/michaelbull/result/ZipTest.kt (100%) rename {src => kotlin-result/src}/jvmBenchmark/kotlin/com/github/michaelbull/result/BindingBenchmark.kt (100%) rename {src => kotlin-result/src}/jvmMain/kotlin/com/github/michaelbull/result/BindException.kt (100%) diff --git a/README.md b/README.md index 17bd381..be6005d 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,36 @@ resources on the topic of monad comprehensions. - [Monad comprehensions - Bow (Swift)][bow-monad-comprehension] - [For comprehensions - Scala][scala-for-comprehension] +#### Coroutine Support + +Use of coroutines within a `binding` block requires an additional dependency: + +```kotlin +dependencies { + implementation("com.michael-bull.kotlin-result:kotlin-result:1.1.8") + implementation("com.michael-bull.kotlin-result:kotlin-result-coroutines:1.1.8") +} +``` + +This allows for asynchronous binds to operate so that if a bind were to fail, +the binding block will return with the first failing async result: + +```kotlin + +suspend fun failsIn5ms(): Result { ... } +suspend fun failsIn1ms(): Result { ... } + +runBlocking{ + val result = binding { + val x = async { failsIn5ms().bind() } + val y = async { failsIn1ms().bind() } + x.await() + y.await() + } + + // result will be Err(DomainErrorB) +} +``` + ## Inspiration Inspiration for this library has been drawn from other languages in which the diff --git a/build.gradle.kts b/build.gradle.kts index af8a49b..ea88530 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,7 @@ import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper val ossrhUsername: String? by ext val ossrhPassword: String? by ext @@ -7,14 +9,14 @@ val ossrhPassword: String? by ext description = "A Result monad for modelling success or failure operations." plugins { - `maven-publish` - signing - kotlin("multiplatform") version "1.3.72" - id("org.jetbrains.dokka") version "0.10.1" + base id("com.github.ben-manes.versions") version "0.28.0" - id("net.researchgate.release") version "2.8.1" - id("kotlinx.benchmark") version "0.2.0-dev-8" - id("org.jetbrains.kotlin.plugin.allopen") version "1.3.72" + + kotlin("multiplatform") version "1.3.72" apply false + id("kotlinx.benchmark") version "0.2.0-dev-8" apply false + id("net.researchgate.release") version "2.8.1" apply false + id("org.jetbrains.dokka") version "0.10.1" apply false + id("org.jetbrains.kotlin.plugin.allopen") version "1.3.72" apply false } tasks.withType { @@ -25,19 +27,6 @@ tasks.withType { } } -val dokka by tasks.existing(DokkaTask::class) { - outputFormat = "javadoc" - outputDirectory = "$buildDir/docs/javadoc" -} - -val javadocJar by tasks.registering(Jar::class) { - group = LifecycleBasePlugin.BUILD_GROUP - description = "Assembles a jar archive containing the Javadoc API documentation." - archiveClassifier.set("javadoc") - dependsOn(dokka) - from(dokka.get().outputDirectory) -} - allprojects { repositories { mavenCentral() @@ -46,155 +35,119 @@ allprojects { } } -allOpen { - annotation("org.openjdk.jmh.annotations.State") - annotation("org.openjdk.jmh.annotations.BenchmarkMode") -} +subprojects { + plugins.withType { + apply(plugin = "net.researchgate.release") + apply(plugin = "org.gradle.signing") -sourceSets.create("benchmark") + val afterReleaseBuild by tasks.existing(DefaultTask::class) + val publish by tasks.existing(Task::class) -benchmark { - targets { - register("jvmBenchmark") - } -} - -kotlin { - jvm { - withJava() - - mavenPublication { - artifact(javadocJar.get()) + afterReleaseBuild { + dependsOn(publish) } - compilations.all { - kotlinOptions { - jvmTarget = "1.8" + plugins.withType { + apply(plugin = "org.jetbrains.dokka") + + val dokka by tasks.existing(DokkaTask::class) { + outputFormat = "javadoc" + outputDirectory = "$buildDir/docs/javadoc" } - } - } - sourceSets { - all { - languageSettings.apply { - useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + val javadocJar by tasks.registering(Jar::class) { + group = LifecycleBasePlugin.BUILD_GROUP + description = "Assembles a jar archive containing the Javadoc API documentation." + archiveClassifier.set("javadoc") + dependsOn(dokka) + from(dokka.get().outputDirectory) + } + + configure { + jvm { + mavenPublication { + artifact(javadocJar.get()) + } + } } } - val commonMain by getting { - dependencies { - implementation(kotlin("stdlib-common")) - } - } + configure { + repositories { + maven { + if (project.version.toString().endsWith("SNAPSHOT")) { + setUrl("https://oss.sonatype.org/content/repositories/snapshots") + } else { + setUrl("https://oss.sonatype.org/service/local/staging/deploy/maven2") + } - val commonTest by getting { - dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.7") + credentials { + username = ossrhUsername + password = ossrhPassword + } + } } - } - val jvmMain by getting { - dependencies { - implementation(kotlin("stdlib-jdk8")) + publications.withType { + pom { + name.set(project.name) + description.set(project.description) + url.set("https://github.com/michaelbull/kotlin-result") + inceptionYear.set("2017") + + licenses { + license { + name.set("ISC License") + url.set("https://opensource.org/licenses/isc-license.txt") + } + } + + developers { + developer { + name.set("Michael Bull") + url.set("https://www.michael-bull.com") + } + } + + contributors { + contributor { + name.set("Kevin Herron") + url.set("https://github.com/kevinherron") + } + + contributor { + name.set("Markus Padourek") + url.set("https://github.com/Globegitter") + } + + contributor { + name.set("Tristan Hamilton") + url.set("https://github.com/Munzey") + } + } + + scm { + connection.set("scm:git:https://github.com/michaelbull/kotlin-result") + developerConnection.set("scm:git:git@github.com:michaelbull/kotlin-result.git") + url.set("https://github.com/michaelbull/kotlin-result") + } + + issueManagement { + system.set("GitHub") + url.set("https://github.com/michaelbull/kotlin-result/issues") + } + + ciManagement { + system.set("GitHub") + url.set("https://github.com/michaelbull/kotlin-result/actions?query=workflow%3Aci") + } + } } - } - val jvmTest by getting { - dependencies { - implementation(kotlin("test-junit")) - implementation(kotlin("test")) - } - } - - val jvmBenchmark by getting { - dependsOn(jvmMain) - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + configure { + useGpgCmd() + sign(publications) } } } } - -publishing { - repositories { - maven { - if (project.version.toString().endsWith("SNAPSHOT")) { - setUrl("https://oss.sonatype.org/content/repositories/snapshots") - } else { - setUrl("https://oss.sonatype.org/service/local/staging/deploy/maven2") - } - - credentials { - username = ossrhUsername - password = ossrhPassword - } - } - } - - publications.withType { - pom { - name.set(project.name) - description.set(project.description) - url.set("https://github.com/michaelbull/kotlin-result") - inceptionYear.set("2017") - - licenses { - license { - name.set("ISC License") - url.set("https://opensource.org/licenses/isc-license.txt") - } - } - - developers { - developer { - name.set("Michael Bull") - url.set("https://www.michael-bull.com") - } - } - - contributors { - contributor { - name.set("Kevin Herron") - url.set("https://github.com/kevinherron") - } - - contributor { - name.set("Markus Padourek") - url.set("https://github.com/Globegitter") - } - - contributor { - name.set("Tristan Hamilton") - url.set("https://github.com/Munzey") - } - } - - scm { - connection.set("scm:git:https://github.com/michaelbull/kotlin-result") - developerConnection.set("scm:git:git@github.com:michaelbull/kotlin-result.git") - url.set("https://github.com/michaelbull/kotlin-result") - } - - issueManagement { - system.set("GitHub") - url.set("https://github.com/michaelbull/kotlin-result/issues") - } - - ciManagement { - system.set("GitHub") - url.set("https://github.com/michaelbull/kotlin-result/actions?query=workflow%3Aci") - } - } - } -} - -signing { - useGpgCmd() - sign(publishing.publications) -} - -tasks.afterReleaseBuild { - dependsOn(tasks.publish) -} diff --git a/example/build.gradle.kts b/example/build.gradle.kts index 2bf8eb4..4053bcc 100644 --- a/example/build.gradle.kts +++ b/example/build.gradle.kts @@ -17,7 +17,7 @@ repositories { dependencies { val ktorVersion = "1.3.2" - implementation(rootProject) + implementation(project(":kotlin-result")) implementation(kotlin("stdlib-jdk8")) implementation("ch.qos.logback:logback-classic:1.2.3") implementation("io.ktor:ktor-server-core:$ktorVersion") diff --git a/kotlin-result-coroutines/build.gradle.kts b/kotlin-result-coroutines/build.gradle.kts new file mode 100644 index 0000000..8b24b48 --- /dev/null +++ b/kotlin-result-coroutines/build.gradle.kts @@ -0,0 +1,41 @@ +description = "Extensions for using kotlin-result with kotlinx-coroutines." + +plugins { + `maven-publish` + kotlin("multiplatform") +} + +kotlin { + sourceSets { + all { + languageSettings.apply { + useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + } + } + + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.8") + implementation(project(":kotlin-result")) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.8") + } + } + + val jvmTest by getting { + dependencies { + implementation(kotlin("test-junit")) + implementation(kotlin("test")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8") + } + } + } +} + diff --git a/kotlin-result-coroutines/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/binding/SuspendableBinding.kt b/kotlin-result-coroutines/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/binding/SuspendableBinding.kt new file mode 100644 index 0000000..b4f5cf3 --- /dev/null +++ b/kotlin-result-coroutines/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/binding/SuspendableBinding.kt @@ -0,0 +1,54 @@ +package com.github.michaelbull.result.coroutines.binding + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +/** + * Suspending variant of [binding][com.github.michaelbull.result.binding]. + */ +suspend inline fun binding(crossinline block: suspend SuspendableResultBinding.() -> V): Result { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + + val receiver = SuspendableResultBindingImpl() + + return try { + with(receiver) { Ok(block()) } + } catch (ex: BindCancellationException) { + receiver.internalError + } +} + +internal object BindCancellationException : CancellationException(null) + +interface SuspendableResultBinding { + suspend fun Result.bind(): V +} + +@PublishedApi +internal class SuspendableResultBindingImpl : SuspendableResultBinding { + + private val mutex = Mutex() + lateinit var internalError: Err + + override suspend fun Result.bind(): V { + return when (this) { + is Ok -> value + is Err -> { + mutex.withLock { + if (::internalError.isInitialized.not()){ + internalError = this + } + } + throw BindCancellationException + } + } + } +} diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt b/kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/RunBlockingTest.kt similarity index 86% rename from src/commonTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt rename to kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/RunBlockingTest.kt index 0fe64d6..46d683a 100644 --- a/src/commonTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt +++ b/kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/RunBlockingTest.kt @@ -1,4 +1,4 @@ -package com.github.michaelbull.result +package com.github.michaelbull.result.coroutines import kotlinx.coroutines.CoroutineScope diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/coroutines/SuspendableBindingTest.kt b/kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/binding/SuspendableBindingTest.kt similarity index 96% rename from src/commonTest/kotlin/com/github/michaelbull/result/coroutines/SuspendableBindingTest.kt rename to kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/binding/SuspendableBindingTest.kt index fe47d18..6c4fdd0 100644 --- a/src/commonTest/kotlin/com/github/michaelbull/result/coroutines/SuspendableBindingTest.kt +++ b/kotlin-result-coroutines/src/commonTest/kotlin/com.github.michaelbull.result.coroutines/binding/SuspendableBindingTest.kt @@ -1,9 +1,9 @@ -package com.github.michaelbull.result.coroutines +package com.github.michaelbull.result.coroutines.binding import com.github.michaelbull.result.Err import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result -import com.github.michaelbull.result.runBlockingTest +import com.github.michaelbull.result.coroutines.runBlockingTest import kotlinx.coroutines.delay import kotlin.test.Test import kotlin.test.assertEquals diff --git a/src/jvmTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt b/kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/RunBlockingTest.kt similarity index 79% rename from src/jvmTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt rename to kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/RunBlockingTest.kt index 4fa0512..1abb138 100644 --- a/src/jvmTest/kotlin/com/github/michaelbull/result/RunBlockingTest.kt +++ b/kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/RunBlockingTest.kt @@ -1,4 +1,4 @@ -package com.github.michaelbull.result +package com.github.michaelbull.result.coroutines import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.runBlocking diff --git a/kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/binding/AsyncSuspendableBindingTest.kt b/kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/binding/AsyncSuspendableBindingTest.kt new file mode 100644 index 0000000..f8910d6 --- /dev/null +++ b/kotlin-result-coroutines/src/jvmTest/kotlin/com/github/michaelbull/result/coroutines/binding/AsyncSuspendableBindingTest.kt @@ -0,0 +1,79 @@ +package com.github.michaelbull.result.coroutines.binding + +import com.github.michaelbull.result.Err +import com.github.michaelbull.result.Ok +import com.github.michaelbull.result.Result +import kotlinx.coroutines.async +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class AsyncSuspendableBindingTest { + + private sealed class BindingError { + object BindingErrorA : BindingError() + object BindingErrorB : BindingError() + } + + @Test + fun returnsOkIfAllBindsSuccessful() { + suspend fun provideX(): Result { + delay(100) + return Ok(1) + } + + suspend fun provideY(): Result { + delay(100) + return Ok(2) + } + + runBlocking { + val result = binding { + val x = async { provideX().bind() } + val y = async { provideY().bind() } + x.await() + y.await() + } + + assertTrue(result is Ok) + assertEquals( + expected = 3, + actual = result.value + ) + } + } + + @Test + fun returnsFirstErrIfBindingFailed() { + suspend fun provideX(): Result { + delay(1) + return Ok(1) + } + + suspend fun provideY(): Result { + delay(2) + return Err(BindingError.BindingErrorA) + } + + suspend fun provideZ(): Result { + delay(1) + return Err(BindingError.BindingErrorB) + } + + runBlocking { + val result = binding { + val x = async { provideX().bind() } + val y = async { provideY().bind() } + val z = async { provideZ().bind() } + x.await() + y.await() + z.await() + } + + assertTrue(result is Err) + assertEquals( + expected = BindingError.BindingErrorB, + actual = result.error + ) + } + } +} diff --git a/kotlin-result/build.gradle.kts b/kotlin-result/build.gradle.kts new file mode 100644 index 0000000..216434f --- /dev/null +++ b/kotlin-result/build.gradle.kts @@ -0,0 +1,75 @@ +description = "A Result monad for modelling success or failure operations." + +plugins { + `maven-publish` + kotlin("multiplatform") + id("org.jetbrains.kotlin.plugin.allopen") + id("kotlinx.benchmark") +} + +allOpen { + annotation("org.openjdk.jmh.annotations.State") + annotation("org.openjdk.jmh.annotations.BenchmarkMode") +} + +sourceSets.create("benchmark") + +benchmark { + targets { + register("jvmBenchmark") + } +} + +kotlin { + jvm { + withJava() + + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + + sourceSets { + all { + languageSettings.apply { + useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + } + } + + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + val jvmMain by getting { + dependencies { + implementation(kotlin("stdlib-jdk8")) + } + } + + val jvmTest by getting { + dependencies { + implementation(kotlin("test-junit")) + implementation(kotlin("test")) + } + } + + val jvmBenchmark by getting { + dependsOn(jvmMain) + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8") + } + } + } +} + diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/And.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/And.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/And.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/And.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Binding.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Binding.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Binding.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Binding.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Factory.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Factory.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Factory.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Factory.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Get.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Get.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Get.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Get.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Iterable.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Iterable.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Iterable.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Iterable.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Map.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Map.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Map.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Map.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/On.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/On.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/On.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/On.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Or.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Or.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Or.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Or.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Result.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/ResultIterator.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/ResultIterator.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/ResultIterator.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/ResultIterator.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Unwrap.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Unwrap.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Unwrap.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Unwrap.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/Zip.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Zip.kt similarity index 100% rename from src/commonMain/kotlin/com/github/michaelbull/result/Zip.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Zip.kt diff --git a/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt similarity index 71% rename from src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt rename to kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt index 324337d..82e0d53 100644 --- a/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt +++ b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/coroutines/SuspendableBinding.kt @@ -11,6 +11,12 @@ import kotlin.contracts.contract /** * Suspending variant of [binding][com.github.michaelbull.result.binding]. */ +@Deprecated( + message = "Will throw a runtime exception if used with async requests that fail to bind. " + + "See https://github.com/michaelbull/kotlin-result/pull/28 " + + "Please import the kotlin-result-coroutines library to continue using this feature.", + level = DeprecationLevel.WARNING +) suspend inline fun binding(crossinline block: suspend ResultBinding.() -> V): Result { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/AndTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/AndTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/AndTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/AndTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/BindingTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/BindingTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/BindingTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/BindingTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/FactoryTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/FactoryTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/FactoryTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/FactoryTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/GetTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/GetTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/GetTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/GetTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/IterableTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/IterableTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/IterableTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/IterableTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/MapTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/MapTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/MapTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/MapTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/OnTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/OnTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/OnTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/OnTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/OrTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/OrTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/OrTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/OrTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/ResultIteratorTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/ResultIteratorTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/ResultIteratorTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/ResultIteratorTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/UnwrapTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/UnwrapTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/UnwrapTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/UnwrapTest.kt diff --git a/src/commonTest/kotlin/com/github/michaelbull/result/ZipTest.kt b/kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/ZipTest.kt similarity index 100% rename from src/commonTest/kotlin/com/github/michaelbull/result/ZipTest.kt rename to kotlin-result/src/commonTest/kotlin/com/github/michaelbull/result/ZipTest.kt diff --git a/src/jvmBenchmark/kotlin/com/github/michaelbull/result/BindingBenchmark.kt b/kotlin-result/src/jvmBenchmark/kotlin/com/github/michaelbull/result/BindingBenchmark.kt similarity index 100% rename from src/jvmBenchmark/kotlin/com/github/michaelbull/result/BindingBenchmark.kt rename to kotlin-result/src/jvmBenchmark/kotlin/com/github/michaelbull/result/BindingBenchmark.kt diff --git a/src/jvmMain/kotlin/com/github/michaelbull/result/BindException.kt b/kotlin-result/src/jvmMain/kotlin/com/github/michaelbull/result/BindException.kt similarity index 100% rename from src/jvmMain/kotlin/com/github/michaelbull/result/BindException.kt rename to kotlin-result/src/jvmMain/kotlin/com/github/michaelbull/result/BindException.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index a123210..5242700 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,10 +1,14 @@ rootProject.name = "kotlin-result" -include("example") +include( + "example", + "kotlin-result", + "kotlin-result-coroutines" +) pluginManagement { repositories { - maven("https://dl.bintray.com/kotlin/kotlinx" ) + maven("https://dl.bintray.com/kotlin/kotlinx") gradlePluginPortal() } }