mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-23 13:50:12 +08:00
Support multiple ResolveContext kinds in single declaration
This commit is contained in:
parent
0007a97d66
commit
717c908ccf
@ -11,7 +11,6 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.*
|
||||
import net.mamoe.mirai.console.command.java.JRawCommand
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
@ -51,6 +50,7 @@ public abstract class RawCommand(
|
||||
/** 指令父权限 */
|
||||
parentPermission: Permission = owner.parentPermission,
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
@OptIn(ExperimentalCommandDescriptors::class)
|
||||
public override val prefixOptional: Boolean = false,
|
||||
) : Command {
|
||||
public override val permission: Permission by lazy { createOrFindCommandPermission(parentPermission) }
|
||||
|
@ -13,6 +13,7 @@ import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandOwner
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
@ -85,6 +86,7 @@ public abstract class JCompositeCommand
|
||||
protected set
|
||||
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
@ExperimentalCommandDescriptors
|
||||
public final override var prefixOptional: Boolean = false
|
||||
protected set
|
||||
|
||||
|
@ -13,6 +13,7 @@ import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.Command
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandOwner
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
|
||||
@ -70,6 +71,7 @@ public abstract class JRawCommand
|
||||
protected set
|
||||
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
@ExperimentalCommandDescriptors
|
||||
public final override var prefixOptional: Boolean = false
|
||||
protected set
|
||||
}
|
@ -10,10 +10,10 @@
|
||||
package net.mamoe.mirai.console.command.java
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.console.command.CommandOwner
|
||||
import net.mamoe.mirai.console.command.SimpleCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.permission.Permission
|
||||
@ -52,9 +52,10 @@ public abstract class JSimpleCommand(
|
||||
) : SimpleCommand(owner, primaryName, secondaryNames = secondaryNames, parentPermission = basePermission) {
|
||||
public override var description: String = super.description
|
||||
protected set
|
||||
|
||||
public override var permission: Permission = super.permission
|
||||
protected set
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public override var prefixOptional: Boolean = super.prefixOptional
|
||||
protected set
|
||||
public override var context: CommandArgumentContext = super.context
|
||||
|
@ -11,22 +11,21 @@
|
||||
|
||||
package net.mamoe.mirai.console.compiler.common
|
||||
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.console.command.Command
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.data.value
|
||||
import net.mamoe.mirai.console.permission.PermissionId
|
||||
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||
import net.mamoe.mirai.console.util.SemVersion
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
/**
|
||||
* 标记一个参数的语境类型, 用于帮助编译器和 IntelliJ 插件进行语境推断.
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
@Target(
|
||||
VALUE_PARAMETER,
|
||||
PROPERTY, FIELD,
|
||||
FUNCTION,
|
||||
TYPE, TYPE_PARAMETER
|
||||
)
|
||||
@Target(VALUE_PARAMETER, PROPERTY, FIELD, FUNCTION, TYPE, TYPE_PARAMETER)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class ResolveContext(
|
||||
val kind: Kind,
|
||||
vararg val kinds: Kind,
|
||||
) {
|
||||
/**
|
||||
* 元素数量可能在任意时间被改动
|
||||
@ -36,18 +35,57 @@ public annotation class ResolveContext(
|
||||
// ConstantKind
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PLUGIN_ID, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
PLUGIN_NAME, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
PLUGIN_VERSION, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
/*
|
||||
* WARNING: IF YOU CHANGE NAMES HERE,
|
||||
* YOU SHOULD ALSO CHANGE THEIR COUNTERPARTS AT net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see PluginDescription.id
|
||||
*/
|
||||
PLUGIN_ID, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
|
||||
/**
|
||||
* @see PluginDescription.name
|
||||
*/
|
||||
PLUGIN_NAME, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
|
||||
/**
|
||||
* @see PluginDescription.version
|
||||
* @see SemVersion.Companion.invoke
|
||||
*/
|
||||
SEMANTIC_VERSION, // ILLEGAL_PLUGIN_DESCRIPTION
|
||||
|
||||
/**
|
||||
* @see SemVersion.Companion.parseRangeRequirement
|
||||
*/
|
||||
VERSION_REQUIREMENT, // ILLEGAL_VERSION_REQUIREMENT // TODO
|
||||
|
||||
/**
|
||||
* @see Command.allNames
|
||||
*/
|
||||
COMMAND_NAME, // ILLEGAL_COMMAND_NAME
|
||||
|
||||
PERMISSION_NAMESPACE, // ILLEGAL_COMMAND_NAMESPACE
|
||||
PERMISSION_NAME, // ILLEGAL_COMMAND_NAME
|
||||
PERMISSION_ID, // ILLEGAL_COMMAND_ID
|
||||
/**
|
||||
* @see PermissionId.name
|
||||
*/
|
||||
PERMISSION_NAMESPACE, // ILLEGAL_PERMISSION_NAMESPACE
|
||||
|
||||
/**
|
||||
* @see PermissionId.name
|
||||
*/
|
||||
PERMISSION_NAME, // ILLEGAL_PERMISSION_NAME
|
||||
|
||||
/**
|
||||
* @see PermissionId.parseFromString
|
||||
*/
|
||||
PERMISSION_ID, // ILLEGAL_PERMISSION_ID
|
||||
|
||||
/**
|
||||
* 标注一个泛型, 要求这个泛型必须拥有一个公开无参 (或所有参数都可选) 构造器.
|
||||
*
|
||||
* @see PluginData.value
|
||||
*/
|
||||
RESTRICTED_NO_ARG_CONSTRUCTOR, // NOT_CONSTRUCTABLE_TYPE
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ internal abstract class JvmPluginInternal(
|
||||
|
||||
final override val parentPermission: Permission by lazy {
|
||||
PermissionService.INSTANCE.register(
|
||||
PermissionService.INSTANCE.allocatePermissionIdForPlugin(this, "*", PermissionService.PluginPermissionIdRequestType.PLUGIN_ROOT_PERMISSION),
|
||||
PermissionService.INSTANCE.allocatePermissionIdForPlugin(this, "*"),
|
||||
"The base permission"
|
||||
)
|
||||
}
|
||||
|
@ -97,8 +97,7 @@ public interface PermissionService<P : Permission> {
|
||||
public fun allocatePermissionIdForPlugin(
|
||||
plugin: Plugin,
|
||||
@ResolveContext(COMMAND_NAME) permissionName: String,
|
||||
reason: PluginPermissionIdRequestType
|
||||
): PermissionId = allocatePermissionIdForPluginDefaultImplement(plugin, permissionName, reason)
|
||||
): PermissionId = allocatePermissionIdForPluginDefaultImplement(plugin, permissionName)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -127,16 +126,6 @@ public interface PermissionService<P : Permission> {
|
||||
@Throws(UnsupportedOperationException::class)
|
||||
public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean)
|
||||
|
||||
/** [Plugin] 尝试分配的 [PermissionId] 来源 */
|
||||
@ConsoleExperimentalApi
|
||||
public enum class PluginPermissionIdRequestType {
|
||||
/** For [Plugin.parentPermission] */
|
||||
PLUGIN_ROOT_PERMISSION,
|
||||
|
||||
/** For [Plugin.permissionId] */
|
||||
NORMAL
|
||||
}
|
||||
|
||||
public companion object {
|
||||
internal var instanceField: PermissionService<*>? = null
|
||||
|
||||
@ -155,7 +144,6 @@ public interface PermissionService<P : Permission> {
|
||||
internal fun PermissionService<*>.allocatePermissionIdForPluginDefaultImplement(
|
||||
plugin: Plugin,
|
||||
@ResolveContext(COMMAND_NAME) permissionName: String,
|
||||
reason: PluginPermissionIdRequestType
|
||||
) = PermissionId(
|
||||
plugin.description.id.toLowerCase(),
|
||||
permissionName.toLowerCase()
|
||||
|
@ -92,7 +92,7 @@ public interface PluginDescription {
|
||||
*
|
||||
* @see Semver 语义化版本. 允许 [宽松][Semver.SemverType.LOOSE] 类型版本.
|
||||
*/
|
||||
@ResolveContext(PLUGIN_VERSION)
|
||||
@ResolveContext(SEMANTIC_VERSION)
|
||||
public val version: SemVersion
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor(
|
||||
public final override val loader: JvmPluginLoader get() = super<JvmPluginInternal>.loader
|
||||
|
||||
public final override fun permissionId(name: String): PermissionId =
|
||||
PermissionService.INSTANCE.allocatePermissionIdForPlugin(this, name, PermissionService.PluginPermissionIdRequestType.NORMAL)
|
||||
PermissionService.INSTANCE.allocatePermissionIdForPlugin(this, name)
|
||||
|
||||
/**
|
||||
* 重载 [PluginData]
|
||||
|
@ -43,7 +43,7 @@ public interface JvmPluginDescription : PluginDescription {
|
||||
/**
|
||||
* @see [PluginDescription.version]
|
||||
*/
|
||||
@ResolveContext(PLUGIN_VERSION) version: String,
|
||||
@ResolveContext(SEMANTIC_VERSION) version: String,
|
||||
/**
|
||||
* @see [PluginDescription.name]
|
||||
*/
|
||||
@ -102,7 +102,7 @@ public class JvmPluginDescriptionBuilder(
|
||||
) {
|
||||
public constructor(
|
||||
@ResolveContext(PLUGIN_ID) id: String,
|
||||
@ResolveContext(PLUGIN_VERSION) version: String,
|
||||
@ResolveContext(SEMANTIC_VERSION) version: String,
|
||||
) : this(id, SemVersion(version))
|
||||
|
||||
private var name: String = id
|
||||
@ -115,7 +115,7 @@ public class JvmPluginDescriptionBuilder(
|
||||
apply { this.name = value.trim() }
|
||||
|
||||
@ILoveKuriyamaMiraiForever
|
||||
public fun version(@ResolveContext(PLUGIN_VERSION) value: String): JvmPluginDescriptionBuilder =
|
||||
public fun version(@ResolveContext(SEMANTIC_VERSION) value: String): JvmPluginDescriptionBuilder =
|
||||
apply { this.version = SemVersion(value) }
|
||||
|
||||
@ILoveKuriyamaMiraiForever
|
||||
|
@ -21,7 +21,7 @@ import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.PLUGIN_VERSION
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.SEMANTIC_VERSION
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.VERSION_REQUIREMENT
|
||||
import net.mamoe.mirai.console.internal.data.map
|
||||
import net.mamoe.mirai.console.internal.util.semver.SemVersionInternal
|
||||
@ -115,7 +115,7 @@ internal constructor(
|
||||
@JvmStatic
|
||||
@JvmName("parse")
|
||||
@Throws(IllegalArgumentException::class, NumberFormatException::class)
|
||||
public operator fun invoke(@ResolveContext(PLUGIN_VERSION) version: String): SemVersion = SemVersionInternal.parse(version)
|
||||
public operator fun invoke(@ResolveContext(SEMANTIC_VERSION) version: String): SemVersion = SemVersionInternal.parse(version)
|
||||
|
||||
/**
|
||||
* 解析一条依赖需求描述, 在无法解析的时候抛出 [IllegalArgumentException]
|
||||
@ -155,7 +155,7 @@ internal constructor(
|
||||
/** @see [Requirement.test] */
|
||||
@JvmStatic
|
||||
@Throws(IllegalArgumentException::class, NumberFormatException::class)
|
||||
public fun Requirement.test(@ResolveContext(PLUGIN_VERSION) version: String): Boolean = test(invoke(version))
|
||||
public fun Requirement.test(@ResolveContext(SEMANTIC_VERSION) version: String): Boolean = test(invoke(version))
|
||||
|
||||
/**
|
||||
* 当满足 [requirement] 时返回 true, 否则返回 false
|
||||
@ -178,7 +178,7 @@ internal constructor(
|
||||
/** for Kotlin only */
|
||||
@JvmStatic
|
||||
@JvmSynthetic
|
||||
public operator fun Requirement.contains(@ResolveContext(PLUGIN_VERSION) version: String): Boolean = test(version)
|
||||
public operator fun Requirement.contains(@ResolveContext(SEMANTIC_VERSION) version: String): Boolean = test(version)
|
||||
}
|
||||
|
||||
@Transient
|
||||
|
@ -13,6 +13,7 @@ import net.mamoe.mirai.console.compiler.common.castOrNull
|
||||
import net.mamoe.mirai.console.compiler.common.firstValue
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -73,11 +74,14 @@ enum class ResolveContextKind {
|
||||
}
|
||||
}
|
||||
|
||||
fun Annotated.isResolveContext(kind: ResolveContextKind) = this.resolveContextKind == kind
|
||||
|
||||
val Annotated.resolveContextKind: ResolveContextKind?
|
||||
val Annotated.resolveContextKinds: List<ResolveContextKind>?
|
||||
get() {
|
||||
val ann = this.findAnnotation(RESOLVE_CONTEXT_FQ_NAME) ?: return null
|
||||
val (_, enumEntryName) = ann.allValueArguments.firstValue().castOrNull<EnumValue>()?.value ?: return null // undetermined kind
|
||||
return ResolveContextKind.valueOf(enumEntryName.asString())
|
||||
val kinds =
|
||||
ann.allValueArguments.firstValue().castOrNull<ArrayValue>()?.value?.mapNotNull { it.castOrNull<EnumValue>()?.value }
|
||||
?: return null // undetermined kind
|
||||
|
||||
return kinds.map { (_, enumEntryName) ->
|
||||
ResolveContextKind.valueOf(enumEntryName.asString())
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ package net.mamoe.mirai.console.intellij.diagnostics
|
||||
import com.intellij.psi.PsiElement
|
||||
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.*
|
||||
import net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind
|
||||
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.resolveAllCalls
|
||||
import net.mamoe.mirai.console.intellij.resolve.resolveStringConstantValues
|
||||
import net.mamoe.mirai.console.intellij.resolve.valueParametersWithArguments
|
||||
@ -134,12 +134,18 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
context: DeclarationCheckerContext,
|
||||
) {
|
||||
declaration.resolveAllCalls(context.bindingContext)
|
||||
.asSequence()
|
||||
.flatMap { call ->
|
||||
call.valueParametersWithArguments().asSequence()
|
||||
}
|
||||
.mapNotNull { (p, a) ->
|
||||
p.resolveContextKind?.let(checkersMap::get)?.let { it to a }
|
||||
p.resolveContextKinds
|
||||
?.map(checkersMap::get)
|
||||
?.mapNotNull {
|
||||
if (it == null) null else it to a
|
||||
}
|
||||
}
|
||||
.flatMap { it.asSequence() }
|
||||
.mapNotNull { (kind, argument) ->
|
||||
argument.resolveStringConstantValues()?.let { const ->
|
||||
Triple(kind, argument, const)
|
||||
|
@ -31,12 +31,12 @@ class PluginDataValuesChecker : DeclarationChecker {
|
||||
declaration.resolveAllCallsWithElement(bindingContext)
|
||||
.filter { (call) -> call.isCalling(PLUGIN_DATA_VALUE_FUNCTIONS_FQ_FQ_NAME) }
|
||||
.filter { (call) ->
|
||||
call.resultingDescriptor.resolveContextKind == ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR
|
||||
call.resultingDescriptor.resolveContextKinds?.contains(ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR) == true
|
||||
}.flatMap { (call, element) ->
|
||||
call.typeArguments.entries.associateWith { element }.asSequence()
|
||||
}.filter { (e, _) ->
|
||||
val (p, t) = e
|
||||
(p.isReified || p.resolveContextKind == ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR)
|
||||
(p.isReified || p.resolveContextKinds?.contains(ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR) == true)
|
||||
&& t is SimpleType
|
||||
}.forEach { (e, callExpr) ->
|
||||
val (_, type) = e
|
||||
|
@ -15,7 +15,6 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
fun DeclarationCheckerContext.report(diagnostic: Diagnostic) {
|
||||
return this.trace.report(diagnostic)
|
||||
@ -25,7 +24,6 @@ val DeclarationCheckerContext.bindingContext get() = this.trace.bindingContext
|
||||
|
||||
fun KtElement?.getResolvedCallOrResolveToCall(
|
||||
context: DeclarationCheckerContext,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL,
|
||||
): ResolvedCall<out CallableDescriptor>? {
|
||||
return this.getResolvedCallOrResolveToCall(context.bindingContext, bodyResolveMode)
|
||||
return this.getResolvedCallOrResolveToCall(context.bindingContext)
|
||||
}
|
@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
|
||||
@ -125,9 +124,8 @@ inline fun <reified E> PsiElement.findChild(): E? = this.children.find { it is E
|
||||
|
||||
fun KtElement?.getResolvedCallOrResolveToCall(
|
||||
context: BindingContext,
|
||||
bodyResolveMode: BodyResolveMode = BodyResolveMode.PARTIAL,
|
||||
): ResolvedCall<out CallableDescriptor>? {
|
||||
return this?.getCall(context)?.getResolvedCall(context)// ?: this?.resolveToCall(bodyResolveMode)
|
||||
return this?.getCall(context)?.getResolvedCall(context)
|
||||
}
|
||||
|
||||
val ResolvedCall<out CallableDescriptor>.valueParameters: List<ValueParameterDescriptor> get() = this.resultingDescriptor.valueParameters
|
||||
|
Loading…
Reference in New Issue
Block a user