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

[Review] MessageChain: rename asMessageChain to toMessageChain, remove flatten

This commit is contained in:
Him188 2021-01-07 20:49:37 +08:00
parent 46e0cda7a7
commit 43b422b540
3 changed files with 315 additions and 169 deletions
mirai-core-api/src/commonMain/kotlin/message/data

View File

@ -13,6 +13,8 @@
package net.mamoe.mirai.message.data
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
@ -25,8 +27,9 @@ import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.MessageSource.Key.quote
import net.mamoe.mirai.message.data.MessageSource.Key.recall
import net.mamoe.mirai.utils.safeCast
import kotlin.js.JsName
import java.util.stream.Stream
import kotlin.reflect.KProperty
import kotlin.streams.asSequence
/**
* 消息链. 空的实现为 [EmptyMessageChain]
@ -36,7 +39,7 @@ import kotlin.reflect.KProperty
* ### 构造消息链
* - [buildMessageChain][buildMessageChain]: 使用构建器
* - [Message.plus][Message.plus]: 将两个消息相连成为一个消息链
* - [asMessageChain][asMessageChain] [Iterable], [Array] 等类型消息转换为 [MessageChain]
* - [toMessageChain][toMessageChain] [Iterable], [Array] 等类型转换为 [MessageChain]
* - [messageChainOf][messageChainOf] 类似 [listOf], 将多个 [Message] 构造为 [MessageChain]
*
* @see get 获取消息链中一个类型的元素, 不存在时返回 `null`
@ -45,8 +48,8 @@ import kotlin.reflect.KProperty
* @see MessageSource.recall 撤回这条消息 (仅限来自 [MessageEvent] 的消息)
*
* @see buildMessageChain 构造一个 [MessageChain]
* @see asMessageChain 将单个 [Message] 转换为 [MessageChain]
* @see asMessageChain [Iterable] [Sequence] 委托为 [MessageChain]
* @see Message.toMessageChain 将单个 [Message] 转换为 [MessageChain]
* @see toMessageChain [Iterable] [Sequence] 委托为 [MessageChain]
*
* @see forEachContent 遍历内容
* @see allContent 判断是否每一个 [MessageContent] 都满足条件
@ -98,7 +101,7 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
@Suppress("DEPRECATION_ERROR")
private val delegate = ListSerializer(PolymorphicSerializer(SingleMessage::class))
override val descriptor: SerialDescriptor = delegate.descriptor
override fun deserialize(decoder: Decoder): MessageChain = delegate.deserialize(decoder).asMessageChain()
override fun deserialize(decoder: Decoder): MessageChain = delegate.deserialize(decoder).toMessageChain()
override fun serialize(encoder: Encoder, value: MessageChain): Unit = delegate.serialize(encoder, value)
}
@ -151,6 +154,22 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
}
}
/**
* 不含任何元素的 [MessageChain].
*/
public object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, List<SingleMessage> by emptyList() {
public override val size: Int get() = 0
public override fun toString(): String = ""
public override fun contentToString(): String = ""
public override fun equals(other: Any?): Boolean = other === this
public override fun iterator(): Iterator<SingleMessage> = this
public override fun hasNext(): Boolean = false
public override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.")
override fun toMiraiCode(): String = ""
override fun appendMiraiCode(builder: StringBuilder) {}
}
// region accessors
/**
@ -238,6 +257,66 @@ public inline fun <reified M : SingleMessage> MessageChain.anyIsInstance(): Bool
// endregion accessors
// region toMessageChain
/**
* 返回一个包含 [messages] 所有元素的消息链, 保留顺序.
* @see buildMessageChain
*/
@JvmName("newChain")
public inline fun messageChainOf(vararg messages: Message): MessageChain = messages.toMessageChain()
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public fun Sequence<Message>.toMessageChain(): MessageChain = MessageChainImpl(this.constrainSingleMessages())
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public fun Stream<Message>.toMessageChain(): MessageChain = this.asSequence().toMessageChain()
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public suspend fun Flow<Message>.toMessageChain(): MessageChain =
buildMessageChain { collect(::add) }
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public inline fun Iterable<Message>.toMessageChain(): MessageChain = this.asSequence().toMessageChain()
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmName("newChain")
public inline fun Iterator<Message>.toMessageChain(): MessageChain = this.asSequence().toMessageChain()
/**
* 扁平化 [this] 并创建一个 [MessageChain].
*/
@JvmSynthetic
// no JvmName because 'fun messageChainOf(vararg messages: Message)'
public inline fun Array<out Message>.toMessageChain(): MessageChain = this.asSequence().toMessageChain()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNCHECKED_CAST")
@kotlin.internal.LowPriorityInOverloadResolution // prefer Iterable<Message>.toMessageChain() for MessageChain
@JvmName("newChain")
public fun Message.toMessageChain(): MessageChain = when (this) {
is MessageChain -> (this as List<SingleMessage>).toMessageChain()
else -> MessageChainImpl(
listOf(
this as? SingleMessage ?: error("Message is either MessageChain nor SingleMessage: $this")
)
)
}
// region delegate
/**
@ -299,160 +378,3 @@ public inline fun <reified T : R, R : SingleMessage?> MessageChain.orElse(
): OrNullDelegate<R> = OrNullDelegate<R>(this.firstIsInstanceOrNull<T>() ?: lazyDefault())
// endregion delegate
// region asMessageChain
/**
* 返回一个包含 [messages] 所有元素的消息链, 保留顺序.
*/
@JvmName("newChain")
public inline fun messageChainOf(vararg messages: Message): MessageChain = messages.asMessageChain()
/**
* 得到包含 [this] [MessageChain].
*/
@JvmName("newChain")
@JsName("newChain")
@Suppress("UNCHECKED_CAST")
public fun Message.asMessageChain(): MessageChain = when (this) {
is MessageChain -> this
else -> SingleMessageChainImpl(this as SingleMessage)
}
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
public fun SingleMessage.asMessageChain(): MessageChain = SingleMessageChainImpl(this)
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
public fun Collection<SingleMessage>.asMessageChain(): MessageChain =
MessageChainImpl(this.constrainSingleMessages())
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@JvmName("newChain1")
// @JsName("newChain")
public fun Array<out Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
@JvmSynthetic
@JvmName("newChain2")
public fun Array<out SingleMessage>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.asSequence())
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmName("newChain")
// @JsName("newChain")
public fun Collection<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
public fun Iterable<SingleMessage>.asMessageChain(): MessageChain =
MessageChainImpl(this.constrainSingleMessages())
@JvmSynthetic
public inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmName("newChain")
// @JsName("newChain")
public fun Iterable<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
public fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplBySequence(this)
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmName("newChain")
// @JsName("newChain")
public fun Sequence<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
/**
* 扁平化消息序列.
*
* [this]:
* ```
* A <- MessageChain(B, C) <- D <- MessageChain(E, F, G)
* ```
* 结果 [Sequence]:
* ```
* A <- B <- C <- D <- E <- F <- G
* ```
*/
public inline fun Iterable<Message>.flatten(): Sequence<SingleMessage> = asSequence().flatten()
// @JsName("flatten1")
@JvmName("flatten1")// avoid platform declare clash
@JvmSynthetic
public inline fun Iterable<SingleMessage>.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
/**
* 扁平化消息序列.
*
* [this]:
* ```
* A <- MessageChain(B, C) <- D <- MessageChain(E, F, G)
* ```
* 结果 [Sequence]:
* ```
* A <- B <- C <- D <- E <- F <- G
* ```
*/
public inline fun Sequence<Message>.flatten(): Sequence<SingleMessage> = flatMap { it.flatten() }
@JsName("flatten1") // avoid platform declare clash
@JvmName("flatten1")
@JvmSynthetic
public inline fun Sequence<SingleMessage>.flatten(): Sequence<SingleMessage> = this // fast path
public inline fun Array<out Message>.flatten(): Sequence<SingleMessage> = this.asSequence().flatten()
public inline fun Array<out SingleMessage>.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
/**
* 返回 [MessageChain.asSequence] `sequenceOf(this as SingleMessage)`
*/
public fun Message.flatten(): Sequence<SingleMessage> {
return when (this) {
is MessageChain -> this.asSequence()
else -> sequenceOf(this as SingleMessage)
}
}
@JvmSynthetic // make Java user happier with less methods
public inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
// endregion converters
/**
* 不含任何元素的 [MessageChain].
*/
public object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, List<SingleMessage> by emptyList() {
public override val size: Int get() = 0
public override fun toString(): String = ""
public override fun contentToString(): String = ""
public override fun equals(other: Any?): Boolean = other === this
public override fun iterator(): Iterator<SingleMessage> = this
public override fun hasNext(): Boolean = false
public override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.")
override fun toMiraiCode(): String = ""
override fun appendMiraiCode(builder: StringBuilder) {}
}

