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
This commit is contained in:
Him188 2020-05-09 14:54:25 +08:00
parent 9733490266
commit b64b1da666
5 changed files with 61 additions and 66 deletions

View File

@ -13,11 +13,10 @@
package net.mamoe.mirai.message.data
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.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 快速链接的两个消息 (避免构造新的 list).
@ -33,26 +32,23 @@ internal class CombinedMessage
internal constructor(
@JvmField internal val left: Message, // 必须已经完成 constrain single
@JvmField internal val tail: Message
) : Message, MessageChain {
) : Message, MessageChain, List<SingleMessage> by (left.flatten() + tail.flatten()).toList() {
fun asSequence(): Sequence<SingleMessage> = sequence {
yieldCombinedOrElementsFlatten(this@CombinedMessage)
}
override fun iterator(): Iterator<SingleMessage> {
return asSequence().iterator()
}
override val size: Int
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
}
@PlannedRemoval("1.2.0")
@Deprecated(
"use asSequence from stdlib",
ReplaceWith("(this as List<SingleMessage>).asSequence()"),
level = DeprecationLevel.HIDDEN
)
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.LowPriorityInOverloadResolution // resolve to extension from stdlib
fun asSequence(): Sequence<SingleMessage> = (this as List<SingleMessage>).asSequence()
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
@ -71,6 +67,7 @@ internal constructor(
}
}
/*
@JvmSynthetic
// 不要把它用作 local function, 会编译错误
@OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class)
@ -93,3 +90,4 @@ private suspend fun SequenceScope<SingleMessage>.yieldCombinedOrElementsFlatten(
}
}
}
*/

View File

@ -196,6 +196,7 @@ fun Iterable<MessageEvent>.toForwardMessage(displayStrategy: DisplayStrategy = D
/**
* 转换为 [ForwardMessage]
*/
@JvmOverloads
fun Message.toForwardMessage(
sender: User,
time: Int = currentTimeSeconds.toInt(),

View File

@ -33,6 +33,10 @@ import kotlin.reflect.KProperty
* 要获取更多消息相关的信息, 查看 [Message]
*
* ### 构造消息链
* - [buildMessageChain]: 使用构建器
* - [Message.plus]: 将两个消息相连成为一个消息链
* - [asMessageChain] [Iterable], 等类型消息
* - [messageChainOf] 类似 [listOf], 将多个 [Message] 构造为 [MessageChain]
*
* ### 消息链如何工作
* - [SingleMessageChainImpl] [单个消息][SingleMessage] 委托为一个 [MessageChain]
@ -54,7 +58,8 @@ import kotlin.reflect.KProperty
* @see getValue 属性委托扩展
* @see flatten 扁平化
*/
interface MessageChain : Message, Iterable<SingleMessage> {
@Suppress("FunctionName", "DeprecatedCallableAddReplaceWith", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
interface MessageChain : Message, List<SingleMessage>, RandomAccess {
/**
* 元素数量. [EmptyMessageChain] 不参加计数.
*/
@ -72,35 +77,22 @@ interface MessageChain : Message, Iterable<SingleMessage> {
* 遍历每一个有内容的消息, [At], [AtAll], [PlainText], [Image], [Face]
* 仅供 `Java` 使用
*/
@Suppress("FunctionName")
@JsName("forEachContent")
@JvmName("forEachContent")
@JavaFriendlyAPI
final fun __forEachContentForJava__(block: (Message) -> Unit) {
this.forEachContent(block)
}
final fun __forEachContentForJava__(block: (Message) -> Unit) = this.forEachContent(block)
/**
* 遍历每一个消息, [MessageSource] [At], [AtAll], [PlainText], [Image], [QuoteReply]
* 仅供 `Java` 使用
*/
@Suppress("FunctionName")
@JsName("forEach")
@PlannedRemoval("1.1.0")
@Deprecated("use Java 8 API", level = DeprecationLevel.HIDDEN)
@JvmName("forEach")
@JavaFriendlyAPI
final fun __forEachForJava__(block: (Message) -> Unit) {
this.forEach(block)
}
@JvmSynthetic
@kotlin.internal.LowPriorityInOverloadResolution
final fun __forEachForJava__(block: (Message) -> Unit) = this.forEach(block)
/**
* 获取第一个类型为 [key] [Message] 实例, 找不到则返回 `null`
*
* @param key 由各个类型消息的伴生对象持有. [PlainText.Key]
*/
@PlannedRemoval("1.2.0")
@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)
}
@ -271,6 +263,13 @@ inline fun <reified T : Message?> MessageChain.orElse(
// region asMessageChain
/**
* 返回一个包含 [messages] 所有元素的消息链, 保留顺序.
*/
@JvmName("newChain")
inline fun messageChainOf(vararg messages: Message): MessageChain = messages.asMessageChain()
/**
* 得到包含 [this] [MessageChain].
*
@ -301,6 +300,18 @@ fun SingleMessage.asMessageChain(): MessageChain = SingleMessageChainImpl(this)
fun Collection<SingleMessage>.asMessageChain(): MessageChain =
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]
*/
@ -316,7 +327,7 @@ fun Iterable<SingleMessage>.asMessageChain(): MessageChain =
MessageChainImplByCollection(this.constrainSingleMessages())
@JvmSynthetic
fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
/**
* [this] [扁平化后][flatten] 委托为一个 [MessageChain]
@ -338,15 +349,6 @@ fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplByS
// @JsName("newChain")
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]
@ -396,6 +398,10 @@ inline fun Sequence<Message>.flatten(): Sequence<SingleMessage> = flatMap { it.f
@JvmSynthetic
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]
*

View File

@ -33,7 +33,7 @@ import kotlin.jvm.JvmSynthetic
*
*
* ### 组成
* MessageSource metadata (元数据), form & target, content 组成
* [MessageSource] metadata (元数据), form & target, content 组成
*
* #### metadata
* - [id] 消息 id (序列号)

View File

@ -245,8 +245,8 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M?
* 使用 [Collection] 作为委托的 [MessageChain]
*/
internal class MessageChainImplByCollection constructor(
internal val delegate: Collection<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable
) : Message, Iterable<SingleMessage>, MessageChain {
internal val delegate: List<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable
) : Message, MessageChain, List<SingleMessage> by delegate {
override val size: Int get() = delegate.size
override fun iterator(): Iterator<SingleMessage> = delegate.iterator()
@ -266,15 +266,7 @@ internal class MessageChainImplByCollection constructor(
*/
internal class MessageChainImplBySequence constructor(
delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle
) : Message, Iterable<SingleMessage>, MessageChain {
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()
) : Message, Iterable<SingleMessage>, MessageChain, List<SingleMessage> by delegate.constrainSingleMessages() {
private var toStringTemp: String? = null
get() = field ?: this.joinToString("") { it.toString() }.also { field = it }
@ -291,11 +283,9 @@ internal class MessageChainImplBySequence constructor(
*/
internal class SingleMessageChainImpl constructor(
internal val delegate: SingleMessage
) : Message, Iterable<SingleMessage>, MessageChain {
override val size: Int get() = 1
) : Message, MessageChain, List<SingleMessage> by listOf(delegate) {
override fun toString(): String = this.delegate.toString()
override fun contentToString(): String = this.delegate.contentToString()
override fun iterator(): Iterator<SingleMessage> = iterator { yield(delegate) }
}