mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-06 08:00:10 +08:00
Add @ResolveContext
for usages of abstract message keys, implement relevant inspections, close #1363
This commit is contained in:
parent
63957b183b
commit
1cd354a7e3
@ -69,6 +69,9 @@ object MiraiConsoleErrors {
|
||||
@JvmField
|
||||
val RESTRICTED_CONSOLE_COMMAND_OWNER = create<PsiElement>(WARNING)
|
||||
|
||||
@JvmField
|
||||
val PROHIBITED_ABSTRACT_MESSAGE_KEYS = create<PsiElement>(WARNING)
|
||||
|
||||
@JvmField
|
||||
val ILLEGAL_COMMAND_DECLARATION_RECEIVER = create<KtTypeReference>(ERROR)
|
||||
|
||||
|
@ -19,6 +19,7 @@ import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.IL
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_PLUGIN_DESCRIPTION
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_VERSION_REQUIREMENT
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.PROHIBITED_ABSTRACT_MESSAGE_KEYS
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.READ_ONLY_VALUE_CANNOT_BE_VAR
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.RESTRICTED_CONSOLE_COMMAND_OWNER
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.UNSERIALIZABLE_TYPE
|
||||
@ -114,6 +115,11 @@ object MiraiConsoleErrorsRendering : DefaultErrorMessages.Extension {
|
||||
"插件不允许使用 ConsoleCommandOwner 构造指令, 请使用插件主类作为 CommandOwner",
|
||||
)
|
||||
|
||||
put(
|
||||
PROHIBITED_ABSTRACT_MESSAGE_KEYS,
|
||||
"使用 MessageContent.Key 等抽象消息类型的 Key 没有意义",
|
||||
)
|
||||
|
||||
put(
|
||||
READ_ONLY_VALUE_CANNOT_BE_VAR,
|
||||
"在 ReadOnlyPluginData 中不可定义 'var' by value",
|
||||
|
@ -58,6 +58,10 @@ val READ_ONLY_PLUGIN_DATA_FQ_NAME = FqName("net.mamoe.mirai.console.data.ReadOnl
|
||||
|
||||
val RESOLVE_CONTEXT_FQ_NAME = FqName("net.mamoe.mirai.console.compiler.common.ResolveContext")
|
||||
|
||||
val PROHIBITED_MESSAGE_KEYS = arrayOf(
|
||||
FqName("net.mamoe.mirai.message.data.MessageContent.Key")
|
||||
)
|
||||
|
||||
/**
|
||||
* net.mamoe.mirai.console.compiler.common.ResolveContext.Kind
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.6.0"
|
||||
kotlin("plugin.serialization") version "1.6.0"
|
||||
id("net.mamoe.mirai-console") version "2.9.0-M1"
|
||||
id("net.mamoe.mirai-console") version "2.99.0-local"
|
||||
java
|
||||
}
|
||||
|
||||
@ -13,6 +13,6 @@ dependencies {
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
package org.example.myplugin
|
||||
|
||||
import net.mamoe.mirai.message.data.MessageContent
|
||||
import net.mamoe.mirai.message.data.messageChainOf
|
||||
|
||||
fun main() {
|
||||
val chain = messageChainOf()
|
||||
chain[MessageContent]
|
||||
}
|
@ -17,8 +17,10 @@ import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.IL
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_PERMISSION_NAMESPACE
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_PLUGIN_DESCRIPTION
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_VERSION_REQUIREMENT
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.PROHIBITED_ABSTRACT_MESSAGE_KEYS
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.RESTRICTED_CONSOLE_COMMAND_OWNER
|
||||
import net.mamoe.mirai.console.compiler.common.resolve.CONSOLE_COMMAND_OWNER_FQ_NAME
|
||||
import net.mamoe.mirai.console.compiler.common.resolve.PROHIBITED_MESSAGE_KEYS
|
||||
import net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind
|
||||
import net.mamoe.mirai.console.compiler.common.resolve.resolveContextKinds
|
||||
import net.mamoe.mirai.console.intellij.resolve.getResolvedCall
|
||||
@ -30,6 +32,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.inspections.collections.isCalling
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@ -219,6 +222,23 @@ class ContextualParametersChecker : CallChecker {
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun checkAbstractMessageKeys(
|
||||
context: CallCheckerContext,
|
||||
inspectionTarget: PsiElement,
|
||||
argument: ValueArgument
|
||||
): Diagnostic? {
|
||||
val expr = argument.getArgumentExpression() ?: return null
|
||||
|
||||
if (expr is KtReferenceExpression) {
|
||||
val call = expr.getResolvedCall(context.bindingContext) ?: return null
|
||||
if (PROHIBITED_MESSAGE_KEYS.any { call.isCalling(it) }) {
|
||||
return PROHIBITED_ABSTRACT_MESSAGE_KEYS.on(inspectionTarget)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun interface ElementChecker {
|
||||
@ -268,6 +288,7 @@ class ContextualParametersChecker : CallChecker {
|
||||
put(ResolveContextKind.PERMISSION_ID, ::checkPermissionId)
|
||||
put(ResolveContextKind.VERSION_REQUIREMENT, ::checkVersionRequirement)
|
||||
put(ResolveContextKind.RESTRICTED_CONSOLE_COMMAND_OWNER, ::checkConsoleCommandOwner)
|
||||
put(ResolveContextKind.RESTRICTED_ABSTRACT_MESSAGE_KEYS, ::checkAbstractMessageKeys)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.intellij.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.inspections.collections.isCalling
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class MessageChainGetCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
// if (resolvedCall.isCalling())
|
||||
}
|
||||
|
||||
}
|
@ -60,6 +60,7 @@ kotlin {
|
||||
api(`ktor-client-okhttp`)
|
||||
|
||||
implementation(project(":mirai-core-utils"))
|
||||
implementation(project(":mirai-console-compiler-annotations"))
|
||||
implementation(`kotlinx-serialization-protobuf-jvm`)
|
||||
implementation(`jetbrains-annotations`)
|
||||
implementation(`log4j-api`)
|
||||
|
@ -21,6 +21,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.event.events.MessageEvent
|
||||
import net.mamoe.mirai.message.MessageSerializers
|
||||
@ -38,6 +39,7 @@ import net.mamoe.mirai.utils.safeCast
|
||||
import java.util.stream.Stream
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.streams.asSequence
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.RESTRICTED_ABSTRACT_MESSAGE_KEYS as RAMK
|
||||
|
||||
/**
|
||||
* 消息链, `List<SingleMessage>`, 即 [单个消息元素][SingleMessage] 的有序集合.
|
||||
@ -211,7 +213,7 @@ public sealed interface MessageChain :
|
||||
*
|
||||
* @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException]
|
||||
*/
|
||||
public operator fun <M : SingleMessage> get(key: MessageKey<M>): M? {
|
||||
public operator fun <M : SingleMessage> get(@ResolveContext(RAMK) key: MessageKey<M>): M? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return firstOrNull { key.safeCast.invoke(it) != null } as M?
|
||||
}
|
||||
@ -242,7 +244,7 @@ public sealed interface MessageChain :
|
||||
*
|
||||
* @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException]
|
||||
*/
|
||||
public operator fun <M : SingleMessage> contains(key: MessageKey<M>): Boolean =
|
||||
public operator fun <M : SingleMessage> contains(@ResolveContext(RAMK) key: MessageKey<M>): Boolean =
|
||||
any { key.safeCast.invoke(it) != null }
|
||||
|
||||
@MiraiExperimentalApi
|
||||
@ -381,7 +383,7 @@ public object EmptyMessageChain : MessageChain, List<SingleMessage> by emptyList
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline fun <M : SingleMessage> MessageChain.getOrFail(
|
||||
key: MessageKey<M>,
|
||||
@ResolveContext(RAMK) key: MessageKey<M>,
|
||||
crossinline lazyMessage: (key: MessageKey<M>) -> String = { key.toString() }
|
||||
): M = get(key) ?: throw NoSuchElementException(lazyMessage(key))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user