1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-03-26 07:20:09 +08:00

Constrain single on Message.plus, add stubs

This commit is contained in:
Him188 2020-04-05 23:35:47 +08:00
parent c95efe98a3
commit 8486926694
6 changed files with 116 additions and 33 deletions
mirai-core/src
commonMain/kotlin/net.mamoe.mirai/message/data
commonTest/kotlin/net/mamoe/mirai/message.data

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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")
}

View File

@ -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)