diff --git a/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt b/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt index 224bb06d6..5b0d23178 100644 --- a/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt +++ b/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt @@ -22,9 +22,10 @@ import kotlinx.serialization.modules.polymorphic import net.mamoe.mirai.Mirai import net.mamoe.mirai.message.MessageSerializers import net.mamoe.mirai.message.data.* -import net.mamoe.mirai.message.data.MessageChainImpl import net.mamoe.mirai.utils.MiraiInternalApi import kotlin.reflect.KClass +import kotlin.reflect.full.allSuperclasses +import kotlin.reflect.full.isSubclassOf internal fun ClassSerialDescriptorBuilder.takeElementsFrom(descriptor: SerialDescriptor) { @@ -70,38 +71,45 @@ public open class MessageSourceSerializerImpl(serialName: String) : private val builtInSerializersModule by lazy { SerializersModule { - // non-Message classes - contextual(RawForwardMessage::class, RawForwardMessage.serializer()) - contextual(ForwardMessage.Node::class, ForwardMessage.Node.serializer()) - contextual(VipFace.Kind::class, VipFace.Kind.serializer()) + // NOTE: contextual serializers disabled because of https://github.com/mamoe/mirai/issues/951 +// // non-Message classes +// contextual(RawForwardMessage::class, RawForwardMessage.serializer()) +// contextual(ForwardMessage.Node::class, ForwardMessage.Node.serializer()) +// contextual(VipFace.Kind::class, VipFace.Kind.serializer()) +// +// +// // In case Proguard or something else obfuscated the Kotlin metadata, providing the serializers explicitly will help. +// contextual(At::class, At.serializer()) +// contextual(AtAll::class, AtAll.serializer()) +// contextual(CustomMessage::class, CustomMessage.serializer()) +// contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer()) +// contextual(Face::class, Face.serializer()) +// contextual(Image::class, Image.Serializer) +// contextual(PlainText::class, PlainText.serializer()) +// contextual(QuoteReply::class, QuoteReply.serializer()) +// +// contextual(ForwardMessage::class, ForwardMessage.serializer()) +// +// +// contextual(LightApp::class, LightApp.serializer()) +// contextual(SimpleServiceMessage::class, SimpleServiceMessage.serializer()) +// contextual(AbstractServiceMessage::class, AbstractServiceMessage.serializer()) +// +// contextual(PttMessage::class, PttMessage.serializer()) +// contextual(Voice::class, Voice.serializer()) +// contextual(PokeMessage::class, PokeMessage.serializer()) +// contextual(VipFace::class, VipFace.serializer()) +// contextual(FlashImage::class, FlashImage.serializer()) +// +// contextual(MusicShare::class, MusicShare.serializer()) +// +// contextual(MessageSource::class, MessageSource.serializer()) - // In case Proguard or something else obfuscated the Kotlin metadata, providing the serializers explicitly will help. - contextual(At::class, At.serializer()) - contextual(AtAll::class, AtAll.serializer()) - contextual(CustomMessage::class, CustomMessage.serializer()) - contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer()) - contextual(Face::class, Face.serializer()) - contextual(Image::class, Image.Serializer) - contextual(PlainText::class, PlainText.serializer()) - contextual(QuoteReply::class, QuoteReply.serializer()) +// contextual(SingleMessage::class, SingleMessage.Serializer) + contextual(MessageChain::class, MessageChain.Serializer) + contextual(MessageChainImpl::class, MessageChainImpl.serializer()) - contextual(ForwardMessage::class, ForwardMessage.serializer()) - - - contextual(LightApp::class, LightApp.serializer()) - contextual(SimpleServiceMessage::class, SimpleServiceMessage.serializer()) - contextual(AbstractServiceMessage::class, AbstractServiceMessage.serializer()) - - contextual(PttMessage::class, PttMessage.serializer()) - contextual(Voice::class, Voice.serializer()) - contextual(PokeMessage::class, PokeMessage.serializer()) - contextual(VipFace::class, VipFace.serializer()) - contextual(FlashImage::class, FlashImage.serializer()) - - contextual(MusicShare::class, MusicShare.serializer()) - - contextual(MessageSource::class, MessageSource.serializer()) fun PolymorphicModuleBuilder.messageMetadataSubclasses() { subclass(MessageSource::class, MessageSource.serializer()) @@ -132,11 +140,6 @@ private val builtInSerializersModule by lazy { subclass(MusicShare::class, MusicShare.serializer()) } - contextual(SingleMessage::class, SingleMessage.Serializer) - contextual(MessageChain::class, MessageChain.Serializer) - contextual(MessageChainImpl::class, MessageChainImpl.serializer()) - -// polymorphicDefault(MessageChain::class) { MessageChainImpl.serializer() } // polymorphic(SingleMessage::class) { // subclass(MessageSource::class, MessageSource.serializer()) @@ -153,6 +156,23 @@ private val builtInSerializersModule by lazy { messageMetadataSubclasses() } + polymorphic(MessageContent::class) { + messageContentSubclasses() + } + + polymorphic(MessageMetadata::class) { + messageMetadataSubclasses() + } + + polymorphic(RichMessage::class) { + subclass(SimpleServiceMessage::class, SimpleServiceMessage.serializer()) + subclass(LightApp::class, LightApp.serializer()) + } + + polymorphic(ServiceMessage::class) { + subclass(SimpleServiceMessage::class, SimpleServiceMessage.serializer()) + } + //contextual(SingleMessage::class, SingleMessage.Serializer) // polymorphic(SingleMessage::class, SingleMessage.Serializer) { // messageContentSubclasses() @@ -180,11 +200,16 @@ internal object MessageSerializersImpl : MessageSerializers { override val serializersModule: SerializersModule get() = serializersModuleField ?: builtInSerializersModule @Synchronized - override fun registerSerializer(baseClass: KClass, serializer: KSerializer) { + override fun registerSerializer(type: KClass, serializer: KSerializer) { serializersModuleField = serializersModule.overwriteWith(SerializersModule { - contextual(baseClass, serializer) - polymorphic(SingleMessage::class) { - subclass(baseClass, serializer) + // contextual(type, serializer) + for (superclass in type.allSuperclasses) { + if (superclass.isFinal) continue + if (!superclass.isSubclassOf(SingleMessage::class)) continue + @Suppress("UNCHECKED_CAST") + polymorphic(superclass as KClass) { + subclass(type, serializer) + } } }) } diff --git a/mirai-core-api/src/commonMain/kotlin/message/MessageSerializers.kt b/mirai-core-api/src/commonMain/kotlin/message/MessageSerializers.kt index 2e2b45520..dcaa795cf 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/MessageSerializers.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/MessageSerializers.kt @@ -12,7 +12,9 @@ package net.mamoe.mirai.message import kotlinx.serialization.ContextualSerializer import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json -import kotlinx.serialization.modules.* +import kotlinx.serialization.modules.PolymorphicModuleBuilder +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.subclass import net.mamoe.mirai.internal.message.MessageSerializersImpl import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.MessageChain @@ -50,21 +52,26 @@ public interface MessageSerializers { public val serializersModule: SerializersModule /** - * 注册一个 [SerializersModuleBuilder.contextual] 和 [SingleMessage] 多态域的 [PolymorphicModuleBuilder.subclass]. + * 注册 [serializer] 到 [type] 的所有为 [SingleMessage] 子类型的超类型的多态域 [PolymorphicModuleBuilder.subclass] * - * 相当于 + * 实现: * ``` - * contextual(baseClass, serializer) - * polymorphic(SingleMessage::class) { - * subclass(baseClass, serializer) + * for (superclass in type.allSuperclasses) { + * if (superclass.isFinal) continue + * if (superclass.isSubclassOf(SingleMessage::class)) continue + * polymorphic(superclass) { + * subclass(type, serializer) + * } * } * ``` * * * 若要自己实现消息类型, 务必在这里注册对应序列化器, 否则在 [MessageChain.serializeToJsonString] 时将会出错. + * + * @since 2.0, revised 2.3 */ @MiraiExperimentalApi - public fun registerSerializer(baseClass: KClass, serializer: KSerializer) + public fun registerSerializer(type: KClass, serializer: KSerializer) /** * 合并 [serializersModule] 到 [MessageSerializers.serializersModule] 并覆盖. diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt index 9f9cfa63d..f7a6c28b6 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt @@ -245,7 +245,7 @@ public interface MessageChain : */ public object Serializer : KSerializer { @Suppress("DEPRECATION_ERROR") - private val delegate = ListSerializer(PolymorphicSerializer(SingleMessage::class)) + private val delegate = ListSerializer(SingleMessage.Serializer) override val descriptor: SerialDescriptor = delegate.descriptor override fun deserialize(decoder: Decoder): MessageChain = delegate.deserialize(decoder).toMessageChain() override fun serialize(encoder: Encoder, value: MessageChain): Unit = delegate.serialize(encoder, value)