Commit 84869266 authored by Him188's avatar Him188

Constrain single on `Message.plus`, add stubs

parent c95efe98
...@@ -56,8 +56,18 @@ private constructor(val target: Long, val display: String) : ...@@ -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(' ')) { if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super.followedBy(tail) return super.followedBy(tail)
} }
......
...@@ -15,6 +15,7 @@ package net.mamoe.mirai.message.data ...@@ -15,6 +15,7 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.SinceMirai import net.mamoe.mirai.utils.SinceMirai
import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
private const val displayA = "@全体成员" private const val displayA = "@全体成员"
...@@ -41,8 +42,18 @@ object AtAll : ...@@ -41,8 +42,18 @@ object AtAll :
override fun contentToString(): String = display 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(' ')) { if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super.followedBy(tail) return super.followedBy(tail)
} }
......
...@@ -31,11 +31,12 @@ class CombinedMessage ...@@ -31,11 +31,12 @@ class CombinedMessage
@Deprecated(message = "use Message.plus", level = DeprecationLevel.ERROR) @Deprecated(message = "use Message.plus", level = DeprecationLevel.ERROR)
@MiraiInternalAPI("CombinedMessage 构造器可能会在将来被改动") constructor( @MiraiInternalAPI("CombinedMessage 构造器可能会在将来被改动") constructor(
@MiraiExperimentalAPI("CombinedMessage.left 可能会在将来被改动") @MiraiExperimentalAPI("CombinedMessage.left 可能会在将来被改动")
val left: Message, val left: SingleMessage,
@MiraiExperimentalAPI("CombinedMessage.tail 可能会在将来被改动") @MiraiExperimentalAPI("CombinedMessage.tail 可能会在将来被改动")
val tail: Message val tail: SingleMessage
) : Iterable<Message>, Message { ) : Iterable<SingleMessage>, Message {
/*
// 不要把它用作 local function, 会编译错误 // 不要把它用作 local function, 会编译错误
@OptIn(MiraiExperimentalAPI::class) @OptIn(MiraiExperimentalAPI::class)
private suspend fun SequenceScope<Message>.yieldCombinedOrElements(message: Message) { private suspend fun SequenceScope<Message>.yieldCombinedOrElements(message: Message) {
...@@ -66,12 +67,15 @@ class CombinedMessage ...@@ -66,12 +67,15 @@ class CombinedMessage
} }
} }
} }
*/
fun asSequence(): Sequence<Message> = sequence { @OptIn(MiraiExperimentalAPI::class)
yieldCombinedOrElements(this@CombinedMessage) fun asSequence(): Sequence<SingleMessage> = sequence {
yield(left)
yield(tail)
} }
override fun iterator(): Iterator<Message> { override fun iterator(): Iterator<SingleMessage> {
return asSequence().iterator() return asSequence().iterator()
} }
...@@ -83,9 +87,4 @@ class CombinedMessage ...@@ -83,9 +87,4 @@ class CombinedMessage
override fun contentToString(): String { override fun contentToString(): String {
return toString() return toString()
} }
@OptIn(MiraiExperimentalAPI::class)
fun isFlat(): Boolean {
return tail is SingleMessage && left is SingleMessage
}
} }
\ No newline at end of file
...@@ -16,6 +16,7 @@ import net.mamoe.mirai.message.MessageReceipt ...@@ -16,6 +16,7 @@ import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.SinceMirai import net.mamoe.mirai.utils.SinceMirai
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
/** /**
...@@ -92,6 +93,8 @@ interface Message { ...@@ -92,6 +93,8 @@ interface Message {
/** /**
* 把 `this` 连接到 [tail] 的头部. 类似于字符串相加. * 把 `this` 连接到 [tail] 的头部. 类似于字符串相加.
* *
* 连接后无法保证 [ConstrainSingle] 的元素单独存在. 需在
*
* 例: * 例:
* ```kotlin * ```kotlin
* val a = PlainText("Hello ") * val a = PlainText("Hello ")
...@@ -104,16 +107,22 @@ interface Message { ...@@ -104,16 +107,22 @@ interface Message {
* println(c) // "Hello world!" * println(c) // "Hello world!"
* ``` * ```
*/ */
@SinceMirai("0.34.0")
@Suppress("DEPRECATION_ERROR") @Suppress("DEPRECATION_ERROR")
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class)
@JvmSynthetic // in java they should use `plus` instead @JvmSynthetic // in java they should use `plus` instead
fun followedBy(tail: Message): CombinedMessage { fun followedBy(tail: Message): Message {
if (this is ConstrainSingle<*> && tail is ConstrainSingle<*> TODO()
&& this.key == tail.key if (this is SingleMessage && tail is SingleMessage) {
) { if (this is ConstrainSingle<*> && tail is ConstrainSingle<*>) {
return CombinedMessage(EmptyMessageChain, tail) return if (this.key == tail.key) {
tail
} else {
CombinedMessage(this, tail)
}
}
} }
return CombinedMessage(left = this, tail = tail)
} }
/** /**
...@@ -138,15 +147,69 @@ interface Message { ...@@ -138,15 +147,69 @@ interface Message {
@SinceMirai("0.34.0") @SinceMirai("0.34.0")
fun contentToString(): String fun contentToString(): String
operator fun plus(another: Message): CombinedMessage = this.followedBy(another) operator fun plus(another: Message): Message = this.followedBy(another)
// avoid resolution ambiguity // 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)` // `+ ""` 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 @JvmSynthetic
......
...@@ -387,10 +387,8 @@ fun Message.flatten(): Sequence<SingleMessage> { ...@@ -387,10 +387,8 @@ fun Message.flatten(): Sequence<SingleMessage> {
@JvmSynthetic // make Java user happier with less methods @JvmSynthetic // make Java user happier with less methods
fun CombinedMessage.flatten(): Sequence<SingleMessage> { fun CombinedMessage.flatten(): Sequence<SingleMessage> {
// already constrained single. // already constrained single.
if (this.isFlat()) { @Suppress("UNCHECKED_CAST")
@Suppress("UNCHECKED_CAST") return (this as Iterable<SingleMessage>).asSequence()
return (this as Iterable<SingleMessage>).asSequence()
} else return this.asSequence().flatten()
} }
@JvmSynthetic // make Java user happier with less methods @JvmSynthetic // make Java user happier with less methods
...@@ -402,11 +400,17 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() / ...@@ -402,11 +400,17 @@ inline fun MessageChain.flatten(): Sequence<SingleMessage> = this.asSequence() /
/** /**
* 不含任何元素的 [MessageChain] * 不含任何元素的 [MessageChain]
*/ */
object EmptyMessageChain : MessageChain, Iterator<SingleMessage> { object EmptyMessageChain : MessageChain, Iterator<SingleMessage>, @MiraiExperimentalAPI SingleMessage {
override fun contains(sub: String): Boolean = sub.isEmpty() override fun contains(sub: String): Boolean = sub.isEmpty()
override val size: Int get() = 0 override val size: Int get() = 0
override fun toString(): String = "" override fun toString(): String = ""
override fun contentToString(): 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 iterator(): Iterator<SingleMessage> = this
override fun hasNext(): Boolean = false override fun hasNext(): Boolean = false
override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.") override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.")
...@@ -424,10 +428,6 @@ object NullMessageChain : MessageChain { ...@@ -424,10 +428,6 @@ object NullMessageChain : MessageChain {
override val size: Int get() = 0 override val size: Int get() = 0
override fun equals(other: Any?): Boolean = other === this override fun equals(other: Any?): Boolean = other === this
override fun contains(sub: String): Boolean = error("accessing NullMessageChain") 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") override fun iterator(): MutableIterator<SingleMessage> = error("accessing NullMessageChain")
} }
......
...@@ -52,7 +52,7 @@ internal class ConstrainSingleTest { ...@@ -52,7 +52,7 @@ internal class ConstrainSingleTest {
@Test @Test
fun testConstrainSingleInPlus() { fun testConstrainSingleInPlus() {
val new = TestConstrainSingleMessage() val new = TestConstrainSingleMessage()
val combined = TestConstrainSingleMessage() + new val combined = (TestConstrainSingleMessage() + new) as CombinedMessage
assertEquals(combined.left, EmptyMessageChain) assertEquals(combined.left, EmptyMessageChain)
assertSame(combined.tail, new) assertSame(combined.tail, new)
......
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