Add EventChannel.filter accepting non-suspend Predicates for Java users

This commit is contained in:
Him188 2021-01-28 08:16:35 +08:00
parent f48f73f673
commit b30e098068
4 changed files with 86 additions and 1 deletions

View File

@ -1516,6 +1516,7 @@ public class net/mamoe/mirai/event/EventChannel {
public final fun context ([Lkotlin/coroutines/CoroutineContext;)Lnet/mamoe/mirai/event/EventChannel;
public final fun exceptionHandler (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/event/EventChannel;
public final fun exceptionHandler (Lkotlinx/coroutines/CoroutineExceptionHandler;)Lnet/mamoe/mirai/event/EventChannel;
public final fun filter (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/event/EventChannel;
public final synthetic fun filter (Lkotlin/jvm/functions/Function2;)Lnet/mamoe/mirai/event/EventChannel;
public final fun filterIsInstance (Ljava/lang/Class;)Lnet/mamoe/mirai/event/EventChannel;
public final fun filterIsInstance (Lkotlin/reflect/KClass;)Lnet/mamoe/mirai/event/EventChannel;

View File

@ -148,6 +148,48 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
}
}
/**
* [EventChannel.filter] Java 版本.
*
* 添加一个过滤器. 过滤器将在收到任何事件之后, 传递给通过 [EventChannel.subscribe] 注册的监听器之前调用.
*
* [filter] 返回 `true`, 该事件将会被传给监听器. 否则将会被忽略, **监听器继续监听**.
*
* ## 线性顺序
* 多个 [filter] 的处理是线性且有顺序的. 若一个 [filter] 已经返回了 `false` (代表忽略这个事件), 则会立即忽略, 而不会传递给后续过滤器.
*
* 示例:
* ```
* GlobalEventChannel // GlobalEventChannel 会收到全局所有事件, 事件类型是 Event
* .filterIsInstance(BotEvent.class) // 过滤, 只接受 BotEvent
* .filter(event ->
* // 此时的 event 一定是 BotEvent
* event.bot.id == 123456 // 再过滤 event 的 bot.id
* )
* .subscribeAlways(event -> {
* // 现在 event 是 BotEvent, 且 bot.id == 123456
* })
* ```
*
* ## 过滤器阻塞
* [filter] 允许阻塞线程. **过滤器的阻塞将被认为是事件监听器的阻塞**.
*
* 过滤器阻塞是否会影响事件处理,
* 取决于 [subscribe] 时的 [ConcurrencyKind] [EventPriority].
*
* ## 过滤器异常处理
* [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出.
*
* @see filterIsInstance 过滤指定类型的事件
*
* @since 2.2
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
public fun filter(filter: (event: BaseEvent) -> Boolean): EventChannel<BaseEvent> {
return filter { runInterruptible { filter(it) } }
}
/**
* 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel]
* @see filter 获取更多信息

View File

@ -0,0 +1,32 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package event;
import net.mamoe.mirai.event.Event;
import net.mamoe.mirai.event.GlobalEventChannel;
import net.mamoe.mirai.event.events.GroupMessageEvent;
import net.mamoe.mirai.event.events.MessageEvent;
/**
* 仅测试可以使用, 不会被编译运行
*/
public class EventChannelJavaTest {
public static void main(String[] args) {
GlobalEventChannel.INSTANCE
.filter(event -> {
return event.toString() == "test";
})
.filterIsInstance(MessageEvent.class)
.subscribeAlways(GroupMessageEvent.class, groupMessageEvent -> {
});
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -16,15 +16,25 @@ import net.mamoe.mirai.event.events.MessageEvent
import org.junit.jupiter.api.Test
internal class EventChannelTest {
suspend fun suspendCall() {
}
@Suppress("UNUSED_VARIABLE")
@Test
fun testVariance() {
var global: EventChannel<Event> = GlobalEventChannel
var a: EventChannel<MessageEvent> = global.filterIsInstance<MessageEvent>()
val filterLambda: (ev: MessageEvent) -> Boolean = { true }
// Kotlin can't resolve to the non-suspend one
a.filter {
// it: Event
suspendCall() // would be allowed in Kotlin
it.isIntercepted
}
val messageEventChannel = a.filterIsInstance<MessageEvent>()
// group.asChannel<GroupMessageEvent>()