cloud-kotlin-coroutines (#318)
* Builder coroutine support * Move coroutines to version catalog * Add kdocs * Add note about simple coordinator * Update changelog
This commit is contained in:
parent
6011bd1d63
commit
3f0ef5715c
10 changed files with 298 additions and 3 deletions
|
|
@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [1.6.0]
|
## [1.6.0]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Kotlin: Support for suspending command functions using `AnnotationParser<C>.installCoroutineSupport()`
|
- Kotlin: New module `cloud-kotlin-coroutines`: Support for suspending command handlers in builders and the Kotlin builder DSL
|
||||||
|
- Kotlin: New module `cloud-kotlin-coroutines-annotations`: Support for suspending annotated command functions using
|
||||||
|
`AnnotationParser<C>.installCoroutineSupport()`
|
||||||
- Flags can be bound to a permission
|
- Flags can be bound to a permission
|
||||||
- Paper: Implement KeyedWorldArgument for matching worlds by their namespaced key
|
- Paper: Implement KeyedWorldArgument for matching worlds by their namespaced key
|
||||||
- Annotations: Parser parameter annotations are now also parsed for flags ([#315](https://github.com/Incendo/cloud/pull/315))
|
- Annotations: Parser parameter annotations are now also parsed for flags ([#315](https://github.com/Incendo/cloud/pull/315))
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,5 @@ dependencies {
|
||||||
api(project(":cloud-core"))
|
api(project(":cloud-core"))
|
||||||
api(project(":cloud-annotations"))
|
api(project(":cloud-annotations"))
|
||||||
api(kotlin("reflect"))
|
api(kotlin("reflect"))
|
||||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
|
api(libs.bundles.coroutines)
|
||||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.5.2")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
cloud-kotlin/cloud-kotlin-coroutines/build.gradle.kts
Normal file
11
cloud-kotlin/cloud-kotlin-coroutines/build.gradle.kts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
plugins {
|
||||||
|
id("cloud.kotlin-conventions")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":cloud-core"))
|
||||||
|
api(libs.bundles.coroutines)
|
||||||
|
|
||||||
|
compileOnly(project(":cloud-kotlin-extensions"))
|
||||||
|
testImplementation(project(":cloud-kotlin-extensions"))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Module cloud-kotlin-coroutines
|
||||||
|
|
||||||
|
Cloud extensions for Kotlin coroutine integration.
|
||||||
|
|
||||||
|
# Package cloud.commandframework.kotlin.coroutines
|
||||||
|
|
||||||
|
Cloud Kotlin coroutines classes and functions.
|
||||||
|
|
||||||
|
# Package cloud.commandframework.kotlin.coroutines.extension
|
||||||
|
|
||||||
|
Extension functions for existing Cloud types
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.kotlin.coroutines
|
||||||
|
|
||||||
|
import cloud.commandframework.context.CommandContext
|
||||||
|
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator
|
||||||
|
import cloud.commandframework.execution.CommandExecutionCoordinator
|
||||||
|
import cloud.commandframework.execution.CommandExecutionHandler
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.future.future
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspending version of [CommandExecutionHandler] for use with
|
||||||
|
* coroutines.
|
||||||
|
*
|
||||||
|
* NOTE: It is highly advised to not use [CommandExecutionCoordinator.SimpleCoordinator] together
|
||||||
|
* with coroutine support. Consider using [AsynchronousCommandExecutionCoordinator] instead.
|
||||||
|
*
|
||||||
|
* @param C command sender type
|
||||||
|
*/
|
||||||
|
public fun interface SuspendingExecutionHandler<C : Any> {
|
||||||
|
/**
|
||||||
|
* Handles command execution.
|
||||||
|
*
|
||||||
|
* @param commandContext command context
|
||||||
|
*/
|
||||||
|
public suspend operator fun invoke(commandContext: CommandContext<C>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new [CommandExecutionHandler] for use in building commands,
|
||||||
|
* backed by this [SuspendingExecutionHandler].
|
||||||
|
*
|
||||||
|
* @param scope coroutine scope
|
||||||
|
* @param context coroutine context
|
||||||
|
* @return new [CommandExecutionHandler]
|
||||||
|
*/
|
||||||
|
public fun asCommandExecutionHandler(
|
||||||
|
scope: CoroutineScope = GlobalScope,
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
): CommandExecutionHandler<C> = createCommandExecutionHandler(scope, context, this)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* Create a new [CommandExecutionHandler] for use in building commands,
|
||||||
|
* backed by the given [SuspendingExecutionHandler].
|
||||||
|
*
|
||||||
|
* @param scope coroutine scope
|
||||||
|
* @param context coroutine context
|
||||||
|
* @param handler suspending handler
|
||||||
|
* @return new [CommandExecutionHandler]
|
||||||
|
*/
|
||||||
|
public fun <C : Any> createCommandExecutionHandler(
|
||||||
|
scope: CoroutineScope = GlobalScope,
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
handler: SuspendingExecutionHandler<C>,
|
||||||
|
): CommandExecutionHandler<C> = CommandExecutionHandler.FutureCommandExecutionHandler { ctx ->
|
||||||
|
scope.future(context) {
|
||||||
|
handler(ctx)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.kotlin.coroutines.extension
|
||||||
|
|
||||||
|
import cloud.commandframework.Command
|
||||||
|
import cloud.commandframework.kotlin.coroutines.SuspendingExecutionHandler
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a suspending command execution handler.
|
||||||
|
*
|
||||||
|
* @param scope coroutine scope
|
||||||
|
* @param context coroutine context
|
||||||
|
* @param handler suspending handler
|
||||||
|
* @return modified copy of this [Command.Builder]
|
||||||
|
* @see Command.Builder.handler
|
||||||
|
* @see SuspendingExecutionHandler
|
||||||
|
*/
|
||||||
|
public fun <C : Any> Command.Builder<C>.suspendingHandler(
|
||||||
|
scope: CoroutineScope = GlobalScope,
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
handler: SuspendingExecutionHandler<C>,
|
||||||
|
): Command.Builder<C> = handler(SuspendingExecutionHandler.createCommandExecutionHandler(scope, context, handler))
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.kotlin.coroutines.extension
|
||||||
|
|
||||||
|
import cloud.commandframework.kotlin.MutableCommandBuilder
|
||||||
|
import cloud.commandframework.kotlin.coroutines.SuspendingExecutionHandler
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a suspending command execution handler.
|
||||||
|
*
|
||||||
|
* @param scope coroutine scope
|
||||||
|
* @param context coroutine context
|
||||||
|
* @param handler suspending handler
|
||||||
|
* @return this [MutableCommandBuilder]
|
||||||
|
* @see MutableCommandBuilder.handler
|
||||||
|
* @see SuspendingExecutionHandler
|
||||||
|
*/
|
||||||
|
public fun <C : Any> MutableCommandBuilder<C>.suspendingHandler(
|
||||||
|
scope: CoroutineScope = GlobalScope,
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
handler: SuspendingExecutionHandler<C>,
|
||||||
|
): MutableCommandBuilder<C> = mutate {
|
||||||
|
it.suspendingHandler(scope, context, handler)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.kotlin.coroutines
|
||||||
|
|
||||||
|
import cloud.commandframework.CommandManager
|
||||||
|
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator
|
||||||
|
import cloud.commandframework.internal.CommandRegistrationHandler
|
||||||
|
import cloud.commandframework.kotlin.coroutines.extension.suspendingHandler
|
||||||
|
import cloud.commandframework.kotlin.extension.buildAndRegister
|
||||||
|
import cloud.commandframework.meta.CommandMeta
|
||||||
|
import cloud.commandframework.meta.SimpleCommandMeta
|
||||||
|
import kotlinx.coroutines.future.await
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
class SuspendingHandlerTest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val executorService: ExecutorService = Executors.newSingleThreadExecutor()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test(): Unit = runBlocking {
|
||||||
|
val manager = TestCommandManager()
|
||||||
|
|
||||||
|
manager.buildAndRegister("suspend") {
|
||||||
|
suspendingHandler {
|
||||||
|
println("called from thread: ${Thread.currentThread().name}")
|
||||||
|
|
||||||
|
someSuspendingFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.executeCommand(TestCommandSender(), "suspend").await()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun someSuspendingFunction() {}
|
||||||
|
|
||||||
|
private class TestCommandSender
|
||||||
|
|
||||||
|
private class TestCommandManager : CommandManager<TestCommandSender>(
|
||||||
|
AsynchronousCommandExecutionCoordinator.newBuilder<TestCommandSender>()
|
||||||
|
.withExecutor(executorService)
|
||||||
|
.build(),
|
||||||
|
CommandRegistrationHandler.nullCommandRegistrationHandler()
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun hasPermission(sender: TestCommandSender, permission: String): Boolean = true
|
||||||
|
|
||||||
|
override fun createDefaultCommandMeta(): CommandMeta = SimpleCommandMeta.empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ plugins:
|
||||||
versions:
|
versions:
|
||||||
kotlin: &kotlin 1.5.31
|
kotlin: &kotlin 1.5.31
|
||||||
dokka: *kotlin
|
dokka: *kotlin
|
||||||
|
coroutines: 1.5.2
|
||||||
checkerQual: 3.14.0
|
checkerQual: 3.14.0
|
||||||
|
|
||||||
# build-logic
|
# build-logic
|
||||||
|
|
@ -26,6 +27,15 @@ dependencies:
|
||||||
name: checker-qual
|
name: checker-qual
|
||||||
version: { ref: checkerQual }
|
version: { ref: checkerQual }
|
||||||
|
|
||||||
|
coroutinesCore:
|
||||||
|
group: org.jetbrains.kotlinx
|
||||||
|
name: kotlinx-coroutines-core
|
||||||
|
version: { ref: coroutines }
|
||||||
|
coroutinesJdk8:
|
||||||
|
group: org.jetbrains.kotlinx
|
||||||
|
name: kotlinx-coroutines-jdk8
|
||||||
|
version: { ref: coroutines }
|
||||||
|
|
||||||
# build-logic
|
# build-logic
|
||||||
indraCommon:
|
indraCommon:
|
||||||
group: net.kyori
|
group: net.kyori
|
||||||
|
|
@ -61,3 +71,6 @@ dependencies:
|
||||||
version: { ref: ktlint }
|
version: { ref: ktlint }
|
||||||
|
|
||||||
bundles:
|
bundles:
|
||||||
|
coroutines:
|
||||||
|
- coroutinesCore
|
||||||
|
- coroutinesJdk8
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ include(":cloud-annotations")
|
||||||
|
|
||||||
// Kotlin Extensions
|
// Kotlin Extensions
|
||||||
setupKotlinModule("cloud-kotlin-extensions")
|
setupKotlinModule("cloud-kotlin-extensions")
|
||||||
|
setupKotlinModule("cloud-kotlin-coroutines")
|
||||||
setupKotlinModule("cloud-kotlin-coroutines-annotations")
|
setupKotlinModule("cloud-kotlin-coroutines-annotations")
|
||||||
|
|
||||||
// Discord Modules
|
// Discord Modules
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue