From 1eba1214c3b84a40cd23db0a6cf1c33f1a2b5f80 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Thu, 10 Dec 2020 14:26:13 +0800
Subject: [PATCH] Improve docs

---
 .../commonMain/kotlin/message/data/Message.kt | 50 ++++++++++++++++---
 .../mamoe/mirai/message/data/MessageKey.kt    | 29 +++++------
 2 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Message.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Message.kt
index 2fb810661..54bf5f83f 100644
--- a/mirai-core-api/src/commonMain/kotlin/message/data/Message.kt
+++ b/mirai-core-api/src/commonMain/kotlin/message/data/Message.kt
@@ -300,28 +300,64 @@ public interface MessageMetadata : SingleMessage {
  * 约束一个 [MessageChain] 中只存在这一种类型的元素. 新元素将会替换旧元素, 保持原顺序.
  *
  * 实现此接口的元素将会在连接时自动处理替换.
+ *
+ * @see AbstractMessageKey
+ * @see AbstractPolymorphicMessageKey
+ *
+ * @see MessageSource
  */
 @ExperimentalMessageKey
 public interface ConstrainSingle : SingleMessage {
     /**
-     * 用于判断是否为同一种元素的 [MessageKey]
+     * 用于判断是否为同一种元素的 [MessageKey]. 使用多态类型 [MessageKey] 最上层的 [MessageKey].
      * @see MessageKey 查看更多信息
      */
     @ExperimentalMessageKey
     public val key: MessageKey<*>
 }
 
+/**
+ * 独立的 [MessageKey] 的实现. '独立' 即 `final`, 不支持多态类型. 适用于作为最顶层的 [MessageKey], 如 [MessageSource].
+ *
+ * @see AbstractPolymorphicMessageKey
+ */
 @ExperimentalMessageKey
 public abstract class AbstractMessageKey<out M : SingleMessage>(
     override val safeCast: (SingleMessage) -> M?,
-) : MessageKey<M> {
-    internal fun tryCast(element: SingleMessage): M? = safeCast(element)
-    internal open fun isSubKey(key: MessageKey<*>): Boolean = key === this
-}
+) : MessageKey<M>
 
+/**
+ * 多态 [MessageKey].
+ *
+ * 示例: [HummerMessage]
+ * ```
+ *               MessageContent
+ *                     ↑
+ *               HummerMessage
+ *                     ↑
+ *        +------------+-------------+
+ *        |            |             |
+ *  PokeMessage     VipFace      FlashImage
+ *
+ * ```
+ *
+ * 当 [连接][Message.plus] 一个 [VipFace] 到一个 [MessageChain] 时,
+ * 由于 [VipFace] 最上层为 [MessageContent], 消息链中第一个 [MessageContent] 会被 (保留顺序地) 替换为 [VipFace], 其他所有 [MessageContent] 都会被删除.
+ *
+ * 如:
+ * ```
+ * val source: MessageSource = ...
+ *
+ * val result = messageChainOf(PlainText("a"), PlainText("b"), source, AtAll) + VipFace.LiuLian
+ * // result 为 [VipFace.LiuLian, source]
+ *
+ * val result = source1 + source2
+ * // result 为 [source2], 总是右侧替换左侧
+ * ```
+ */
 @ExperimentalMessageKey
 public abstract class AbstractPolymorphicMessageKey<out B : SingleMessage, out M : B>(
-    public val baseKey: MessageKey<B>,
+    baseKey: MessageKey<B>,
     safeCast: (SingleMessage) -> M?,
 ) : MessageKey<M>, AbstractMessageKey<M>(safeCast) {
     internal val topmostKey: MessageKey<*> =
@@ -329,7 +365,7 @@ public abstract class AbstractPolymorphicMessageKey<out B : SingleMessage, out M
 }
 
 /**
- * 消息内容
+ * 带内容的消息.
  *
  * @see PlainText 纯文本
  * @see At At 一个群成员.
diff --git a/mirai-core-api/src/commonMain/kotlin/net/mamoe/mirai/message/data/MessageKey.kt b/mirai-core-api/src/commonMain/kotlin/net/mamoe/mirai/message/data/MessageKey.kt
index 0572857c8..97c1ff8d3 100644
--- a/mirai-core-api/src/commonMain/kotlin/net/mamoe/mirai/message/data/MessageKey.kt
+++ b/mirai-core-api/src/commonMain/kotlin/net/mamoe/mirai/message/data/MessageKey.kt
@@ -12,42 +12,39 @@ package net.mamoe.mirai.message.data
 /**
  * 类型 Key. 由伴生对象实现, 表示一个 [Message] 对象的类型.
  *
- * 除 [MessageChain] 外, 每个 [Message] 类型都拥有一个伴生对象 (companion object) 来持有一个 Key
- *
- * 在 [MessageChain.get] 时将会使用到这个 Key 进行判断类型.
+ * 每个 [ConstrainSingle] 类型都拥有一个伴生对象来持有 [MessageKey] 以允许 `val source = chain[MessageSource]` 的用法.
  *
  * #### 用例
  * [MessageChain.get][MessageChain.get]: 允许使用数组访问操作符获取指定类型的消息元素
  * ```
- * val image: Image = chain[Image]
+ * val source: MessageSource = chain[MessageSource]
  * ```
  *
  * @param M 指代持有这个 Key 的消息类型
  */
 @ExperimentalMessageKey
 public interface MessageKey<out M : SingleMessage> {
+    /**
+     * 将一个 [SingleMessage] 强转为 [M] 类型. 在类型不符合时返回 `null`
+     */
     public val safeCast: (SingleMessage) -> M?
 }
 
 @ExperimentalMessageKey
 public fun MessageKey<*>.isInstance(message: SingleMessage): Boolean = this.safeCast(message) != null
 
-@ExperimentalMessageKey
-public tailrec fun <A : SingleMessage, B : SingleMessage> MessageKey<A>.isSubKeyOf(baseKey: MessageKey<B>): Boolean {
-    return when {
-        this === baseKey -> true
-        this is AbstractPolymorphicMessageKey<*, *> -> {
-            this.baseKey.isSubKeyOf(baseKey)
-        }
-        else -> false
-    }
-}
-
+/**
+ * 获取最上层 [MessageKey].
+ *
+ * 当 [this][MessageKey] 为 [AbstractPolymorphicMessageKey]
+ *
+ * 如 [FlashImage], 其 [MessageKey]
+ */
 @ExperimentalMessageKey
 public val <A : SingleMessage> MessageKey<A>.topmostKey: MessageKey<*>
     get() = when (this) {
         is AbstractPolymorphicMessageKey<*, *> -> {
-            this.baseKey.topmostKey
+            this.topmostKey
         }
         else -> this
     }
\ No newline at end of file