Add noinline subscribers that take eventClasses

This commit is contained in:
Him188 2020-04-21 14:19:17 +08:00
parent 8c3b76e1d3
commit 5234226788

View File

@ -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<in E : Event> : 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<in E : Event> : CompletableJob {
* @see subscribeGroupMessages 监听群消息 DSL
* @see subscribeFriendMessages 监听好友消息 DSL
*/
@OptIn(MiraiInternalAPI::class)
@OptIn(ExperimentalContracts::class)
inline fun <reified E : Event> CoroutineScope.subscribe(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
noinline handler: suspend E.(E) -> ListeningStatus
): Listener<E> {
contract {
callsInPlace(handler, InvocationKind.UNKNOWN)
}
return subscribe(E::class, coroutineContext, concurrency, handler)
}
/**
* @see CoroutineScope.subscribe
*/
@SinceMirai("0.38.0")
fun <E : Event> CoroutineScope.subscribe(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
handler: suspend E.(E) -> ListeningStatus
): Listener<E> =
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 <reified E : Event> CoroutineScope.subscribe(
*
* @param coroutineContext 给事件监听协程的额外的 [CoroutineContext]
*
* @see subscribe 获取更多说明
* @see CoroutineScope.subscribe 获取更多说明
*/
@OptIn(MiraiInternalAPI::class, ExperimentalContracts::class)
@OptIn(ExperimentalContracts::class)
inline fun <reified E : Event> CoroutineScope.subscribeAlways(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
@ -160,11 +181,26 @@ inline fun <reified E : Event> 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 <E : Event> CoroutineScope.subscribeAlways(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
listener: suspend E.(E) -> Unit
): Listener<E> {
contract {
callsInPlace(listener, InvocationKind.UNKNOWN)
}
return eventClass.subscribeInternal(
Handler(coroutineContext, concurrency) { it.listener(it); ListeningStatus.LISTENING }
)
}
/**
@ -178,17 +214,24 @@ inline fun <reified E : Event> CoroutineScope.subscribeAlways(
*
* @see subscribe 获取更多说明
*/
@OptIn(MiraiInternalAPI::class)
@JvmSynthetic
inline fun <reified E : Event> CoroutineScope.subscribeOnce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
noinline listener: suspend E.(E) -> Unit
): Listener<E> =
E::class.subscribeInternal(
Handler(
coroutineContext,
Listener.ConcurrencyKind.LOCKED
) { it.listener(it); ListeningStatus.STOPPED })
): Listener<E> = subscribeOnce(E::class, coroutineContext, listener)
/**
* @see CoroutineScope.subscribeOnce
*/
@SinceMirai("0.38.0")
fun <E : Event> CoroutineScope.subscribeOnce(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
listener: suspend E.(E) -> Unit
): Listener<E> =
eventClass.subscribeInternal(
Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) { it.listener(it); ListeningStatus.STOPPED }
)
//
// 以下为带筛选 Bot 的监听
@ -207,18 +250,28 @@ inline fun <reified E : Event> CoroutineScope.subscribeOnce(
*
* @see subscribe 获取更多说明
*/
@JvmSynthetic
@JvmName("subscribeAlwaysForBot")
@OptIn(MiraiInternalAPI::class)
inline fun <reified E : BotEvent> Bot.subscribe(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
noinline handler: suspend E.(E) -> ListeningStatus
): Listener<E> = this.subscribe(E::class, coroutineContext, concurrency, handler)
/**
* @see Bot.subscribe
*/
@SinceMirai("0.38.0")
fun <E : BotEvent> Bot.subscribe(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.LOCKED,
handler: suspend E.(E) -> ListeningStatus
): Listener<E> =
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 <reified E : BotEvent> Bot.subscribe(
*
* @see subscribe 获取更多说明
*/
@JvmSynthetic
@JvmName("subscribeAlwaysForBot1")
@OptIn(MiraiInternalAPI::class)
inline fun <reified E : BotEvent> Bot.subscribeAlways(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
noinline listener: suspend E.(E) -> Unit
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, listener)
/**
* @see Bot.subscribeAlways
*/
@SinceMirai("0.38.0")
fun <E : BotEvent> Bot.subscribeAlways(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listener: suspend E.(E) -> Unit
): Listener<E> {
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 <reified E : BotEvent> Bot.subscribeAlways(
*
* @see subscribe 获取更多说明
*/
@JvmSynthetic
@JvmName("subscribeOnceForBot2")
@OptIn(MiraiInternalAPI::class)
inline fun <reified E : BotEvent> Bot.subscribeOnce(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
noinline listener: suspend E.(E) -> Unit
): Listener<E> = subscribeOnce(E::class, coroutineContext, listener)
/**
* @see Bot.subscribeOnce
*/
@SinceMirai("0.38.0")
fun <E : BotEvent> Bot.subscribeOnce(
eventClass: KClass<E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
listener: suspend E.(E) -> Unit
): Listener<E> =
E::class.subscribeInternal(Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) {
eventClass.subscribeInternal(Handler(coroutineContext, Listener.ConcurrencyKind.LOCKED) {
if (it.bot === this) {
it.listener(it)
ListeningStatus.STOPPED