From 52342267880a4099b47e1e9ebd94ffcbd6b6e1ee Mon Sep 17 00:00:00 2001 From: Him188 Date: Tue, 21 Apr 2020 14:19:17 +0800 Subject: [PATCH] Add noinline subscribers that take eventClasses --- .../net.mamoe.mirai/event/subscriber.kt | 137 ++++++++++++++---- 1 file changed, 105 insertions(+), 32 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscriber.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscriber.kt index 1652f662d..4bfa4596e 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscriber.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/subscriber.kt @@ -19,12 +19,15 @@ import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.internal.Handler import net.mamoe.mirai.event.internal.subscribeInternal import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.SinceMirai import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.jvm.JvmName +import kotlin.jvm.JvmSynthetic +import kotlin.reflect.KClass /* * 该文件为所有的订阅事件的方法. @@ -118,12 +121,14 @@ interface Listener : CompletableJob { * * **注意:** 事件处理是 `suspend` 的, 请规范处理 JVM 阻塞方法. * - * @param coroutineContext 给事件监听协程的额外的 [CoroutineContext] + * @param coroutineContext 给事件监听协程的额外的 [CoroutineContext]. + * @param concurrency 并发类型. 查看 [Listener.ConcurrencyKind] * - * @see subscribingGet 监听一个事件, 并尝试从这个事件中获取一个值. - * @see subscribingGetAsync 异步监听一个事件, 并尝试从这个事件中获取一个值. + * @see syncFromEvent 监听一个事件, 并尝试从这个事件中获取一个值. + * @see syncFromEventAsync 异步监听一个事件, 并尝试从这个事件中获取一个值. * - * @see whileSelectMessages 挂起当前协程, 等待任意一个事件监听器返回 `false` 后返回. + * @see selectMessages 以 `when` 的语法 '选择' 即将到来的一条消息. + * @see whileSelectMessages 以 `when` 的语法 '选择' 即将到来的所有消息, 直到不满足筛选结果. * * @see subscribeAlways 一直监听 * @see subscribeOnce 只监听一次 @@ -132,13 +137,29 @@ interface Listener : CompletableJob { * @see subscribeGroupMessages 监听群消息 DSL * @see subscribeFriendMessages 监听好友消息 DSL */ -@OptIn(MiraiInternalAPI::class) +@OptIn(ExperimentalContracts::class) inline fun CoroutineScope.subscribe( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, noinline handler: suspend E.(E) -> ListeningStatus +): Listener { + contract { + callsInPlace(handler, InvocationKind.UNKNOWN) + } + return subscribe(E::class, coroutineContext, concurrency, handler) +} + +/** + * @see CoroutineScope.subscribe + */ +@SinceMirai("0.38.0") +fun CoroutineScope.subscribe( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, + handler: suspend E.(E) -> ListeningStatus ): Listener = - E::class.subscribeInternal(Handler(coroutineContext, concurrency) { it.handler(it); }) + eventClass.subscribeInternal(Handler(coroutineContext, concurrency) { it.handler(it); }) /** * 在指定的 [CoroutineScope] 下订阅所有 [E] 及其子类事件. @@ -149,9 +170,9 @@ inline fun CoroutineScope.subscribe( * * @param coroutineContext 给事件监听协程的额外的 [CoroutineContext] * - * @see subscribe 获取更多说明 + * @see CoroutineScope.subscribe 获取更多说明 */ -@OptIn(MiraiInternalAPI::class, ExperimentalContracts::class) +@OptIn(ExperimentalContracts::class) inline fun CoroutineScope.subscribeAlways( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, @@ -160,11 +181,26 @@ inline fun CoroutineScope.subscribeAlways( contract { callsInPlace(listener, InvocationKind.UNKNOWN) } - return E::class.subscribeInternal( - Handler( - coroutineContext, - concurrency - ) { it.listener(it); ListeningStatus.LISTENING }) + return subscribeAlways(E::class, coroutineContext, concurrency, listener) +} + +/** + * @see CoroutineScope.subscribeAlways + */ +@SinceMirai("0.38.0") +@OptIn(ExperimentalContracts::class) +fun CoroutineScope.subscribeAlways( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, + listener: suspend E.(E) -> Unit +): Listener { + contract { + callsInPlace(listener, InvocationKind.UNKNOWN) + } + return eventClass.subscribeInternal( + Handler(coroutineContext, concurrency) { it.listener(it); ListeningStatus.LISTENING } + ) } /** @@ -178,17 +214,24 @@ inline fun CoroutineScope.subscribeAlways( * * @see subscribe 获取更多说明 */ -@OptIn(MiraiInternalAPI::class) +@JvmSynthetic inline fun CoroutineScope.subscribeOnce( coroutineContext: CoroutineContext = EmptyCoroutineContext, noinline listener: suspend E.(E) -> Unit -): Listener = - E::class.subscribeInternal( - Handler( - coroutineContext, - Listener.ConcurrencyKind.LOCKED - ) { it.listener(it); ListeningStatus.STOPPED }) +): Listener = subscribeOnce(E::class, coroutineContext, listener) +/** + * @see CoroutineScope.subscribeOnce + */ +@SinceMirai("0.38.0") +fun CoroutineScope.subscribeOnce( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + listener: suspend E.(E) -> Unit +): Listener = + eventClass.subscribeInternal( + Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) { it.listener(it); ListeningStatus.STOPPED } + ) // // 以下为带筛选 Bot 的监听 @@ -207,18 +250,28 @@ inline fun CoroutineScope.subscribeOnce( * * @see subscribe 获取更多说明 */ +@JvmSynthetic @JvmName("subscribeAlwaysForBot") @OptIn(MiraiInternalAPI::class) inline fun Bot.subscribe( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, noinline handler: suspend E.(E) -> ListeningStatus +): Listener = this.subscribe(E::class, coroutineContext, concurrency, handler) + +/** + * @see Bot.subscribe + */ +@SinceMirai("0.38.0") +fun Bot.subscribe( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED, + handler: suspend E.(E) -> ListeningStatus ): Listener = - E::class.subscribeInternal( - Handler( - coroutineContext, - concurrency - ) { if (it.bot === this) it.handler(it) else ListeningStatus.LISTENING }) + eventClass.subscribeInternal( + Handler(coroutineContext, concurrency) { if (it.bot === this) it.handler(it) else ListeningStatus.LISTENING } + ) /** @@ -232,18 +285,28 @@ inline fun Bot.subscribe( * * @see subscribe 获取更多说明 */ +@JvmSynthetic @JvmName("subscribeAlwaysForBot1") @OptIn(MiraiInternalAPI::class) inline fun Bot.subscribeAlways( coroutineContext: CoroutineContext = EmptyCoroutineContext, concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, noinline listener: suspend E.(E) -> Unit +): Listener = subscribeAlways(E::class, coroutineContext, concurrency, listener) + +/** + * @see Bot.subscribeAlways + */ +@SinceMirai("0.38.0") +fun Bot.subscribeAlways( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, + listener: suspend E.(E) -> Unit ): Listener { - return E::class.subscribeInternal( - Handler( - coroutineContext, - concurrency - ) { if (it.bot === this) it.listener(it); ListeningStatus.LISTENING }) + return eventClass.subscribeInternal( + Handler(coroutineContext, concurrency) { if (it.bot === this) it.listener(it); ListeningStatus.LISTENING } + ) } /** @@ -257,13 +320,23 @@ inline fun Bot.subscribeAlways( * * @see subscribe 获取更多说明 */ +@JvmSynthetic @JvmName("subscribeOnceForBot2") -@OptIn(MiraiInternalAPI::class) inline fun Bot.subscribeOnce( coroutineContext: CoroutineContext = EmptyCoroutineContext, noinline listener: suspend E.(E) -> Unit +): Listener = subscribeOnce(E::class, coroutineContext, listener) + +/** + * @see Bot.subscribeOnce + */ +@SinceMirai("0.38.0") +fun Bot.subscribeOnce( + eventClass: KClass, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + listener: suspend E.(E) -> Unit ): Listener = - E::class.subscribeInternal(Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) { + eventClass.subscribeInternal(Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) { if (it.bot === this) { it.listener(it) ListeningStatus.STOPPED