1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-25 04:50:26 +08:00

Stable MessageKey

This commit is contained in:
Him188 2020-12-27 23:04:16 +08:00
parent b2f0424418
commit 16e4bde07e
9 changed files with 12 additions and 76 deletions
mirai-core-api/src
mirai-core/src/jvmTest/kotlin

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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 =

View File

@ -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() })

View File

@ -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

View File

@ -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
}