From 83d8a0cf65731463e780c0df6128a7fd475ef40b Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:44:21 +0200 Subject: [PATCH 01/11] Add native targets to KMP modules - Migrate test-kit to use kotlinx-resources --- build.gradle.kts | 7 ++- buildSrc/build.gradle.kts | 1 + .../kord-multiplatform-module.gradle.kts | 1 + .../main/kotlin/kord-native-module.gradle.kts | 29 +++++++++++ common/build.gradle.kts | 26 ++++++++++ common/src/appleMain/kotlin/HttpEngine.kt | 9 ++++ common/src/linuxMain/kotlin/HttpEngine.kt | 9 ++++ common/src/mingwMain/kotlin/HttpEngine.kt | 9 ++++ core/build.gradle.kts | 1 + core/src/nativeMain/kotlin/KordBuilder.kt | 3 ++ gateway/build.gradle.kts | 1 + .../src/nativeMain/kotlin/DefaultGateway.kt | 9 ++++ gateway/src/nativeMain/kotlin/Inflater.kt | 52 +++++++++++++++++++ gradle.properties | 4 ++ gradle/libs.versions.toml | 14 +++-- ksp-annotations/build.gradle.kts | 1 + rest/build.gradle.kts | 1 + .../nativeMain/kotlin/RecoveredStackTrace.kt | 4 ++ .../dev/kord/rest/request/StackTrace.kt | 23 ++++++++ test-kit/build.gradle.kts | 1 + test-kit/src/commonMain/kotlin/Annotations.kt | 5 ++ test-kit/src/commonMain/kotlin/Platform.kt | 11 +++- test-kit/src/jsMain/kotlin/Platform.kt | 14 ++--- test-kit/src/jsMain/kotlin/Platform.node.kt | 19 ------- .../src/nativeMain/kotlin/IgnoreOnNative.kt | 5 ++ test-kit/src/nativeMain/kotlin/Platform.kt | 23 ++++++++ 26 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 buildSrc/src/main/kotlin/kord-native-module.gradle.kts create mode 100644 common/src/appleMain/kotlin/HttpEngine.kt create mode 100644 common/src/linuxMain/kotlin/HttpEngine.kt create mode 100644 common/src/mingwMain/kotlin/HttpEngine.kt create mode 100644 core/src/nativeMain/kotlin/KordBuilder.kt create mode 100644 gateway/src/nativeMain/kotlin/DefaultGateway.kt create mode 100644 gateway/src/nativeMain/kotlin/Inflater.kt create mode 100644 rest/src/nativeMain/kotlin/RecoveredStackTrace.kt create mode 100644 rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt delete mode 100644 test-kit/src/jsMain/kotlin/Platform.node.kt create mode 100644 test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt create mode 100644 test-kit/src/nativeMain/kotlin/Platform.kt diff --git a/build.gradle.kts b/build.gradle.kts index 0ad64bff26f..be333e43178 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,11 @@ plugins { org.jetbrains.dokka // for dokkaHtmlMultiModule task } -repositories { - mavenCentral() +allprojects { + repositories { + mavenCentral() + maven("https://oss.sonatype.org/content/repositories/snapshots/") + } } group = Library.group diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 71fc53572c3..686332581da 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } repositories { + gradlePluginPortal() mavenCentral() } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index ea4cbbf586f..5e485c6ffa6 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -8,6 +8,7 @@ plugins { `kotlinx-atomicfu` org.jetbrains.kotlinx.`binary-compatibility-validator` com.google.devtools.ksp + com.goncalossilva.resources } repositories { diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts new file mode 100644 index 00000000000..3aabb90a53d --- /dev/null +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -0,0 +1,29 @@ +plugins { + org.jetbrains.kotlin.multiplatform +} + +kotlin { + targetHierarchy.default() + + linuxX64() + // Waiting for Ktor + // https://youtrack.jetbrains.com/issue/KTOR-872 + //linuxArm64() + + mingwX64() + + macosArm64() + macosX64() + + iosArm64() + iosX64() +// iosSimulatorArm64() + + watchosX64() + watchosArm64() +// watchosSimulatorArm64() + + tvosX64() + tvosArm64() +// tvosSimulatorArm64() +} diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1d592ab41f0..4e526ffd18f 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` alias(libs.plugins.buildconfig) } @@ -39,6 +40,31 @@ kotlin { implementation(projects.kspAnnotations) } } + + nativeMain { + dependencies { + // Native does not have compileOnly + implementation(projects.kspAnnotations) + } + } + + mingwMain { + dependencies { + api(libs.ktor.client.winhttp) + } + } + + appleMain { + dependencies { + api(libs.ktor.client.darwin) + } + } + + linuxMain { + dependencies { + api(libs.ktor.client.curl) + } + } } } diff --git a/common/src/appleMain/kotlin/HttpEngine.kt b/common/src/appleMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..d43679d2357 --- /dev/null +++ b/common/src/appleMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.darwin.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine: HttpClientEngineFactory by Darwin diff --git a/common/src/linuxMain/kotlin/HttpEngine.kt b/common/src/linuxMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..f38a8a9aba8 --- /dev/null +++ b/common/src/linuxMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.curl.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine : HttpClientEngineFactory by Curl diff --git a/common/src/mingwMain/kotlin/HttpEngine.kt b/common/src/mingwMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..eb8489d3bed --- /dev/null +++ b/common/src/mingwMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.winhttp.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine : HttpClientEngineFactory by WinHttp diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ac5deb38510..9cc3aed84c0 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/core/src/nativeMain/kotlin/KordBuilder.kt b/core/src/nativeMain/kotlin/KordBuilder.kt new file mode 100644 index 00000000000..a3d196befb4 --- /dev/null +++ b/core/src/nativeMain/kotlin/KordBuilder.kt @@ -0,0 +1,3 @@ +package dev.kord.core.builder.kord + +public actual class KordBuilder actual constructor(token: String) : BaseKordBuilder(token) diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 28e43c7aeb2..1ee7cf9fedc 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/gateway/src/nativeMain/kotlin/DefaultGateway.kt b/gateway/src/nativeMain/kotlin/DefaultGateway.kt new file mode 100644 index 00000000000..9a563091de9 --- /dev/null +++ b/gateway/src/nativeMain/kotlin/DefaultGateway.kt @@ -0,0 +1,9 @@ +package dev.kord.gateway + +import kotlin.experimental.ExperimentalNativeApi + +// TODO: Timeout +internal actual fun Throwable.isTimeout() = false + +@OptIn(ExperimentalNativeApi::class) +internal actual val os: String get() = Platform.osFamily.name diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt new file mode 100644 index 00000000000..4fbca05c13c --- /dev/null +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -0,0 +1,52 @@ +package dev.kord.gateway + +import io.ktor.utils.io.core.* +import io.ktor.websocket.* +import kotlinx.cinterop.* +import platform.zlib.* + +private const val MAX_WBITS = 15 // Maximum window size in bits +private const val CHUNK_SIZE = 256 * 1000 + +@OptIn(ExperimentalForeignApi::class) +internal actual class Inflater : Closeable { + private val zStream = nativeHeap.alloc().apply { + val initResponse = inflateInit2(ptr, MAX_WBITS) + if (initResponse != Z_OK) { + nativeHeap.free(this) + throw IllegalStateException("Could not initialize zlib: $initResponse") + } + } + + actual fun Frame.inflateData(): String { + val compressedData = data + var out = ByteArray(0) + memScoped { + val uncompressedDataSize = CHUNK_SIZE // allocate enough space for the uncompressed data + val uncompressedData = allocArray(uncompressedDataSize) + zStream.apply { + next_in = compressedData.refTo(0).getPointer(memScope).reinterpret() + avail_in = compressedData.size.convert() + } + + do { + zStream.apply { + next_out = uncompressedData + avail_out = uncompressedDataSize.convert() + } + val resultCode = inflate(zStream.ptr, Z_NO_FLUSH) + if (resultCode != Z_OK && resultCode != Z_STREAM_END) { + throw IllegalStateException("An error occurred during decompression of frame: $resultCode") + } + out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.toInt()) + } while (zStream.avail_out == 0u) + } + + return out.decodeToString() + } + + override fun close() { + inflateEnd(zStream.ptr) + nativeHeap.free(zStream) + } +} diff --git a/gradle.properties b/gradle.properties index 09f960ded7b..b2378e076cf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,3 +10,7 @@ kotlin.code.style=official # https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin kotlinx.atomicfu.enableJvmIrTransformation=true kotlinx.atomicfu.enableJsIrTransformation=true + +# We are aware of these issues and their symptoms don't affect us +kotlin.native.ignoreIncorrectDependencies=true +kotlin.native.ignoreDisabledTargets=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8c9e24129c1..9cc6d600ad2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,8 @@ kotlinx-coroutines = "1.7.2" # https://github.com/Kotlin/kotlinx.coroutines kotlinx-serialization = "1.5.1" # https://github.com/Kotlin/kotlinx.serialization kotlinx-datetime = "0.4.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "3.0.5" # https://github.com/oshai/kotlin-logging -kord-cache = "0.4.0" # https://github.com/kordlib/cache +# This is the specific release supporting native, until we setup CI +kord-cache = "0.5.x-20230411.160140-1" # https://github.com/kordlib/cache # implementation dependencies kotlin-node = "18.16.12-pre.591-compat" # https://github.com/JetBrains/kotlin-wrappers @@ -29,7 +30,7 @@ dokka = "1.8.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.21.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.13.2" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "4.1.2" # https://github.com/gmazzo/gradle-buildconfig-plugin - +kotlinx-resources = "0.4.0" # https://github.com/goncalossilva/kotlinx-resources [libraries] @@ -42,6 +43,9 @@ ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negoti ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } +ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" } +ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } +ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" } ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } ktor-client-websockets = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" } ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" } @@ -75,6 +79,7 @@ kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", versi junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } +kotlinx-resources = { module = "com.goncalossilva:resources", version.ref = "kotlinx-resources" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: # https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins @@ -84,13 +89,13 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } - +kordx-resources-plugin = { module = "com.goncalossilva:resources-plugin", version.ref = "kotlinx-resources" } [bundles] ktor-client-serialization = ["ktor-client-content-negotiation", "ktor-serialization-kotlinx-json"] -test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test"] +test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test", "kotlinx-resources"] test-js = ["kotlin-test-js", "kotlin-node"] test-jvm = ["kotlin-test-junit5", "junit-jupiter-engine", "slf4j-simple"] @@ -101,6 +106,7 @@ pluginsForBuildSrc = [ "atomicfu-plugin", "binary-compatibility-validator-plugin", "ksp-plugin", + "kordx-resources-plugin" ] diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index 0c68a988730..e4fe6b72e20 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { `kord-internal-multiplatform-module` + `kord-native-module` // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index 21202494c78..46d91151df9 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt b/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt new file mode 100644 index 00000000000..091fca9aadd --- /dev/null +++ b/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt @@ -0,0 +1,4 @@ +package dev.kord.rest.request + +// You cannot really modify stack traces in Native :( +internal actual fun RecoveredStackTrace.sanitizeStackTrace() = Unit diff --git a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt new file mode 100644 index 00000000000..41e0a08d13a --- /dev/null +++ b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt @@ -0,0 +1,23 @@ +package dev.kord.rest.request + +import kotlin.test.assertEquals + +actual typealias StackTraceElement = String + +//kotlin.Exception +//at 0 ??? 7ff68473da75 kfun:kotlin.Throwable#(kotlin.String?){} + 117 +//at 1 ??? 7ff684f9ee89 kfun:dev.kord.rest.request.RecoveredStackTrace#(){} + 89 +//at 2 ??? 7ff684f9e939 kfun:dev.kord.rest.request.StackTraceRecoveringKtorRequestHandler.$handleCOROUTINE$23#invokeSuspend(kotlin.Result){}kotlin.Any? + 681 +//at 3 ??? 7ff684f9ed3c kfun:dev.kord.rest.request.StackTraceRecoveringKtorRequestHandler#handle(dev.kord.rest.request.Request<0:0,0:1>){0§;1§}0:1 + 300 +//at 4 ??? 7ff684fbd4c4 kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace recovery$lambda$1COROUTINE$15.invokeSuspend#internal + 2740 +//-->at 5 ??? 7ff684fbdeca kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace<-- +actual fun currentThreadStackTrace(): StackTraceElement = + Exception().stackTraceToString().lineSequence().filterNot(String::isBlank).drop(5).first().trim() + .substringAfter("???") + +internal actual fun RecoveredStackTrace.validate(expected: StackTraceElement) { + // The first few lines are artifacts from coroutines which are not present in expected + val actual = stackTraceToString().lineSequence().drop(6).first().trim() + .substringAfter("???") // index is off at call site + assertEquals(expected, actual) +} diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 93ad034df43..511f9f57ed9 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-internal-multiplatform-module` + `kord-native-module` } kotlin { diff --git a/test-kit/src/commonMain/kotlin/Annotations.kt b/test-kit/src/commonMain/kotlin/Annotations.kt index bcc93e2653d..a2b8b3ae23d 100644 --- a/test-kit/src/commonMain/kotlin/Annotations.kt +++ b/test-kit/src/commonMain/kotlin/Annotations.kt @@ -14,3 +14,8 @@ expect annotation class IgnoreOnJs() @Target(CLASS, FUNCTION) @OptionalExpectation expect annotation class IgnoreOnJvm() + +/** Ignores this test on Native platforms. */ +@Target(CLASS, FUNCTION) +@OptionalExpectation +expect annotation class IgnoreOnNative() diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index fe9f5179e53..b3ea79f20fa 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -1,12 +1,19 @@ package dev.kord.test import io.ktor.utils.io.* +import com.goncalossilva.resources.Resource expect object Platform { val IS_JVM: Boolean val IS_NODE: Boolean + val IS_BROWSER: Boolean + val IS_MINGW: Boolean + val IS_LINUX: Boolean + val IS_DARWIN: Boolean } expect fun getEnv(name: String): String? -expect suspend fun file(project: String, path: String): String -expect suspend fun readFile(project: String, path: String): ByteReadChannel +fun file(path: String): String = resource(path).readText() +fun readFile(path: String): ByteReadChannel = ByteReadChannel(resource(path).readBytes()) + +private fun resource(path: String) = Resource("src/commonTest/resources/$path") diff --git a/test-kit/src/jsMain/kotlin/Platform.kt b/test-kit/src/jsMain/kotlin/Platform.kt index bf7bcae63bb..f646655df04 100644 --- a/test-kit/src/jsMain/kotlin/Platform.kt +++ b/test-kit/src/jsMain/kotlin/Platform.kt @@ -1,6 +1,5 @@ package dev.kord.test -import io.ktor.utils.io.* import node.process.process actual object Platform { @@ -9,12 +8,13 @@ actual object Platform { get() = js( "typeof process !== 'undefined' && process.versions != null && process.versions.node != null" ) as Boolean + actual val IS_BROWSER: Boolean + get() = js( + "typeof window !== 'undefined' && typeof window.document !== 'undefined' || typeof self !== 'undefined' && typeof self.location !== 'undefined'" + ) as Boolean + actual const val IS_MINGW: Boolean = false + actual const val IS_LINUX: Boolean = false + actual const val IS_DARWIN: Boolean = false } actual fun getEnv(name: String) = process.env[name] - -actual suspend fun file(project: String, path: String): String = - if (Platform.IS_NODE) nodeFile(project, path) else TODO("Browser JS is not supported yet") - -actual suspend fun readFile(project: String, path: String): ByteReadChannel = - if (Platform.IS_NODE) nodeReadFile(project, path) else TODO("Browser JS is not supported yet") diff --git a/test-kit/src/jsMain/kotlin/Platform.node.kt b/test-kit/src/jsMain/kotlin/Platform.node.kt deleted file mode 100644 index 2949105f551..00000000000 --- a/test-kit/src/jsMain/kotlin/Platform.node.kt +++ /dev/null @@ -1,19 +0,0 @@ -package dev.kord.test - -import io.ktor.utils.io.* -import js.core.toList -import node.buffer.Buffer -import node.buffer.BufferEncoding -import node.process.process - -internal suspend fun nodeFile(project: String, path: String): String = - node.fs.readFile("${process.env["PROJECT_ROOT"]}/$project/src/commonTest/resources/$path") - .toString(BufferEncoding.utf8) - -internal suspend fun nodeReadFile(project: String, path: String): ByteReadChannel { - val buffer = node.fs.readFile("${process.env["PROJECT_ROOT"]}/$project/src/commonTest/resources/$path") - - return ByteReadChannel(buffer.toByteArray()) -} - -private fun Buffer.toByteArray() = values().toList().toByteArray() diff --git a/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt b/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt new file mode 100644 index 00000000000..db53b213dce --- /dev/null +++ b/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt @@ -0,0 +1,5 @@ +package dev.kord.test + +import kotlin.test.Ignore + +actual typealias IgnoreOnNative = Ignore diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt new file mode 100644 index 00000000000..979518d356e --- /dev/null +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -0,0 +1,23 @@ +@file:OptIn(ExperimentalNativeApi::class) + +package dev.kord.test + +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.toKString +import platform.posix.getenv +import kotlin.experimental.ExperimentalNativeApi +import kotlin.native.Platform + +private val darwinFamilies = listOf(OsFamily.WATCHOS, OsFamily.TVOS, OsFamily.MACOSX) + +actual object Platform { + actual val IS_JVM: Boolean = false + actual val IS_NODE: Boolean = false + actual val IS_BROWSER: Boolean = false + actual val IS_MINGW: Boolean = Platform.osFamily == OsFamily.WINDOWS + actual val IS_LINUX: Boolean = Platform.osFamily == OsFamily.LINUX + actual val IS_DARWIN: Boolean = Platform.osFamily in darwinFamilies +} + +@OptIn(ExperimentalForeignApi::class) +actual fun getEnv(name: String) = getenv(name)?.toKString() From bcae6db4b796fa41617b8316c63b86a6f7e6ecaa Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:48:47 +0200 Subject: [PATCH 02/11] Disable CI for now --- .github/workflows/deployment-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deployment-ci.yml b/.github/workflows/deployment-ci.yml index 20f02ea035d..76726467f9a 100644 --- a/.github/workflows/deployment-ci.yml +++ b/.github/workflows/deployment-ci.yml @@ -8,6 +8,9 @@ on: - '**' # We want to run this on all branch pushes tags-ignore: - '**' # We don't want this to run on tags pushes + branches-ignore: + # CI is not setup for Native + - 'feature/native' pull_request: release: types: [ published ] From 3e81dc579500cea86b16b076d5e76c9e3d83dd63 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:49:11 +0200 Subject: [PATCH 03/11] Use hierarchies for all KMP targets --- .../kord-multiplatform-module.gradle.kts | 22 +++++++++---------- .../main/kotlin/kord-native-module.gradle.kts | 2 -- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 5e485c6ffa6..a90092d0d20 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,4 +1,5 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest plugins { @@ -23,7 +24,17 @@ apiValidation { applyKordBCVOptions() } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + targetHierarchy.default { + common { + group("nonJvm") { + withNative() + withJs() + } + } + } + explicitApi() jvm() @@ -51,17 +62,6 @@ kotlin { implementation(project(":test-kit")) } } - val nonJvmMain by creating { - dependsOn(commonMain.get()) - } - targets - .map { it.name } - .filter { it != "jvm" && it != "metadata" } - .forEach { target -> - sourceSets.getByName("${target}Main") { - dependsOn(nonJvmMain) - } - } } } diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 3aabb90a53d..1198e9e6bbe 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -3,8 +3,6 @@ plugins { } kotlin { - targetHierarchy.default() - linuxX64() // Waiting for Ktor // https://youtrack.jetbrains.com/issue/KTOR-872 From 3ecaf4edec865bc1cd6b7aa64d2f49f8042edf6b Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:49:31 +0200 Subject: [PATCH 04/11] Add missing generated files --- ...icationRoleConnectionMetadataRecordType.kt | 137 ++++++++++++++++++ .../entity/DiscordRoleConnectionMetadata.kt | 75 ++++++++++ .../ApplicationRoleConnectionMetadataData.kt | 39 +++++ .../RoleConnectionMetadataRecord.kt | 26 ++++ 4 files changed, 277 insertions(+) create mode 100644 common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt create mode 100644 common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt create mode 100644 core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt create mode 100644 core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt new file mode 100644 index 00000000000..a758497efeb --- /dev/null +++ b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt @@ -0,0 +1,137 @@ +// THIS FILE IS AUTO-GENERATED BY KordEnumProcessor.kt, DO NOT EDIT! +@file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting", + "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection")) + +package dev.kord.common.entity + +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.LazyThreadSafetyMode.PUBLICATION +import kotlin.String +import kotlin.Suppress +import kotlin.collections.List +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * Type of [DiscordRoleConnectionMetadata] values + * + * See [DiscordApplicationRoleConnectionMetadataRecordType]s in the + * [Discord Developer Documentation](https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type). + */ +@Serializable(with = DiscordApplicationRoleConnectionMetadataRecordType.Serializer::class) +public sealed class DiscordApplicationRoleConnectionMetadataRecordType( + /** + * The raw value used by Discord. + */ + public val `value`: Int, +) { + public final override fun equals(other: Any?): Boolean = this === other || + (other is DiscordApplicationRoleConnectionMetadataRecordType && this.value == other.value) + + public final override fun hashCode(): Int = value.hashCode() + + public final override fun toString(): String = + "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}(value=$value)" + + /** + * An unknown [DiscordApplicationRoleConnectionMetadataRecordType]. + * + * This is used as a fallback for [DiscordApplicationRoleConnectionMetadataRecordType]s that + * haven't been added to Kord yet. + */ + public class Unknown( + `value`: Int, + ) : DiscordApplicationRoleConnectionMetadataRecordType(value) + + /** + * The metadata value (integer) is less than or equal to the guild's configured value (integer) + */ + public object IntegerLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(1) + + /** + * The metadata value (integer) is greater than or equal to the guild's configured value + * (integer) + */ + public object IntegerGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(2) + + /** + * The metadata value (integer) is equal to the guild's configured value (integer) + */ + public object IntegerEqual : DiscordApplicationRoleConnectionMetadataRecordType(3) + + /** + * The metadata value (integer) is not equal to the guild's configured value (integer) + */ + public object IntegerNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(4) + + /** + * The metadata value (ISO8601 string) is less than or equal to the guild's configured value + * (integer; days before current date) + */ + public object DateTimeLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(5) + + /** + * The metadata value (ISO8601 string) is greater than or equal to the guild's configured value + * (integer; days before current date) + */ + public object DateTimeGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(6) + + /** + * The metadata value (integer) is equal to the guild's configured value (integer; 1) + */ + public object BooleanEqual : DiscordApplicationRoleConnectionMetadataRecordType(7) + + /** + * The metadata value (integer) is not equal to the guild's configured value (integer; 1) + */ + public object BooleanNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(8) + + internal object Serializer : KSerializer { + public override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType", + PrimitiveKind.INT) + + public override fun serialize(encoder: Encoder, + `value`: DiscordApplicationRoleConnectionMetadataRecordType) = + encoder.encodeInt(value.value) + + public override fun deserialize(decoder: Decoder) = when (val value = decoder.decodeInt()) { + 1 -> IntegerLessThanOrEqual + 2 -> IntegerGreaterThanOrEqual + 3 -> IntegerEqual + 4 -> IntegerNotEqual + 5 -> DateTimeLessThanOrEqual + 6 -> DateTimeGreaterThanOrEqual + 7 -> BooleanEqual + 8 -> BooleanNotEqual + else -> Unknown(value) + } + } + + public companion object { + /** + * A [List] of all known [DiscordApplicationRoleConnectionMetadataRecordType]s. + */ + public val entries: List by + lazy(mode = PUBLICATION) { + listOf( + IntegerLessThanOrEqual, + IntegerGreaterThanOrEqual, + IntegerEqual, + IntegerNotEqual, + DateTimeLessThanOrEqual, + DateTimeGreaterThanOrEqual, + BooleanEqual, + BooleanNotEqual, + ) + } + + } +} diff --git a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt new file mode 100644 index 00000000000..c1150a053e7 --- /dev/null +++ b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt @@ -0,0 +1,75 @@ +@file:GenerateKordEnum( + name = "DiscordApplicationRoleConnectionMetadataRecordType", + valueType = GenerateKordEnum.ValueType.INT, + docUrl = "https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type", + kDoc = "Type of [DiscordRoleConnectionMetadata] values", + entries = [ + GenerateKordEnum.Entry( + name = "IntegerLessThanOrEqual", + intValue = 1, + kDoc = "The metadata value (integer) is less than or equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerGreaterThanOrEqual", + intValue = 2, + kDoc = "The metadata value (integer) is greater than or equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerEqual", + intValue = 3, + kDoc = "The metadata value (integer) is equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerNotEqual", + intValue = 4, + kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "DateTimeLessThanOrEqual", + intValue = 5, + kDoc = "The metadata value (ISO8601 string) is less than or equal to the guild's configured value (integer; days before current date)" + ), + GenerateKordEnum.Entry( + name = "DateTimeGreaterThanOrEqual", + intValue = 6, + kDoc = "The metadata value (ISO8601 string) is greater than or equal to the guild's configured value (integer; days before current date)" + ), + GenerateKordEnum.Entry( + name = "BooleanEqual", + intValue = 7, + kDoc = "The metadata value (integer) is equal to the guild's configured value (integer; 1)" + ), + GenerateKordEnum.Entry( + name = "BooleanNotEqual", + intValue = 8, + kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer; 1)" + ) + ] +) + +package dev.kord.common.entity + +import dev.kord.common.Locale +import dev.kord.common.entity.optional.Optional +import dev.kord.ksp.GenerateKordEnum +import kotlinx.serialization.Serializable + +/** + * A representation of role connection metadata for an [application][DiscordApplication]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ +@Serializable +public data class DiscordApplicationRoleConnectionMetadataRecord( + val type: DiscordApplicationRoleConnectionMetadataRecordType, + val key: String, + val name: String, + val nameLocalizations: Optional> = Optional.Missing(), + val description: String, + val descriptionLocalizations: Optional> = Optional.Missing() +) diff --git a/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt b/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt new file mode 100644 index 00000000000..fd3faf8a2c5 --- /dev/null +++ b/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt @@ -0,0 +1,39 @@ +package dev.kord.core.cache.data + +import dev.kord.common.Locale +import dev.kord.common.entity.DiscordApplication +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecord +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType +import dev.kord.common.entity.optional.Optional + +/** + * A representation of role connection metadata for an [application][DiscordApplication]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ + +public data class ApplicationRoleConnectionMetadataData( + val type: DiscordApplicationRoleConnectionMetadataRecordType, + val key: String, + val name: String, + val nameLocalizations: Optional> = Optional.Missing(), + val description: String, + val descriptionLocalizations: Optional> = Optional.Missing() +) { + public companion object { + public fun from(record: DiscordApplicationRoleConnectionMetadataRecord): ApplicationRoleConnectionMetadataData = + ApplicationRoleConnectionMetadataData( + record.type, + record.key, + record.name, + record.nameLocalizations, + record.description, + record.descriptionLocalizations + ) + } +} diff --git a/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt b/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt new file mode 100644 index 00000000000..d3d9c77d673 --- /dev/null +++ b/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt @@ -0,0 +1,26 @@ +package dev.kord.core.entity.application + +import dev.kord.common.Locale +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType +import dev.kord.core.cache.data.ApplicationRoleConnectionMetadataData + +/** + * A representation of role connection metadata for an [application][Application]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ +public class RoleConnectionMetadataRecord(public val data: ApplicationRoleConnectionMetadataData) { + public val type: DiscordApplicationRoleConnectionMetadataRecordType get() = data.type + public val key: String get() = data.key + public val name: String get() = data.name + public val nameLocalizations: Map + get() = data.nameLocalizations.value ?: emptyMap() + public val description: String get() = data.description + public val descriptionLocalizations: Map + get() = data.nameLocalizations.value ?: emptyMap() +} From 11ee8d7b3b67e17d549f97c8855f11eb567cabff Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 21:20:34 +0200 Subject: [PATCH 05/11] Add missing generated types --- common/api/common.api | 90 +++++++++++++++++++ ...icationRoleConnectionMetadataRecordType.kt | 27 +++--- core/api/core.api | 38 ++++++++ 3 files changed, 140 insertions(+), 15 deletions(-) diff --git a/common/api/common.api b/common/api/common.api index 98c6e53cc2d..2a8c470f335 100644 --- a/common/api/common.api +++ b/common/api/common.api @@ -2435,6 +2435,96 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord { + public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion; + public synthetic fun (ILdev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V + public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Ldev/kord/common/entity/optional/Optional; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ldev/kord/common/entity/optional/Optional; + public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public static synthetic fun copy$default (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public fun equals (Ljava/lang/Object;)Z + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final synthetic fun write$Self (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public abstract class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion; + public synthetic fun (ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun equals (Ljava/lang/Object;)Z + public final fun getValue ()I + public final fun hashCode ()I + public final fun toString ()Ljava/lang/String; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion { + public final fun getEntries ()Ljava/util/List; + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Unknown : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public fun (I)V +} + public final class dev/kord/common/entity/DiscordAttachment { public static final field Companion Ldev/kord/common/entity/DiscordAttachment$Companion; public synthetic fun (ILdev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt index a758497efeb..df3e645a038 100644 --- a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt +++ b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt @@ -1,16 +1,10 @@ -// THIS FILE IS AUTO-GENERATED BY KordEnumProcessor.kt, DO NOT EDIT! +// THIS FILE IS AUTO-GENERATED, DO NOT EDIT! @file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting", "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection")) package dev.kord.common.entity -import kotlin.Any -import kotlin.Boolean -import kotlin.Int import kotlin.LazyThreadSafetyMode.PUBLICATION -import kotlin.String -import kotlin.Suppress -import kotlin.collections.List import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind @@ -32,12 +26,12 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( */ public val `value`: Int, ) { - public final override fun equals(other: Any?): Boolean = this === other || + final override fun equals(other: Any?): Boolean = this === other || (other is DiscordApplicationRoleConnectionMetadataRecordType && this.value == other.value) - public final override fun hashCode(): Int = value.hashCode() + final override fun hashCode(): Int = value.hashCode() - public final override fun toString(): String = + final override fun toString(): String = "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}(value=$value)" /** @@ -94,15 +88,18 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( public object BooleanNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(8) internal object Serializer : KSerializer { - public override val descriptor: SerialDescriptor = + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType", PrimitiveKind.INT) - public override fun serialize(encoder: Encoder, - `value`: DiscordApplicationRoleConnectionMetadataRecordType) = - encoder.encodeInt(value.value) + override fun serialize(encoder: Encoder, + `value`: DiscordApplicationRoleConnectionMetadataRecordType) { + encoder.encodeInt(value.value) + } - public override fun deserialize(decoder: Decoder) = when (val value = decoder.decodeInt()) { + override fun deserialize(decoder: Decoder): + DiscordApplicationRoleConnectionMetadataRecordType = + when (val value = decoder.decodeInt()) { 1 -> IntegerLessThanOrEqual 2 -> IntegerGreaterThanOrEqual 3 -> IntegerEqual diff --git a/core/api/core.api b/core/api/core.api index 983cc33c83a..7da9480d095 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -2639,6 +2639,33 @@ public final class dev/kord/core/cache/data/ApplicationInteractionData$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData { + public static final field Companion Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion; + public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V + public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Ldev/kord/common/entity/optional/Optional; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ldev/kord/common/entity/optional/Optional; + public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public static synthetic fun copy$default (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public fun equals (Ljava/lang/Object;)Z + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion { + public final fun from (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; +} + public final class dev/kord/core/cache/data/AttachmentData { public static final field Companion Ldev/kord/core/cache/data/AttachmentData$Companion; public synthetic fun (ILdev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V @@ -7623,6 +7650,17 @@ public final class dev/kord/core/entity/application/MessageCommand$DefaultImpls public static fun isNsfw (Ldev/kord/core/entity/application/MessageCommand;)Z } +public final class dev/kord/core/entity/application/RoleConnectionMetadataRecord { + public fun (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;)V + public final fun getData ()Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ljava/util/Map; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ljava/util/Map; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; +} + public final class dev/kord/core/entity/application/UnknownGlobalApplicationCommand : dev/kord/core/entity/application/GlobalApplicationCommand { public fun (Ldev/kord/core/cache/data/ApplicationCommandData;Ldev/kord/rest/service/InteractionService;)V public fun compareTo (Ldev/kord/core/entity/Entity;)I From c7f633033a7ee71019a01d6b435cb5b1896fbf60 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 21:44:12 +0200 Subject: [PATCH 06/11] Fix tests - revert back to own test file handler - update yarn lock - Fix task dependencies --- ...d-internal-multiplatform-module.gradle.kts | 4 +++ .../kord-multiplatform-module.gradle.kts | 13 ++++++++-- .../main/kotlin/kord-native-module.gradle.kts | 13 +++++++--- common/build.gradle.kts | 4 +-- core/build.gradle.kts | 2 +- gateway/build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 ++ kotlin-js-store/yarn.lock | 18 +++++++++++++ ksp-annotations/build.gradle.kts | 2 +- rest/build.gradle.kts | 2 +- test-kit/build.gradle.kts | 7 ++++- test-kit/src/commonMain/kotlin/Platform.kt | 6 ++--- test-kit/src/jsMain/kotlin/Platform.kt | 7 +++++ test-kit/src/jsMain/kotlin/Platform.node.kt | 19 ++++++++++++++ test-kit/src/jvmMain/kotlin/Platform.kt | 4 +++ test-kit/src/nativeMain/kotlin/Platform.kt | 26 +++++++++++++++++++ 16 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 test-kit/src/jsMain/kotlin/Platform.node.kt diff --git a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts index 53be1985486..367146b1074 100644 --- a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi + plugins { org.jetbrains.kotlin.multiplatform } @@ -6,7 +8,9 @@ repositories { mavenCentral() } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + targetHierarchy.default() jvm() js(IR) { nodejs() diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index a90092d0d20..c29c0849e2a 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,5 +1,7 @@ +import org.gradle.configurationcache.extensions.capitalized import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest plugins { @@ -9,7 +11,6 @@ plugins { `kotlinx-atomicfu` org.jetbrains.kotlinx.`binary-compatibility-validator` com.google.devtools.ksp - com.goncalossilva.resources } repositories { @@ -76,7 +77,15 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } - for (task in listOf("compileKotlinJvm", "compileKotlinJs", "jvmSourcesJar", "jsSourcesJar")) { + val compilationTasks = kotlin.targets.flatMap { + buildList { + add("compileKotlin${it.name.capitalized()}") + if (it !is KotlinNativeTarget) { + add("${it.name}SourcesJar") + } + } + } + for (task in compilationTasks) { named(task) { dependsOn("kspCommonMainKotlinMetadata") } diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 1198e9e6bbe..548c59f8950 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -1,12 +1,17 @@ +import org.apache.tools.ant.taskdefs.condition.Os + plugins { org.jetbrains.kotlin.multiplatform } kotlin { - linuxX64() - // Waiting for Ktor - // https://youtrack.jetbrains.com/issue/KTOR-872 - //linuxArm64() + if(!Os.isFamily(Os.FAMILY_WINDOWS)) { + linuxX64() + // Waiting for Ktor + // https://youtrack.jetbrains.com/issue/KTOR-872 + //linuxArm64() + } + mingwX64() diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 4e526ffd18f..d98e91a26b4 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` alias(libs.plugins.buildconfig) } @@ -60,7 +60,7 @@ kotlin { } } - linuxMain { + findByName("linuxMain")?.apply { dependencies { api(libs.ktor.client.curl) } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 9cc3aed84c0..e70af650cfb 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 1ee7cf9fedc..8f4a510dd86 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9cc6d600ad2..3673fdf51d8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,6 +24,7 @@ kotlinpoet = "1.14.2" # https://github.com/square/kotlinpoet junit5 = "5.9.3" # https://github.com/junit-team/junit5 mockk = "1.13.5" # https://github.com/mockk/mockk slf4j = "2.0.7" # https://www.slf4j.org +okio = "3.5.0" # plugins dokka = "1.8.20" # https://github.com/Kotlin/dokka @@ -80,6 +81,7 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", vers mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } kotlinx-resources = { module = "com.goncalossilva:resources", version.ref = "kotlinx-resources" } +okio = { module = "com.squareup.okio:okio", version.ref = "okio" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: # https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 3fe9b3c8408..4e5f9c2940c 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -157,6 +157,14 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +dukat@0.5.8-rc.4: + version "0.5.8-rc.4" + resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" + integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== + dependencies: + google-protobuf "3.12.2" + typescript "3.9.5" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -241,6 +249,11 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +google-protobuf@3.12.2: + version "3.12.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" + integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -520,6 +533,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +typescript@3.9.5: + version "3.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" + integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== + typescript@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index e4fe6b72e20..74548672acb 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -1,8 +1,8 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { - `kord-internal-multiplatform-module` `kord-native-module` + `kord-internal-multiplatform-module` // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index 46d91151df9..0d0f79756fb 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 511f9f57ed9..40f52c38294 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-internal-multiplatform-module` `kord-native-module` + `kord-internal-multiplatform-module` } kotlin { @@ -21,5 +21,10 @@ kotlin { api(libs.bundles.test.jvm) } } + nativeMain { + dependencies { + api(libs.okio) + } + } } } diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index b3ea79f20fa..6b22bfdf063 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -13,7 +13,5 @@ expect object Platform { } expect fun getEnv(name: String): String? -fun file(path: String): String = resource(path).readText() -fun readFile(path: String): ByteReadChannel = ByteReadChannel(resource(path).readBytes()) - -private fun resource(path: String) = Resource("src/commonTest/resources/$path") +expect suspend fun file(project: String, path: String): String +expect suspend fun readFile(project: String, path: String): ByteReadChannel diff --git a/test-kit/src/jsMain/kotlin/Platform.kt b/test-kit/src/jsMain/kotlin/Platform.kt index f646655df04..c9cc7a4220a 100644 --- a/test-kit/src/jsMain/kotlin/Platform.kt +++ b/test-kit/src/jsMain/kotlin/Platform.kt @@ -1,5 +1,6 @@ package dev.kord.test +import io.ktor.utils.io.* import node.process.process actual object Platform { @@ -18,3 +19,9 @@ actual object Platform { } actual fun getEnv(name: String) = process.env[name] + +actual suspend fun file(project: String, path: String): String = + if (Platform.IS_NODE) nodeFile(project, path) else TODO("Browser JS is not supported yet") + +actual suspend fun readFile(project: String, path: String): ByteReadChannel = + if (Platform.IS_NODE) nodeReadFile(project, path) else TODO("Browser JS is not supported yet") diff --git a/test-kit/src/jsMain/kotlin/Platform.node.kt b/test-kit/src/jsMain/kotlin/Platform.node.kt new file mode 100644 index 00000000000..2949105f551 --- /dev/null +++ b/test-kit/src/jsMain/kotlin/Platform.node.kt @@ -0,0 +1,19 @@ +package dev.kord.test + +import io.ktor.utils.io.* +import js.core.toList +import node.buffer.Buffer +import node.buffer.BufferEncoding +import node.process.process + +internal suspend fun nodeFile(project: String, path: String): String = + node.fs.readFile("${process.env["PROJECT_ROOT"]}/$project/src/commonTest/resources/$path") + .toString(BufferEncoding.utf8) + +internal suspend fun nodeReadFile(project: String, path: String): ByteReadChannel { + val buffer = node.fs.readFile("${process.env["PROJECT_ROOT"]}/$project/src/commonTest/resources/$path") + + return ByteReadChannel(buffer.toByteArray()) +} + +private fun Buffer.toByteArray() = values().toList().toByteArray() diff --git a/test-kit/src/jvmMain/kotlin/Platform.kt b/test-kit/src/jvmMain/kotlin/Platform.kt index 85e5784737c..d70783d045a 100644 --- a/test-kit/src/jvmMain/kotlin/Platform.kt +++ b/test-kit/src/jvmMain/kotlin/Platform.kt @@ -6,6 +6,10 @@ import io.ktor.utils.io.jvm.javaio.* actual object Platform { actual const val IS_JVM: Boolean = true actual const val IS_NODE: Boolean = false + actual val IS_BROWSER: Boolean = false + actual val IS_MINGW: Boolean = false + actual val IS_LINUX: Boolean = false + actual val IS_DARWIN: Boolean = false } actual fun getEnv(name: String): String? = System.getenv(name) diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 979518d356e..82e6e61381b 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -2,8 +2,13 @@ package dev.kord.test +import io.ktor.utils.io.* import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.toKString +import okio.BufferedSource +import okio.FileSystem +import okio.IOException +import okio.Path.Companion.toPath import platform.posix.getenv import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform @@ -21,3 +26,24 @@ actual object Platform { @OptIn(ExperimentalForeignApi::class) actual fun getEnv(name: String) = getenv(name)?.toKString() + +private fun actutalPath(path: String) = + "src/commonTest/resources/$path".toPath() + +actual suspend fun file(project: String, path: String): String = read(path, BufferedSource::readUtf8) + +actual suspend fun readFile(project: String, path: String): ByteReadChannel = + read(path) { ByteReadChannel(readByteArray()) } + +private inline fun read(path: String, readerAction: BufferedSource.() -> T): T { + val actualPath = actutalPath(path) + return try { + FileSystem.SYSTEM.read(actualPath, readerAction) + } catch (e: Throwable) { + val pwd = FileSystem.SYSTEM.canonicalize(".".toPath()) + val absolutePath = pwd / actualPath + throw FileNotFoundException(absolutePath.toString(), e) + } +} + +class FileNotFoundException(absolutePath: String, cause: Throwable) : IOException("Absolute Path: $absolutePath", cause) From a4a5e70bc612b71085106957bfab392ee5cc88a8 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:11:58 +0200 Subject: [PATCH 07/11] Fix weird atomic issues on native --- .../kotlin/kord-multiplatform-module.gradle.kts | 5 +++++ .../kotlin/ratelimit/AbstractRateLimiter.kt | 14 ++++++++++++-- .../kotlin/ratelimit/AbstractRateLimiter.kt | 4 ++++ .../kotlin/{ => request}/RecoveredStackTrace.kt | 0 .../nonNativeMain/kotlin/AbstractRateLimiter.kt | 3 +++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt rename rest/src/nativeMain/kotlin/{ => request}/RecoveredStackTrace.kt (100%) create mode 100644 rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index c29c0849e2a..2806f1a9fcc 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -33,6 +33,11 @@ kotlin { withNative() withJs() } + + group("nonNative") { + withJs() + withJvm() + } } } diff --git a/rest/src/commonMain/kotlin/ratelimit/AbstractRateLimiter.kt b/rest/src/commonMain/kotlin/ratelimit/AbstractRateLimiter.kt index b7803871eb8..c623e61dea0 100644 --- a/rest/src/commonMain/kotlin/ratelimit/AbstractRateLimiter.kt +++ b/rest/src/commonMain/kotlin/ratelimit/AbstractRateLimiter.kt @@ -14,6 +14,8 @@ import kotlinx.datetime.Clock import mu.KLogger import kotlin.time.Duration.Companion.minutes +internal expect val useUpdate: Boolean + public abstract class AbstractRateLimiter internal constructor(public val clock: Clock) : RequestRateLimiter { internal abstract val logger: KLogger @@ -67,7 +69,11 @@ public abstract class AbstractRateLimiter internal constructor(public val clock: when (response) { is RequestResponse.GlobalRateLimit -> { logger.trace { "[RATE LIMIT]:[GLOBAL]:exhausted until ${response.reset.value}" } - globalSuspensionPoint.update { response.reset } + if (useUpdate) { + globalSuspensionPoint.update { response.reset } + } else { + globalSuspensionPoint.value = response.reset + } } is RequestResponse.BucketRateLimit -> { logger.trace { "[RATE LIMIT]:[BUCKET]:Bucket ${response.bucketKey.value} was exhausted until ${response.reset.value}" } @@ -93,7 +99,11 @@ public abstract class AbstractRateLimiter internal constructor(public val clock: } fun updateReset(newValue: Reset) { - reset.update { newValue } + if (useUpdate) { + reset.update { newValue } + } else { + reset.value = newValue + } } fun unlock() = mutex.unlock() diff --git a/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt b/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt new file mode 100644 index 00000000000..fcb7c50f4b1 --- /dev/null +++ b/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt @@ -0,0 +1,4 @@ +package dev.kord.rest.ratelimit + +// https://github.com/Kotlin/kotlinx-atomicfu/issues/291 +internal actual val useUpdate: Boolean = false diff --git a/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt b/rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt similarity index 100% rename from rest/src/nativeMain/kotlin/RecoveredStackTrace.kt rename to rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt diff --git a/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt b/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt new file mode 100644 index 00000000000..f48a77ecc64 --- /dev/null +++ b/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt @@ -0,0 +1,3 @@ +package dev.kord.rest.ratelimit + +internal actual val useUpdate: Boolean = true From 8b1a501d7456f11013619ea7d01449f7169d0067 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 15 Apr 2023 19:02:53 +0200 Subject: [PATCH 08/11] Implement Throwable.isTimeout() on native --- gateway/src/nativeMain/kotlin/DefaultGateway.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/DefaultGateway.kt b/gateway/src/nativeMain/kotlin/DefaultGateway.kt index 9a563091de9..2224a4ebe0c 100644 --- a/gateway/src/nativeMain/kotlin/DefaultGateway.kt +++ b/gateway/src/nativeMain/kotlin/DefaultGateway.kt @@ -1,9 +1,11 @@ package dev.kord.gateway +import dev.kord.common.annotation.KordInternal +import io.ktor.util.network.* import kotlin.experimental.ExperimentalNativeApi -// TODO: Timeout -internal actual fun Throwable.isTimeout() = false +@KordInternal +public actual fun Throwable.isTimeout(): Boolean = this is UnresolvedAddressException @OptIn(ExperimentalNativeApi::class) internal actual val os: String get() = Platform.osFamily.name From affa813b624cb32e252b060612549fffddc6be0a Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:41:53 +0200 Subject: [PATCH 09/11] Add publishing utility functions --- .../kord-multiplatform-module.gradle.kts | 31 ++++++++++++++++++- .../main/kotlin/kord-publishing.gradle.kts | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 2806f1a9fcc..acf8687d286 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -35,7 +35,7 @@ kotlin { } group("nonNative") { - withJs() + withJs() withJvm() } } @@ -96,6 +96,35 @@ tasks { } } + register("publishNonNative") { + dependsOn( + "publishKotlinMultiplatformPublicationToMavenRepository", + "publishJsPublicationToMavenRepository", + "publishJvmPublicationToMavenRepository" + ) + } + + register("publishLinux") { + dependsOn("publishLinuxX64PublicationToMavenRepository") + } + + register("publishMingw") { + dependsOn("publishMingwX64PublicationToMavenRepository") + } + + register("publishDarwin") { + dependsOn( + "publishMacosArm64PublicationToMavenRepository", + "publishMacosX64PublicationToMavenRepository", + "publishIosArm64PublicationToMavenRepository", + "publishIosX64PublicationToMavenRepository", + "publishWatchosX64PublicationToMavenRepository", + "publishWatchosArm64PublicationToMavenRepository", + "publishTvosX64PublicationToMavenRepository", + "publishTvosArm64PublicationToMavenRepository" + ) + } + afterEvaluate { named("sourcesJar") { dependsOn("kspCommonMainKotlinMetadata") diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index a001f7113cc..4f7222f05ef 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -75,5 +75,5 @@ signing { val secretKey = getenv("SIGNING_KEY")?.let { String(Base64.getDecoder().decode(it)) } val password = getenv("SIGNING_PASSWORD") useInMemoryPgpKeys(secretKey, password) - sign(publishing.publications) + //sign(publishing.publications) } From 3f6e7901181ad11871af07b15c10e82f8176ece2 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:50:33 +0200 Subject: [PATCH 10/11] Fix darwin compilation --- .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index acf8687d286..4671d43fd8c 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,7 +1,6 @@ import org.gradle.configurationcache.extensions.capitalized import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest plugins { @@ -85,8 +84,9 @@ tasks { val compilationTasks = kotlin.targets.flatMap { buildList { add("compileKotlin${it.name.capitalized()}") - if (it !is KotlinNativeTarget) { - add("${it.name}SourcesJar") + val sourcesJarName = "${it.name}SourcesJar" + if (tasks.findByName(sourcesJarName) != null) { + add(sourcesJarName) } } } From d508a68d56e89cb7d5dae502d1ff7e0f7df38b2c Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:53:14 +0200 Subject: [PATCH 11/11] Fix darwin compilation v2 --- .../kord-multiplatform-module.gradle.kts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 4671d43fd8c..e292be715a9 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -81,21 +81,22 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } - val compilationTasks = kotlin.targets.flatMap { - buildList { - add("compileKotlin${it.name.capitalized()}") - val sourcesJarName = "${it.name}SourcesJar" - if (tasks.findByName(sourcesJarName) != null) { + afterEvaluate { + val compilationTasks = kotlin.targets.flatMap { + buildList { + add("compileKotlin${it.name.capitalized()}") + val sourcesJarName = "${it.name}SourcesJar" add(sourcesJarName) } } - } - for (task in compilationTasks) { - named(task) { - dependsOn("kspCommonMainKotlinMetadata") + for (task in compilationTasks) { + named(task) { + dependsOn("kspCommonMainKotlinMetadata") + } } } + register("publishNonNative") { dependsOn( "publishKotlinMultiplatformPublicationToMavenRepository",