Skip to content

Commit

Permalink
Feature/test (#9)
Browse files Browse the repository at this point in the history
- migrate to dokka 2 for documentation
- multi-module project setup
- introduce `kmmresult-test`, featuring
  - `result should succeed`
  - `result shouldNot succeed`
  - `result shouldSucceedWith expectedValue`
  - `result.shouldSucceed()` returning the contained value
- remove Arrow dependency and import arrow's list of Fatal exceptions directly into our code
- Introduce `Result.nonFatalOrThrow` to mimic KmmResult's non-fatal-only behaviour, but without the object instantiation overhead
- Introduce `carchingUnwrapped`, which mimics KmmResult's non-fatal-only behaviour, but without the object instantiation overhead
  • Loading branch information
JesusMcCloud authored Oct 16, 2024
1 parent 984255b commit b8111e2
Show file tree
Hide file tree
Showing 18 changed files with 568 additions and 193 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/publish-pages-only.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Build Dokka HTML
run: ./gradlew dokkaHtml
run: ./gradlew dokkaGenerate
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload docs folder
path: './docs'
path: './docs/html'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Build Dokka HTML
run: ./gradlew dokkaHtml
run: ./gradlew dokkaGenerate
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload docs folder
path: './docs'
path: './docs/html'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,15 @@
- add `recoverCatching` to match Kotlin's `result`
- add `callsInPlace` contracts
- return result fon `onFailure` and `onSuccess`

## 1.8.0
- migrate to dokka 2 for documentation
- multi-module project setup
- introduce `kmmresult-test`, featuring
- `result should succeed`
- `result shouldNot succeed`
- `result shouldSucceedWith expectedValue`
- `result.shouldSucceed()` returning the contained value
- remove Arrow dependency and import arrow's list of Fatal exceptions directly into our code
- Introduce `Result.nonFatalOrThrow` to mimic KmmResult's non-fatal-only behaviour, but without the object instantiation overhead
- Introduce `carchingUnwrapped`, which mimics KmmResult's non-fatal-only behaviour, but without the object instantiation overhead
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ var intResult = KmmResult.success(3)
intResult = KmmResult.failure (NotImplementedError("Not Implemented"))
```

Also provides `map()` to transform success types while passing through errors and `mapFailure` to transform error types
while passing through success cases.
In addition, the more generic `fold()` is available for conveniently operating on both success and failure branches.


There really is not much more to say, except for two things:
- `KmmResult` sports `unwrap()` to conveniently map it to the `kotlin.Result` equivalent
- It provides a `Result.wrap()` extension function to go the opposite way.
Convenience functions:
- `map()` transforms success types while passing through errors
- `mapFailure` transforms error types while passing through success cases
- the more generic `fold()` is available for conveniently operating on both success and failure branches
- `KmmResult` sports `unwrap()` to conveniently map it to the `kotlin.Result` equivalent
- `Result.wrap()` extension function goes the opposite way
- `mapCatching()` does what you'd expect
- `wrapping()` allows for wrapping the failure branch's exception unless it is of the specified type

Refer to the [full documentation](https://a-sit-plus.github.io/kmmresult/) for more info.

Expand Down Expand Up @@ -83,6 +83,18 @@ func funWithKotlin() -> KmmResult<NSString> {
}
```

## Non-Fatal-Only `catching`
KmmResult comes with `catching`. This is a non-fatal-only-catching version of stdlib's `runCatching`, directly returning a `KmmResult`.
It re-throws any fatal exceptions, such as `OutOfMemoryError`. The underlying logic is borrowed from [Arrow's](https://arrow-kt.io)'s
[`nonFatalOrThrow`](https://apidocs.arrow-kt.io/arrow-core/arrow.core/non-fatal-or-throw.html).

The only downside of `catching` is that it incurs instatiation overhead, because it creates a `KmmResult` instance.
Internally, though, only the behaviour is important, not Swift interop. Hence, you don't care for a `KmmResult` and you
certainly don't care for the cost of instantiating an object. Here, the `Result.nonFatalOrThrow()` extension shipped with KmmResult
comes to the rescue. It does exactly what the name suggest: It re-throws any fatal exception and leaved the `Result` object
untouched otherwise.


Happy folding!

## Contributing
Expand Down
189 changes: 15 additions & 174 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,198 +1,40 @@
import io.gitlab.arturbosch.detekt.Detekt
import org.gradle.kotlin.dsl.support.listFilesOrdered
import org.jetbrains.kotlin.build.joinToReadableString

plugins {
kotlin("multiplatform") version "2.0.0"
id("maven-publish")
id("signing")
plugins {base
id("org.jetbrains.dokka")
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
id("org.jetbrains.dokka") version "1.9.20"
id("org.jetbrains.kotlinx.kover") version "0.8.0"
id("io.gitlab.arturbosch.detekt") version "1.23.6"
}

val artifactVersion: String by extra
group = "at.asitplus"
version = artifactVersion

repositories {
mavenCentral()
dependencies {
dokka(project(":kmmresult"))
dokka(project(":kmmresult-test"))
}

val dokkaOutputDir = "$projectDir/docs"
tasks.dokkaHtml {

dokka {
val moduleDesc = File("$rootDir/dokka-tmp.md").also { it.createNewFile() }
val readme =
File("${rootDir}/README.md").readText()
val moduleTitle = project.name
moduleDesc.writeText("# Module ${project.name}\n\n$readme")
moduleName.set(moduleTitle)

dokkaSourceSets {
named("commonMain") {

includes.from(moduleDesc)
sourceLink {
localDirectory.set(file("src/$name/kotlin"))
remoteUrl.set(
uri("https://github.com/a-sit-plus/kmmresult/tree/development/src/$name/kotlin").toURL()
)
// Suffix which is used to append the line number to the URL. Use #L for GitHub
remoteLineSuffix.set("#L")
}
}
}
outputDirectory.set(file("${rootDir}/docs"))
doLast {
rootDir.listFilesOrdered { it.extension.lowercase() == "png" || it.extension.lowercase() == "svg" }
.forEach { it.copyTo(File("$rootDir/docs/${it.name}"), overwrite = true) }
}
}
val deleteDokkaOutputDir by tasks.register<Delete>("deleteDokkaOutputDirectory") {
delete(dokkaOutputDir)
}
val javadocJar = tasks.register<Jar>("javadocJar") {
dependsOn(deleteDokkaOutputDir, tasks.dokkaHtml)
archiveClassifier.set("javadoc")
from(dokkaOutputDir)
}
moduleDesc.writeText("\n\n$readme")
moduleName.set("KmmResult")

tasks.getByName("check") {
dependsOn("detektMetadataMain")
}


//first sign everything, then publish!
tasks.withType<AbstractPublishToMaven>() {
tasks.withType<Sign>().forEach {
dependsOn(it)
dokkaPublicationDirectory.set(file("${rootDir}/docs"))
dokkaPublications.html {
includes.from(moduleDesc)
}
}

kotlin {

val xcf = org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig(project, "KmmResult")
listOf(
macosArm64(),
macosX64(),
tvosArm64(),
tvosX64(),
tvosSimulatorArm64(),
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "KmmResult"
binaryOption("bundleId", "at.asitplus.KmmResult")
embedBitcode("bitcode")
xcf.add(this)
isStatic = true
}
}

jvmToolchain(11)
jvm {
compilations.all {
kotlinOptions {
freeCompilerArgs = listOf(
"-Xjsr305=strict"
)
}
}
withJava() //for Java Interop tests
}

js(IR) {
browser { testTask { enabled = false } }
nodejs()
}
linuxX64()
linuxArm64()
mingwX64()

sourceSets {
commonMain.dependencies {
implementation("io.arrow-kt:arrow-core:1.2.4")
}

commonTest.dependencies {
implementation(kotlin("test"))
}
}



tasks.withType<Detekt>().configureEach {
reports {
xml.required.set(true)
html.required.set(false)
txt.required.set(false)
sarif.required.set(true)
md.required.set(true)
}
}

dependencies {
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.6")
}
tasks.dokkaGenerate {
doLast {
rootDir.listFilesOrdered { it.extension.lowercase() == "png" || it.extension.lowercase() == "svg" }
.forEach { it.copyTo(File("$rootDir/docs/html/${it.name}"), overwrite = true) }

repositories {
mavenCentral()
}

publishing {
publications {
withType<MavenPublication> {
artifact(javadocJar)
pom {
name.set("KmmResult")
description.set("Functional equivalent of kotlin.Result but with KMM goodness")
url.set("https://github.com/a-sit-plus/kmmresult")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("JesusMcCloud")
name.set("Bernd Prünster")
email.set("[email protected]")
}
developer {
id.set("nodh")
name.set("Christian Kollmann")
email.set("[email protected]")
}
}
scm {
connection.set("scm:git:[email protected]:a-sit-plus/kmmresult.git")
developerConnection.set("scm:git:[email protected]:a-sit-plus/kmmresult.git")
url.set("https://github.com/a-sit-plus/kmmresult")
}
}
}
}
repositories {
mavenLocal() {
signing.isRequired = false
}
}
}
}

signing {
val signingKeyId: String? by project
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}

nexusPublishing {
repositories {
sonatype {
Expand All @@ -201,4 +43,3 @@ nexusPublishing {
}
}
}

13 changes: 13 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
`kotlin-dsl`
}

repositories {
mavenCentral()
gradlePluginPortal()
}

dependencies {
implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.0.0-Beta")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
}
1 change: 1 addition & 0 deletions buildSrc/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'kmmResult_buildSrc'
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ kotlin.mpp.enableCInteropCommonization=true
kotlin.mpp.stability.nowarn=true
kotlin.native.ignoreDisabledTargets=true

artifactVersion = 1.7.0
artifactVersion = 1.8.0
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
Loading

0 comments on commit b8111e2

Please sign in to comment.