Commit b64b1da6 authored by Him188's avatar Him188

Make MessageChain implement `List<SingleMessage>`;

Hide relevant APIs on `Iterable`;
Deprecate `__forEachForJava__` in favor of Java 8 API;
Add `fun messageChainOf(vararg messages: Message): MessageChain`;
Add `fun Array<out Message>.asMessageChain(): MessageChain`;
Add `fun Array<out SingleMessage>.asMessageChain(): MessageChain`;
Add `fun Array<out Message>.flatten(): Sequence<SingleMessage>`;
Add `fun Array<out SingleMessage>.flatten(): Sequence<SingleMessage>`;
Close #312
parent 97334902
...@@ -13,11 +13,10 @@ ...@@ -13,11 +13,10 @@
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.PlannedRemoval
import kotlin.jvm.JvmField import kotlin.jvm.JvmField
import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/** /**
* 快速链接的两个消息 (避免构造新的 list). * 快速链接的两个消息 (避免构造新的 list).
...@@ -33,26 +32,23 @@ internal class CombinedMessage ...@@ -33,26 +32,23 @@ internal class CombinedMessage
internal constructor( internal constructor(
@JvmField internal val left: Message, // 必须已经完成 constrain single @JvmField internal val left: Message, // 必须已经完成 constrain single
@JvmField internal val tail: Message @JvmField internal val tail: Message
) : Message, MessageChain { ) : Message, MessageChain, List<SingleMessage> by (left.flatten() + tail.flatten()).toList() {
fun asSequence(): Sequence<SingleMessage> = sequence { @PlannedRemoval("1.2.0")
yieldCombinedOrElementsFlatten(this@CombinedMessage) @Deprecated(
} "use asSequence from stdlib",
ReplaceWith("(this as List<SingleMessage>).asSequence()"),
override fun iterator(): Iterator<SingleMessage> { level = DeprecationLevel.HIDDEN
return asSequence().iterator() )
} @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.LowPriorityInOverloadResolution // resolve to extension from stdlib
override val size: Int fun asSequence(): Sequence<SingleMessage> = (this as List<SingleMessage>).asSequence()
get() = kotlin.run {
var size = 0
size += if (left is MessageChain) left.size else 1
size += if (tail is MessageChain) tail.size else 1
size
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
return other is CombinedMessage && other.left == this.left && other.tail == this.tail if (other == null) return false
if (other::class != CombinedMessage::class) return false
other as CombinedMessage
return other.left == this.left && other.tail == this.tail
} }
private var toStringCache: String? = null private var toStringCache: String? = null
...@@ -71,6 +67,7 @@ internal constructor( ...@@ -71,6 +67,7 @@ internal constructor(
} }
} }
/*
@JvmSynthetic @JvmSynthetic
// 不要把它用作 local function, 会编译错误 // 不要把它用作 local function, 会编译错误
@OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class) @OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class)
...@@ -93,3 +90,4 @@ private suspend fun SequenceScope<SingleMessage>.yieldCombinedOrElementsFlatten( ...@@ -93,3 +90,4 @@ private suspend fun SequenceScope<SingleMessage>.yieldCombinedOrElementsFlatten(
} }
} }
} }
*/
\ No newline at end of file
...@@ -196,6 +196,7 @@ fun Iterable<MessageEvent>.toForwardMessage(displayStrategy: DisplayStrategy = D ...@@ -196,6 +196,7 @@ fun Iterable<MessageEvent>.toForwardMessage(displayStrategy: DisplayStrategy = D
/** /**
* 转换为 [ForwardMessage] * 转换为 [ForwardMessage]
*/ */
@JvmOverloads
fun Message.toForwardMessage( fun Message.toForwardMessage(
sender: User, sender: User,
time: Int = currentTimeSeconds.toInt(), time: Int = currentTimeSeconds.toInt(),
......
...@@ -33,6 +33,10 @@ import kotlin.reflect.KProperty ...@@ -33,6 +33,10 @@ import kotlin.reflect.KProperty
* 要获取更多消息相关的信息, 查看 [Message] * 要获取更多消息相关的信息, 查看 [Message]
* *
* ### 构造消息链 * ### 构造消息链
* - [buildMessageChain]: 使用构建器
* - [Message.plus]: 将两个消息相连成为一个消息链
* - [asMessageChain] 将 [Iterable], 等类型消息
* - [messageChainOf] 类似 [listOf], 将多个 [Message] 构造为 [MessageChain]
* *
* ### 消息链如何工作 * ### 消息链如何工作
* - [SingleMessageChainImpl] 将 [单个消息][SingleMessage] 委托为一个 [MessageChain] * - [SingleMessageChainImpl] 将 [单个消息][SingleMessage] 委托为一个 [MessageChain]
...@@ -54,7 +58,8 @@ import kotlin.reflect.KProperty ...@@ -54,7 +58,8 @@ import kotlin.reflect.KProperty
* @see getValue 属性委托扩展 * @see getValue 属性委托扩展
* @see flatten 扁平化 * @see flatten 扁平化
*/ */
interface MessageChain : Message, Iterable<SingleMessage> { @Suppress("FunctionName", "DeprecatedCallableAddReplaceWith", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
interface MessageChain : Message, List<SingleMessage>, RandomAccess {
/** /**
* 元素数量. [EmptyMessageChain] 不参加计数. * 元素数量. [EmptyMessageChain] 不参加计数.
*/ */
...@@ -72,35 +77,22 @@ interface MessageChain : Message, Iterable<SingleMessage> { ...@@ -72,35 +77,22 @@ interface MessageChain : Message, Iterable<SingleMessage> {
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face] 等 * 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face] 等
* 仅供 `Java` 使用 * 仅供 `Java` 使用
*/ */
@Suppress("FunctionName")
@JsName("forEachContent")
@JvmName("forEachContent") @JvmName("forEachContent")
@JavaFriendlyAPI @JavaFriendlyAPI
final fun __forEachContentForJava__(block: (Message) -> Unit) { final fun __forEachContentForJava__(block: (Message) -> Unit) = this.forEachContent(block)
this.forEachContent(block)
}
/**
* 遍历每一个消息, 即 [MessageSource] [At], [AtAll], [PlainText], [Image], [QuoteReply] 等 @PlannedRemoval("1.1.0")
* 仅供 `Java` 使用 @Deprecated("use Java 8 API", level = DeprecationLevel.HIDDEN)
*/
@Suppress("FunctionName")
@JsName("forEach")
@JvmName("forEach") @JvmName("forEach")
@JavaFriendlyAPI @JavaFriendlyAPI
final fun __forEachForJava__(block: (Message) -> Unit) { @JvmSynthetic
this.forEach(block) @kotlin.internal.LowPriorityInOverloadResolution
} final fun __forEachForJava__(block: (Message) -> Unit) = this.forEach(block)
/**
* 获取第一个类型为 [key] 的 [Message] 实例, 找不到则返回 `null`
*
* @param key 由各个类型消息的伴生对象持有. 如 [PlainText.Key]
*/
@PlannedRemoval("1.2.0") @PlannedRemoval("1.2.0")
@JvmName("firstOrNull") @JvmName("firstOrNull")
@Deprecated("use get", ReplaceWith("get(key)")) @Deprecated("use get instead. This is going to be removed in mirai 1.2.0", ReplaceWith("get(key)"))
final fun <M : Message> getOrNull(key: Message.Key<M>): M? = get(key) final fun <M : Message> getOrNull(key: Message.Key<M>): M? = get(key)
} }
...@@ -271,6 +263,13 @@ inline fun <reified T : Message?> MessageChain.orElse( ...@@ -271,6 +263,13 @@ inline fun <reified T : Message?> MessageChain.orElse(
// region asMessageChain // region asMessageChain
/**
* 返回一个包含 [messages] 所有元素的消息链, 保留顺序.
*/
@JvmName("newChain")
inline fun messageChainOf(vararg messages: Message): MessageChain = messages.asMessageChain()
/** /**
* 得到包含 [this] 的 [MessageChain]. * 得到包含 [this] 的 [MessageChain].
* *
...@@ -301,6 +300,18 @@ fun SingleMessage.asMessageChain(): MessageChain = SingleMessageChainImpl(this) ...@@ -301,6 +300,18 @@ fun SingleMessage.asMessageChain(): MessageChain = SingleMessageChainImpl(this)
fun Collection<SingleMessage>.asMessageChain(): MessageChain = fun Collection<SingleMessage>.asMessageChain(): MessageChain =
MessageChainImplByCollection(this.constrainSingleMessages()) MessageChainImplByCollection(this.constrainSingleMessages())
/**
* 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain]
*/
@JvmSynthetic
@JvmName("newChain1")
// @JsName("newChain")
fun Array<out Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
@JvmSynthetic
@JvmName("newChain2")
fun Array<out SingleMessage>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.asSequence())
/** /**
* 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain] * 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain]
*/ */
...@@ -316,7 +327,7 @@ fun Iterable<SingleMessage>.asMessageChain(): MessageChain = ...@@ -316,7 +327,7 @@ fun Iterable<SingleMessage>.asMessageChain(): MessageChain =
MessageChainImplByCollection(this.constrainSingleMessages()) MessageChainImplByCollection(this.constrainSingleMessages())
@JvmSynthetic @JvmSynthetic
fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃 inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
/** /**
* 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain] * 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain]
...@@ -338,15 +349,6 @@ fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplByS ...@@ -338,15 +349,6 @@ fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplByS
// @JsName("newChain") // @JsName("newChain")
fun Sequence<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten()) fun Sequence<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
/**
* 构造一个 [MessageChain]
* 为提供更好的 Java API.
*/
@Suppress("FunctionName")
@JvmName("newChain")
fun _____newChain______(vararg messages: Message): MessageChain {
return messages.asIterable().asMessageChain()
}
/** /**
* 构造一个 [MessageChain] * 构造一个 [MessageChain]
...@@ -396,6 +398,10 @@ inline fun Sequence<Message>.flatten(): Sequence<SingleMessage> = flatMap { it.f ...@@ -396,6 +398,10 @@ inline fun Sequence<Message>.flatten(): Sequence<SingleMessage> = flatMap { it.f
@JvmSynthetic @JvmSynthetic
inline fun Sequence<SingleMessage>.flatten(): Sequence<SingleMessage> = this // fast path inline fun Sequence<SingleMessage>.flatten(): Sequence<SingleMessage> = this // fast path
inline fun Array<out Message>.flatten(): Sequence<SingleMessage> = this.asSequence().flatten()
inline fun Array<out SingleMessage>.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
/** /**
* 扁平化 [Message] * 扁平化 [Message]
* *
......
...@@ -33,7 +33,7 @@ import kotlin.jvm.JvmSynthetic ...@@ -33,7 +33,7 @@ import kotlin.jvm.JvmSynthetic
* *
* *
* ### 组成 * ### 组成
* MessageSource 由 metadata (元数据), form & target, content 组成 * [MessageSource] 由 metadata (元数据), form & target, content 组成
* *
* #### metadata * #### metadata
* - [id] 消息 id (序列号) * - [id] 消息 id (序列号)
......
...@@ -245,8 +245,8 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M? ...@@ -245,8 +245,8 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M?
* 使用 [Collection] 作为委托的 [MessageChain] * 使用 [Collection] 作为委托的 [MessageChain]
*/ */
internal class MessageChainImplByCollection constructor( internal class MessageChainImplByCollection constructor(
internal val delegate: Collection<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable internal val delegate: List<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable
) : Message, Iterable<SingleMessage>, MessageChain { ) : Message, MessageChain, List<SingleMessage> by delegate {
override val size: Int get() = delegate.size override val size: Int get() = delegate.size
override fun iterator(): Iterator<SingleMessage> = delegate.iterator() override fun iterator(): Iterator<SingleMessage> = delegate.iterator()
...@@ -266,15 +266,7 @@ internal class MessageChainImplByCollection constructor( ...@@ -266,15 +266,7 @@ internal class MessageChainImplByCollection constructor(
*/ */
internal class MessageChainImplBySequence constructor( internal class MessageChainImplBySequence constructor(
delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle
) : Message, Iterable<SingleMessage>, MessageChain { ) : Message, Iterable<SingleMessage>, MessageChain, List<SingleMessage> by delegate.constrainSingleMessages() {
override val size: Int by lazy { collected.size }
/**
* [Sequence] 可能只能消耗一遍, 因此需要先转为 [List]
*/
private val collected: List<SingleMessage> by lazy { delegate.constrainSingleMessages() }
override fun iterator(): Iterator<SingleMessage> = collected.iterator()
private var toStringTemp: String? = null private var toStringTemp: String? = null
get() = field ?: this.joinToString("") { it.toString() }.also { field = it } get() = field ?: this.joinToString("") { it.toString() }.also { field = it }
...@@ -291,11 +283,9 @@ internal class MessageChainImplBySequence constructor( ...@@ -291,11 +283,9 @@ internal class MessageChainImplBySequence constructor(
*/ */
internal class SingleMessageChainImpl constructor( internal class SingleMessageChainImpl constructor(
internal val delegate: SingleMessage internal val delegate: SingleMessage
) : Message, Iterable<SingleMessage>, MessageChain { ) : Message, MessageChain, List<SingleMessage> by listOf(delegate) {
override val size: Int get() = 1
override fun toString(): String = this.delegate.toString() override fun toString(): String = this.delegate.toString()
override fun contentToString(): String = this.delegate.contentToString() override fun contentToString(): String = this.delegate.contentToString()
override fun iterator(): Iterator<SingleMessage> = iterator { yield(delegate) }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment