feat: Kotlin 2.x/K2, version catalog, serialization & coroutines modules, docs

v3.4 modernization (continued):

- Migrate to Kotlin 2.x (K2); introduce gradle/libs.versions.toml version catalog;
  simplify the JS/Wasm/Node and iOS source-set wiring for the K2 hierarchy template.
- Apply binary-compatibility-validator and Kover plugins.
- New published module tree-structure-serialization: @Serializable TreeNodeDto with
  toDto()/toTreeNode() round-trip (kotlinx.serialization).
- New published module tree-structure-coroutines: asFlow()/pre/post/levelOrderFlow()
  (kotlinx.coroutines Flow traversal).
- Docs: README examples for Sequence/navigation/functional APIs, class-level KDoc
  (thread-safety/complexity), and a CHANGELOG.md.
- Ignore subproject build/ directories.
- Bump version to 3.4.0.

All JVM tests green (core + both modules).
This commit is contained in:
2026-06-06 13:47:20 +02:00
parent c45c5b7afa
commit e1f01c4e2d
14 changed files with 470 additions and 66 deletions

View File

@@ -0,0 +1,88 @@
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.dokka)
alias(libs.plugins.mavenPublish)
signing
}
group = "com.github.adriankuta"
version = rootProject.version
mavenPublishing {
publishToMavenCentral(automaticRelease = false)
signAllPublications()
coordinates("com.github.adriankuta", "tree-structure-serialization", version.toString())
pom {
name.set("Tree Data Structure — kotlinx.serialization")
description.set("kotlinx.serialization support (TreeNodeDto round-trip) for the tree-structure library.")
url.set("https://github.com/AdrianKuta/Tree-Data-Structure")
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
distribution.set("repo")
}
}
developers {
developer {
id.set("AdrianKuta")
name.set("Adrian Kuta")
email.set("adrian.kuta93@gmail.com")
}
}
scm {
url.set("https://github.com/AdrianKuta/Tree-Data-Structure")
connection.set("scm:git:https://github.com/AdrianKuta/Tree-Data-Structure.git")
developerConnection.set("scm:git:ssh://git@github.com/AdrianKuta/Tree-Data-Structure.git")
}
}
}
repositories {
mavenCentral()
}
kotlin {
jvmToolchain(21)
jvm()
js(IR) {
browser()
nodejs()
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
browser()
nodejs()
}
iosX64()
iosArm64()
iosSimulatorArm64()
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
commonMain.dependencies {
api(project(":"))
api(libs.kotlinx.serialization.json)
}
commonTest.dependencies {
implementation(kotlin("test"))
}
}
}

View File

@@ -0,0 +1,30 @@
package com.github.adriankuta.datastructure.tree.serialization
import com.github.adriankuta.datastructure.tree.TreeNode
import kotlinx.serialization.Serializable
/**
* A serializable, acyclic view of a [TreeNode] subtree. [TreeNode] itself holds a back-reference to
* its parent (a cycle), so it cannot be `@Serializable` directly — convert to/from this DTO instead.
*
* ```
* val json = Json.encodeToString(tree.toDto())
* val restored = Json.decodeFromString<TreeNodeDto<String>>(json).toTreeNode()
* ```
*/
@Serializable
public data class TreeNodeDto<T>(
val value: T,
val children: List<TreeNodeDto<T>> = emptyList(),
)
/** Converts this subtree into a serializable [TreeNodeDto], preserving values and shape. */
public fun <T> TreeNode<T>.toDto(): TreeNodeDto<T> =
TreeNodeDto(value, children.map { it.toDto() })
/** Rebuilds a mutable [TreeNode] tree from this DTO. */
public fun <T> TreeNodeDto<T>.toTreeNode(): TreeNode<T> {
val node = TreeNode(value)
children.forEach { node.addChild(it.toTreeNode()) }
return node
}

View File

@@ -0,0 +1,40 @@
package com.github.adriankuta.datastructure.tree.serialization
import com.github.adriankuta.datastructure.tree.structurallyEquals
import com.github.adriankuta.datastructure.tree.tree
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class TreeNodeSerializationTest {
@Test
fun roundTripsThroughJson() {
val original = tree("World") {
child("North America") { child("USA") }
child("Europe") {
child("Poland")
child("Germany")
}
}
val json = Json.encodeToString(original.toDto())
val restored = Json.decodeFromString<TreeNodeDto<String>>(json).toTreeNode()
assertTrue(original.structurallyEquals(restored))
}
@Test
fun dtoMirrorsTreeShape() {
val dto = tree(1) {
child(2)
child(3) { child(4) }
}.toDto()
assertEquals(1, dto.value)
assertEquals(2, dto.children.size)
assertEquals(4, dto.children[1].children[0].value)
}
}