View File

@ -66,7 +66,7 @@ internal fun Message.contentEqualsStrictImpl(another: Message, ignoreCase: Boole
@JvmSynthetic
internal fun Message.followedByImpl(tail: Message): MessageChain {
return MessageChainImplBySequence(this.flatten() + tail.flatten())
return MessageChainImplBySequence(this.toMessageChain().asSequence() + tail.toMessageChain().asSequence())
/*
when {
this is SingleMessage && tail is SingleMessage -> {
@ -113,7 +113,7 @@ internal fun Message.followedByImpl(tail: Message): MessageChain {
@JvmSynthetic
internal fun Sequence<SingleMessage>.constrainSingleMessages(): List<SingleMessage> =
constrainSingleMessagesImpl(this.asSequence())
constrainSingleMessagesImpl(this)
/**
* - [Sequence.toMutableList]
@ -146,6 +146,11 @@ internal fun constrainSingleMessagesImpl(sequence: Sequence<SingleMessage>): Lis
internal fun Iterable<SingleMessage>.constrainSingleMessages(): List<SingleMessage> =
constrainSingleMessagesImpl(this.asSequence())
@JvmName("constrainSingleMessages_Sequence")
@JvmSynthetic
internal fun Sequence<Message>.constrainSingleMessages(): List<SingleMessage> =
this.flatMap { it.toMessageChain() }.constrainSingleMessages()
@JvmSynthetic
@Suppress("UNCHECKED_CAST", "DEPRECATION_ERROR", "DEPRECATION")
@ -179,11 +184,6 @@ internal fun MessageChainImplBySequence(
delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle
): MessageChain = MessageChainImpl(delegate.constrainSingleMessages())
@Suppress("FunctionName")
internal fun SingleMessageChainImpl(
delegate: SingleMessage
): MessageChain = MessageChainImpl(listOf(delegate))
//////////////////////
// region Image impl

View File

@ -0,0 +1,224 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
@file:Suppress("unused", "NOTHING_TO_INLINE", "INAPPLICABLE_JVM_NAME")
package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.PlannedRemoval
import kotlin.js.JsName
///////////////////////////////////////////////////////////////////////////
// Deprecated
///////////////////////////////////////////////////////////////////////////
/**
* 得到包含 [this] [MessageChain].
*/
@Suppress("UNCHECKED_CAST")
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Message.asMessageChain(): MessageChain = toMessageChain()
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun SingleMessage.asMessageChain(): MessageChain = toMessageChain()
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Collection<SingleMessage>.asMessageChain(): MessageChain = toMessageChain()
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@JvmName("newChain1")
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
// @JsName("newChain")
public fun Array<out Message>.asMessageChain(): MessageChain = toMessageChain()
@JvmSynthetic
@JvmName("newChain2")
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Array<out SingleMessage>.asMessageChain(): MessageChain = toMessageChain()
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmName("newChain")
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
// @JsName("newChain")
public fun Collection<Message>.asMessageChain(): MessageChain = toMessageChain()
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Iterable<SingleMessage>.asMessageChain(): MessageChain = toMessageChain()
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public inline fun MessageChain.asMessageChain(): MessageChain = this
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
// @JsName("newChain")
@JvmName("asMessageChainMessage")
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Iterable<Message>.asMessageChain(): MessageChain = toMessageChain()
/**
* 直接将 [this] 构建为一个 [MessageChain]
*/
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
public fun Sequence<SingleMessage>.asMessageChain(): MessageChain = toMessageChain()
/**
* [this] [扁平化后][flatten] 构建为一个 [MessageChain]
*/
@JvmName("asMessageChainMessage")
@JvmSynthetic
@PlannedRemoval("2.0.0")
@Deprecated(
"Use toMessageChain.",
ReplaceWith("this.toMessageChain()", "net.mamoe.mirai.message.data.toMessageChain"),
DeprecationLevel.ERROR
)
// @JsName("newChain")
public fun Sequence<Message>.asMessageChain(): MessageChain = toMessageChain()
/**
* 扁平化消息序列.
*
* [this]:
* ```
* A <- MessageChain(B, C) <- D <- MessageChain(E, F, G)
* ```
* 结果 [Sequence]:
* ```
* A <- B <- C <- D <- E <- F <- G
* ```
*/
@Deprecated("flatten is deprecated.", ReplaceWith("this.toMessageChain().asSequence()"))
@PlannedRemoval("2.0.0")
public inline fun Iterable<Message>.flatten(): Sequence<SingleMessage> = toMessageChain().asSequence()
// @JsName("flatten1")
@Deprecated("flatten is deprecated.", ReplaceWith("this.asSequence()"))
@PlannedRemoval("2.0.0")
@JvmName("flatten1")// avoid platform declare clash
@JvmSynthetic
public inline fun Iterable<SingleMessage>.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
/**
* 扁平化消息序列.
*
* [this]:
* ```
* A <- MessageChain(B, C) <- D <- MessageChain(E, F, G)
* ```
* 结果 [Sequence]:
* ```
* A <- B <- C <- D <- E <- F <- G
* ```
*/
@Deprecated("flatten is deprecated.", ReplaceWith("this.toMessageChain().asSequence()"))
@PlannedRemoval("2.0.0")
public inline fun Sequence<Message>.flatten(): Sequence<SingleMessage> = this.toMessageChain().asSequence()
@Deprecated("flatten is deprecated.", ReplaceWith("this"))
@PlannedRemoval("2.0.0")
@JsName("flatten1") // avoid platform declare clash
@JvmName("flatten1")
@JvmSynthetic
public inline fun Sequence<SingleMessage>.flatten(): Sequence<SingleMessage> = this // fast path
@Deprecated("flatten is deprecated.", ReplaceWith("this.toMessageChain().asSequence()"))
@PlannedRemoval("2.0.0")
public inline fun Array<out Message>.flatten(): Sequence<SingleMessage> = this.toMessageChain().asSequence()
@Deprecated("flatten is deprecated.", ReplaceWith("this.asSequence()"))
@PlannedRemoval("2.0.0")
public inline fun Array<out SingleMessage>.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path
/**
* 返回 [MessageChain.asSequence] `sequenceOf(this as SingleMessage)`
*/
@Deprecated("flatten is deprecated.", ReplaceWith("this.toMessageChain().asSequence()"))
@PlannedRemoval("2.0.0")
public fun Message.flatten(): Sequence<SingleMessage> = this.toMessageChain().asSequence()
@Deprecated("flatten is deprecated.", ReplaceWith("this.asSequence()"))
@PlannedRemoval("2.0.0")
@JvmSynthetic // make Java user happier with less methods
public inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() // fast path