diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt index 919b13ae3..b044ae4c4 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt @@ -56,8 +56,18 @@ private constructor(val target: Long, val display: String) : } // 自动为消息补充 " " + @Suppress("INAPPLICABLE_JVM_NAME") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmName("followedBy") + @JvmSynthetic + override fun followedBy1(tail: Message): CombinedMessage { + if (tail is PlainText && tail.stringValue.startsWith(' ')) { + return followedByInternalForBinaryCompatibility(tail) + } + return followedByInternalForBinaryCompatibility(PlainText(" ") + tail) + } - override fun followedBy(tail: Message): CombinedMessage { + override fun followedBy(tail: Message): Message { if (tail is PlainText && tail.stringValue.startsWith(' ')) { return super.followedBy(tail) } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt index 36cd382b3..74b4403ca 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/AtAll.kt @@ -15,6 +15,7 @@ package net.mamoe.mirai.message.data import net.mamoe.mirai.utils.SinceMirai import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName +import kotlin.jvm.JvmSynthetic private const val displayA = "@全体成员" @@ -41,8 +42,18 @@ object AtAll : override fun contentToString(): String = display // 自动为消息补充 " " + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("followedBy") + @JvmSynthetic + override fun followedBy1(tail: Message): CombinedMessage { + if (tail is PlainText && tail.stringValue.startsWith(' ')) { + return followedByInternalForBinaryCompatibility(tail) + } + return followedByInternalForBinaryCompatibility(PlainText(" ") + tail) + } - override fun followedBy(tail: Message): CombinedMessage { + override fun followedBy(tail: Message): Message { if (tail is PlainText && tail.stringValue.startsWith(' ')) { return super.followedBy(tail) } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt index 48093df52..e4b96601f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CombinedMessage.kt @@ -31,11 +31,12 @@ class CombinedMessage @Deprecated(message = "use Message.plus", level = DeprecationLevel.ERROR) @MiraiInternalAPI("CombinedMessage 构造器可能会在将来被改动") constructor( @MiraiExperimentalAPI("CombinedMessage.left 可能会在将来被改动") - val left: Message, + val left: SingleMessage, @MiraiExperimentalAPI("CombinedMessage.tail 可能会在将来被改动") - val tail: Message -) : Iterable<Message>, Message { + val tail: SingleMessage +) : Iterable<SingleMessage>, Message { + /* // 不要把它用作 local function, 会编译错误 @OptIn(MiraiExperimentalAPI::class) private suspend fun SequenceScope<Message>.yieldCombinedOrElements(message: Message) { @@ -66,12 +67,15 @@ class CombinedMessage } } } + */ - fun asSequence(): Sequence<Message> = sequence { - yieldCombinedOrElements(this@CombinedMessage) + @OptIn(MiraiExperimentalAPI::class) + fun asSequence(): Sequence<SingleMessage> = sequence { + yield(left) + yield(tail) } - override fun iterator(): Iterator<Message> { + override fun iterator(): Iterator<SingleMessage> { return asSequence().iterator() } @@ -83,9 +87,4 @@ class CombinedMessage override fun contentToString(): String { return toString() } - - @OptIn(MiraiExperimentalAPI::class) - fun isFlat(): Boolean { - return tail is SingleMessage && left is SingleMessage - } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt index 9a2222a4c..d27aa10a2 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt @@ -16,6 +16,7 @@ import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.SinceMirai +import kotlin.jvm.JvmName import kotlin.jvm.JvmSynthetic /** @@ -92,6 +93,8 @@ interface Message { /** * 把 `this` 连接到 [tail] 的头部. 类似于字符串相加. * + * 连接后无法保证 [ConstrainSingle] 的元素单独存在. 需在 + * * 例: * ```kotlin * val a = PlainText("Hello ") @@ -104,16 +107,22 @@ interface Message { * println(c) // "Hello world!" * ``` */ + @SinceMirai("0.34.0") @Suppress("DEPRECATION_ERROR") @OptIn(MiraiInternalAPI::class) @JvmSynthetic // in java they should use `plus` instead - fun followedBy(tail: Message): CombinedMessage { - if (this is ConstrainSingle<*> && tail is ConstrainSingle<*> - && this.key == tail.key - ) { - return CombinedMessage(EmptyMessageChain, tail) + fun followedBy(tail: Message): Message { + TODO() + if (this is SingleMessage && tail is SingleMessage) { + if (this is ConstrainSingle<*> && tail is ConstrainSingle<*>) { + return if (this.key == tail.key) { + tail + } else { + CombinedMessage(this, tail) + } + } + } - return CombinedMessage(left = this, tail = tail) } /** @@ -138,15 +147,69 @@ interface Message { @SinceMirai("0.34.0") fun contentToString(): String - operator fun plus(another: Message): CombinedMessage = this.followedBy(another) + operator fun plus(another: Message): Message = this.followedBy(another) // avoid resolution ambiguity - operator fun plus(another: SingleMessage): CombinedMessage = this.followedBy(another) + operator fun plus(another: SingleMessage): Message = this.followedBy(another) - operator fun plus(another: String): CombinedMessage = this.followedBy(another.toMessage()) + operator fun plus(another: String): Message = this.followedBy(another.toMessage()) // `+ ""` will be resolved to `plus(String)` instead of `plus(CharSeq)` - operator fun plus(another: CharSequence): CombinedMessage = this.followedBy(another.toString().toMessage()) + operator fun plus(another: CharSequence): Message = this.followedBy(another.toString().toMessage()) + + + // FOR BINARY COMPATIBILITY UNTIL 1.0.0 + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("followedBy") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmSynthetic + fun followedBy1(tail: Message): CombinedMessage = this.followedByInternalForBinaryCompatibility(tail) + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("plus") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmSynthetic + fun plus1(another: Message): CombinedMessage = this.followedByInternalForBinaryCompatibility(another) + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("plus") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmSynthetic + fun plus1(another: SingleMessage): CombinedMessage = this.followedByInternalForBinaryCompatibility(another) + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("plus") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmSynthetic + fun plus1(another: String): CombinedMessage = this.followedByInternalForBinaryCompatibility(another.toMessage()) + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("plus") + @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) + @JvmSynthetic + fun plus1(another: CharSequence): CombinedMessage = + this.followedByInternalForBinaryCompatibility(another.toString().toMessage()) +} + +@OptIn(MiraiInternalAPI::class) +@JvmSynthetic +@Suppress("DEPRECATION_ERROR") +internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): CombinedMessage { + TODO() + if (this is ConstrainSingle<*>) { + + } + + if (this is SingleMessage && tail is SingleMessage) { + if (this is ConstrainSingle<*> && tail is ConstrainSingle<*> + && this.key == tail.key + ) return CombinedMessage(EmptyMessageChain, tail) + return CombinedMessage(left = this, tail = tail) + } else { + + // return CombinedMessage(left = this.constrain) + } } @JvmSynthetic diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt index 342ca1f36..518d4a100 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt @@ -387,10 +387,8 @@ fun Message.flatten(): Sequence<SingleMessage> { @JvmSynthetic // make Java user happier with less methods fun CombinedMessage.flatten(): Sequence<SingleMessage> { // already constrained single. - if (this.isFlat()) { - @Suppress("UNCHECKED_CAST") - return (this as Iterable<SingleMessage>).asSequence() - } else return this.asSequence().flatten() + @Suppress("UNCHECKED_CAST") + return (this as Iterable<SingleMessage>).asSequence() } @JvmSynthetic // make Java user happier with less methods @@ -402,11 +400,17 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() / /** * 不含任何元素的 [MessageChain] */ -object EmptyMessageChain : MessageChain, Iterator<SingleMessage> { +object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, @MiraiExperimentalAPI SingleMessage { override fun contains(sub: String): Boolean = sub.isEmpty() override val size: Int get() = 0 override fun toString(): String = "" override fun contentToString(): String = "" + + override val length: Int get() = 0 + override fun get(index: Int): Char = ""[index] + override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = "".subSequence(startIndex, endIndex) + override fun compareTo(other: String): Int = "".compareTo(other) + override fun iterator(): Iterator<SingleMessage> = this override fun hasNext(): Boolean = false override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.") @@ -424,10 +428,6 @@ object NullMessageChain : MessageChain { override val size: Int get() = 0 override fun equals(other: Any?): Boolean = other === this override fun contains(sub: String): Boolean = error("accessing NullMessageChain") - - @OptIn(MiraiInternalAPI::class) - @Suppress("DEPRECATION_ERROR") - override fun followedBy(tail: Message): CombinedMessage = error("accessing NullMessageChain") override fun iterator(): MutableIterator<SingleMessage> = error("accessing NullMessageChain") } diff --git a/mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ConstrainSingleTest.kt b/mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ConstrainSingleTest.kt index 4bb537f6b..0d88c51f0 100644 --- a/mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ConstrainSingleTest.kt +++ b/mirai-core/src/commonTest/kotlin/net/mamoe/mirai/message.data/ConstrainSingleTest.kt @@ -52,7 +52,7 @@ internal class ConstrainSingleTest { @Test fun testConstrainSingleInPlus() { val new = TestConstrainSingleMessage() - val combined = TestConstrainSingleMessage() + new + val combined = (TestConstrainSingleMessage() + new) as CombinedMessage assertEquals(combined.left, EmptyMessageChain) assertSame(combined.tail, new)