mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-25 04:50:26 +08:00
Stable MessageKey
This commit is contained in:
parent
b2f0424418
commit
16e4bde07e
mirai-core-api/src
commonMain/kotlin/message/data
commonTest/kotlin/message.data
mirai-core/src/jvmTest/kotlin
@ -56,7 +56,6 @@ public data class PokeMessage @MiraiInternalApi constructor(
|
||||
public val pokeType: Int, // 'type' is used by serialization
|
||||
public val id: Int
|
||||
) : HummerMessage, CodableMessage {
|
||||
@ExperimentalMessageKey
|
||||
override val key: MessageKey<HummerMessage>
|
||||
get() = Key
|
||||
|
||||
@ -195,7 +194,6 @@ public interface MarketFace : CodableMessage, HummerMessage {
|
||||
public val name: String
|
||||
public val id: Int
|
||||
|
||||
@ExperimentalMessageKey
|
||||
override val key: MessageKey<MarketFace>
|
||||
get() = Key
|
||||
|
||||
@ -238,11 +236,9 @@ public data class VipFace @MiraiInternalApi constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalMessageKey
|
||||
override val key: MessageKey<VipFace>
|
||||
get() = Key
|
||||
|
||||
@Suppress("DEPRECATION_ERROR", "DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
public companion object Key :
|
||||
AbstractPolymorphicMessageKey<HummerMessage, VipFace>(HummerMessage, { it.safeCast() }) {
|
||||
|
||||
@ -292,7 +288,7 @@ public data class VipFace @MiraiInternalApi constructor(
|
||||
}
|
||||
|
||||
override fun appendMiraiCode(builder: StringBuilder) {
|
||||
builder.append(stringValue) // TODO:
|
||||
builder.append(stringValue)
|
||||
}
|
||||
|
||||
private val stringValue = "[mirai:vipface:$kind,$count]"
|
||||
@ -325,7 +321,6 @@ public data class FlashImage(
|
||||
@Contextual
|
||||
public val image: Image
|
||||
) : MessageContent, HummerMessage, CodableMessage, ConstrainSingle {
|
||||
@ExperimentalMessageKey
|
||||
override val key: MessageKey<FlashImage>
|
||||
get() = Key
|
||||
|
||||
|
@ -27,7 +27,6 @@ import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.MessageSerializer
|
||||
import net.mamoe.mirai.message.MessageSerializerImpl
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalApi
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
import net.mamoe.mirai.utils.safeCast
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
@ -239,16 +238,6 @@ public interface Message { // must be interface. Don't consider any changes.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标注一个实验性的 [MessageKey] API.
|
||||
*
|
||||
* 在 `2.0-M2` 时将会推进 [MessageKey] 到稳定状态并删除此注解.
|
||||
*/
|
||||
@PlannedRemoval("2.0-M2")
|
||||
@MiraiExperimentalApi
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||
public annotation class ExperimentalMessageKey
|
||||
|
||||
|
||||
@MiraiExperimentalApi
|
||||
@JvmSynthetic
|
||||
@ -364,13 +353,11 @@ public interface MessageMetadata : SingleMessage {
|
||||
*
|
||||
* @see MessageSource
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public interface ConstrainSingle : SingleMessage {
|
||||
/**
|
||||
* 用于判断是否为同一种元素的 [MessageKey]. 使用多态类型 [MessageKey] 最上层的 [MessageKey].
|
||||
* @see MessageKey 查看更多信息
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public val key: MessageKey<*>
|
||||
}
|
||||
|
||||
@ -390,7 +377,6 @@ public interface ConstrainSingle : SingleMessage {
|
||||
*/
|
||||
@Serializable(MessageContent.Serializer::class)
|
||||
public interface MessageContent : SingleMessage {
|
||||
@ExperimentalMessageKey
|
||||
public companion object Key : AbstractMessageKey<MessageContent>({ it.safeCast() })
|
||||
|
||||
public object Serializer : KSerializer<MessageContent> by PolymorphicSerializer(MessageContent::class)
|
||||
|
@ -86,11 +86,9 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
|
||||
*
|
||||
* @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException]
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public operator fun <M : SingleMessage> get(key: MessageKey<M>): M? =
|
||||
asSequence().mapNotNull { key.safeCast.invoke(it) }.firstOrNull()
|
||||
|
||||
@ExperimentalMessageKey
|
||||
public operator fun <M : SingleMessage> contains(key: MessageKey<M>): Boolean =
|
||||
asSequence().any { key.safeCast.invoke(it) != null }
|
||||
|
||||
@ -149,7 +147,6 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
|
||||
*
|
||||
* @param key 由各个类型消息的伴生对象持有. 如 [MessageSource.Key]
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
@JvmOverloads
|
||||
public inline fun <M : SingleMessage> MessageChain.getOrFail(
|
||||
key: MessageKey<M>,
|
||||
@ -200,60 +197,33 @@ public inline fun MessageChain.noneContent(block: (MessageContent) -> Boolean):
|
||||
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
* 获取第一个 [M] 实例. 在不存在时返回 `null`.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline fun <reified M : SingleMessage?> MessageChain.findIsInstance(): M? =
|
||||
this.find { it is M } as M?
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
* 获取第一个 [M] 实例. 在不存在时返回 `null`.
|
||||
* @see findIsInstance
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline fun <reified M : SingleMessage?> MessageChain.firstIsInstanceOrNull(): M? =
|
||||
this.find { it is M } as M?
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
* @throws [NoSuchElementException] 如果找不到该类型的实例
|
||||
* 获取第一个 [M] 实例. 在不存在时抛出 [NoSuchElementException].
|
||||
* @see findIsInstance
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline fun <reified M : SingleMessage> MessageChain.firstIsInstance(): M = this.first { it is M } as M
|
||||
|
||||
/**
|
||||
* 判断 [this] 中是否存在 [Message] 的实例
|
||||
* 当 [this] 中存在 [M] 的实例时返回 `true`.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline fun <reified M : SingleMessage> MessageChain.anyIsInstance(): Boolean = this.any { it is M }
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
*/
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
@Deprecated("Use get", ReplaceWith("get(key)"))
|
||||
@JvmSynthetic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <M : SingleMessage> MessageChain.firstOrNull(key: MessageKey<M>): M? = get(key)
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
* @throws [NoSuchElementException] 如果找不到该类型的实例
|
||||
*/
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
@Deprecated("Use getOrFail", ReplaceWith("getOrFail(key)", "net.mamoe.mirai.message.data.getOrFail"))
|
||||
@JvmSynthetic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <M : SingleMessage> MessageChain.first(key: MessageKey<M>): M =
|
||||
get(key) ?: throw NoSuchElementException("Message type $key not found in chain $this")
|
||||
|
||||
/**
|
||||
* 获取第一个 [M] 类型的 [Message] 实例
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
@JvmSynthetic
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <M : SingleMessage> MessageChain.any(key: MessageKey<M>): Boolean = get(key) != null
|
||||
|
||||
// endregion accessors
|
||||
|
||||
|
||||
@ -279,7 +249,7 @@ public inline operator fun <reified T : SingleMessage> MessageChain.getValue(thi
|
||||
*/
|
||||
@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
|
||||
public inline class OrNullDelegate<out R> @PublishedApi internal constructor(@JvmField @PublishedApi internal val value: Any?) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@Suppress("UNCHECKED_CAST") // don't inline, IC error
|
||||
public operator fun getValue(thisRef: Any?, property: KProperty<*>): R = value as R
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ package net.mamoe.mirai.message.data
|
||||
*
|
||||
* @param M 指代持有这个 Key 的消息类型
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public interface MessageKey<out M : SingleMessage> {
|
||||
/**
|
||||
* 将一个 [SingleMessage] 强转为 [M] 类型. 在类型不符合时返回 `null`
|
||||
@ -36,7 +35,6 @@ public interface MessageKey<out M : SingleMessage> {
|
||||
*
|
||||
* @see AbstractPolymorphicMessageKey
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public abstract class AbstractMessageKey<out M : SingleMessage>(
|
||||
override val safeCast: (SingleMessage) -> M?,
|
||||
) : MessageKey<M>
|
||||
@ -71,7 +69,6 @@ public abstract class AbstractMessageKey<out M : SingleMessage>(
|
||||
* // result 为 [source2], 总是右侧替换左侧
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public abstract class AbstractPolymorphicMessageKey<out B : SingleMessage, out M : B>(
|
||||
baseKey: MessageKey<B>,
|
||||
safeCast: (SingleMessage) -> M?,
|
||||
@ -80,8 +77,9 @@ public abstract class AbstractPolymorphicMessageKey<out B : SingleMessage, out M
|
||||
if (baseKey is AbstractPolymorphicMessageKey<*, *>) baseKey.topmostKey else baseKey
|
||||
}
|
||||
|
||||
|
||||
@ExperimentalMessageKey
|
||||
/**
|
||||
* 尝试 [MessageKey.safeCast], 成功时返回 `true`
|
||||
*/
|
||||
public fun MessageKey<*>.isInstance(message: SingleMessage): Boolean = this.safeCast(message) != null
|
||||
|
||||
/**
|
||||
@ -91,11 +89,8 @@ public fun MessageKey<*>.isInstance(message: SingleMessage): Boolean = this.safe
|
||||
*
|
||||
* 如 [FlashImage], 其 [MessageKey]
|
||||
*/
|
||||
@ExperimentalMessageKey
|
||||
public val <A : SingleMessage> MessageKey<A>.topmostKey: MessageKey<*>
|
||||
get() = when (this) {
|
||||
is AbstractPolymorphicMessageKey<*, *> -> {
|
||||
this.topmostKey
|
||||
}
|
||||
is AbstractPolymorphicMessageKey<*, *> -> this.topmostKey
|
||||
else -> this
|
||||
}
|
@ -70,7 +70,6 @@ import net.mamoe.mirai.utils.safeCast
|
||||
*/
|
||||
@Serializable(MessageSourceSerializerImpl.Companion::class)
|
||||
public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle {
|
||||
@ExperimentalMessageKey
|
||||
public final override val key: MessageKey<MessageSource>
|
||||
get() = Key
|
||||
|
||||
|
@ -43,7 +43,6 @@ import net.mamoe.mirai.utils.safeCast
|
||||
public data class QuoteReply(public val source: MessageSource) : Message, MessageMetadata, ConstrainSingle {
|
||||
public companion object Key : AbstractMessageKey<QuoteReply>({ it.safeCast() })
|
||||
|
||||
@ExperimentalMessageKey
|
||||
public override val key: MessageKey<QuoteReply> get() = Key
|
||||
|
||||
public override fun toString(): String =
|
||||
|
@ -15,7 +15,6 @@ import kotlin.test.assertSame
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
internal class TestConstrainSingleMessage : ConstrainSingle, Any() {
|
||||
companion object Key : AbstractMessageKey<TestConstrainSingleMessage>({ it.safeCast() })
|
||||
|
||||
|
@ -14,7 +14,6 @@ import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
private open class TestStandaloneConstrainSingleMessage : ConstrainSingle, MessageContent {
|
||||
companion object Key : AbstractMessageKey<TestStandaloneConstrainSingleMessage>({ it.safeCast() })
|
||||
|
||||
@ -24,7 +23,6 @@ private open class TestStandaloneConstrainSingleMessage : ConstrainSingle, Messa
|
||||
override val key: MessageKey<TestStandaloneConstrainSingleMessage> get() = Key
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
private class TestPolymorphicConstrainSingleMessage : ConstrainSingle, TestStandaloneConstrainSingleMessage(),
|
||||
MessageContent {
|
||||
companion object Key :
|
||||
@ -38,7 +36,6 @@ private class TestPolymorphicConstrainSingleMessage : ConstrainSingle, TestStand
|
||||
override val key: MessageKey<TestPolymorphicConstrainSingleMessage> get() = Key
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
private class TestPolymorphicConstrainSingleMessageOverridingMessageContent : ConstrainSingle, MessageContent,
|
||||
TestStandaloneConstrainSingleMessage() {
|
||||
companion object Key :
|
||||
@ -56,7 +53,6 @@ private class TestPolymorphicConstrainSingleMessageOverridingMessageContent : Co
|
||||
|
||||
|
||||
internal class MessageKeyTest {
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
@Test
|
||||
fun `test polymorphism get`() {
|
||||
val constrainSingle: TestStandaloneConstrainSingleMessage
|
||||
@ -72,7 +68,6 @@ internal class MessageKeyTest {
|
||||
assertEquals(constrainSingle, chain[TestStandaloneConstrainSingleMessage])
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
@Test
|
||||
fun `test polymorphism override base`() {
|
||||
val constrainSingle: TestPolymorphicConstrainSingleMessage
|
||||
@ -88,7 +83,6 @@ internal class MessageKeyTest {
|
||||
assertEquals(constrainSingle, chain[TestPolymorphicConstrainSingleMessage])
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMessageKey::class)
|
||||
@Test
|
||||
fun `test polymorphism override message content`() {
|
||||
val constrainSingle: TestPolymorphicConstrainSingleMessageOverridingMessageContent
|
||||
|
@ -22,7 +22,6 @@ internal class TestConstrainSingleMessage : ConstrainSingle, Any() {
|
||||
override fun toString(): String = "<TestConstrainSingleMessage#${super.hashCode()}>"
|
||||
override fun contentToString(): String = ""
|
||||
|
||||
@ExperimentalMessageKey
|
||||
override val key: MessageKey<TestConstrainSingleMessage>
|
||||
get() = Key
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user