Fix the problem listening super events

This commit is contained in:
Him188 2019-12-23 22:55:06 +08:00
parent 227fd84533
commit 34236147e4
2 changed files with 52 additions and 12 deletions

View File

@ -90,19 +90,24 @@ internal object EventListenerManger {
}
// inline: NO extra Continuation
@Suppress("UNCHECKED_CAST")
internal suspend inline fun Subscribable.broadcastInternal() {
if (EventDisabled) return
callAndRemoveIfRequired(this::class.listeners())
this::class.supertypes.forEach { superType ->
val superListeners =
@Suppress("UNCHECKED_CAST")
(superType.classifier as? KClass<out Subscribable>)?.listeners() ?: return // return if super type is not Subscribable
var supertypes = this::class.supertypes
while (true) {
val superSubscribableType = supertypes.firstOrNull {
it.classifier as? KClass<out Subscribable> != null
}
callAndRemoveIfRequired(superListeners)
superSubscribableType?.let {
callAndRemoveIfRequired((it.classifier as KClass<out Subscribable>).listeners())
}
supertypes = (superSubscribableType?.classifier as? KClass<*>)?.supertypes ?: return
}
return
}
private suspend inline fun <E : Subscribable> E.callAndRemoveIfRequired(listeners: EventListeners<E>) {

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.event
import kotlinx.coroutines.CompletableJob
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.test.shouldBeEqualTo
import kotlin.system.exitProcess
@ -16,28 +18,61 @@ class EventTests {
runBlocking {
val subscriber = subscribeAlways<TestEvent> {
triggered = true
println("Triggered")
}
TestEvent().broadcast().triggered shouldBeEqualTo true
subscriber.complete()
println("finished")
}
}
@Test
fun testSubscribeGlobalScope() {
runBlocking {
TestEvent().broadcast().triggered shouldBeEqualTo true
println("finished")
}
GlobalScope.subscribeAlways<TestEvent> {
triggered = true
}
TestEvent().broadcast().triggered shouldBeEqualTo true
}
}
open class ParentEvent : Subscribable {
var triggered = false
}
open class ChildEvent : ParentEvent()
open class ChildChildEvent : ChildEvent()
@Test
fun `broadcast Child to Parent`() {
runBlocking {
val job: CompletableJob
job = subscribeAlways<ParentEvent> {
triggered = true
}
ChildEvent().broadcast().triggered shouldBeEqualTo true
job.complete()
}
}
@Test
fun `broadcast ChildChild to Parent`() {
runBlocking {
val job: CompletableJob
job = subscribeAlways<ParentEvent> {
triggered = true
}
ChildChildEvent().broadcast().triggered shouldBeEqualTo true
job.complete()
}
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
EventTests().testSubscribeGlobalScope()
EventTests().`broadcast ChildChild to Parent`()
exitProcess(0)
}
}