mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-13 11:30:13 +08:00
Reformat and cleanup code
This commit is contained in:
parent
f341d2f1f6
commit
f096d0d042
@ -42,7 +42,8 @@ public interface MiraiConsoleFrontEndDescription {
|
||||
* 返回 `null` 表示禁止 [MiraiConsole] 后端检查版本兼容性.
|
||||
*/
|
||||
@MiraiExperimentalApi
|
||||
public val compatibleBackendVersion: SemVersion? get() = null
|
||||
public val compatibleBackendVersion: SemVersion?
|
||||
get() = null
|
||||
|
||||
/**
|
||||
* 返回显示在 [MiraiConsole] 启动时的信息
|
||||
|
@ -268,7 +268,7 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
if (::instance.isInitialized && instance.isActive) {
|
||||
error(
|
||||
"Mirai Console is already initialized and is currently running. " +
|
||||
"Run MiraiConsole.cancel to kill old instance before starting another instance."
|
||||
"Run MiraiConsole.cancel to kill old instance before starting another instance."
|
||||
)
|
||||
}
|
||||
this@Companion.instance = this
|
||||
|
@ -187,12 +187,12 @@ public object BuiltInCommands {
|
||||
onFailure = { throwable ->
|
||||
scopeWith(ConsoleCommandSender).sendMessage(
|
||||
"Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" +
|
||||
if (this is CommandSenderOnMessage<*>) {
|
||||
CommandManagerImpl.launch(CoroutineName("stacktrace delayer from Login")) {
|
||||
fromEvent.nextMessageOrNull(60.secondsToMillis) { it.message.contentEquals("stacktrace") }
|
||||
}
|
||||
"\n 1 分钟内发送 stacktrace 以获取堆栈信息"
|
||||
} else ""
|
||||
if (this is CommandSenderOnMessage<*>) {
|
||||
CommandManagerImpl.launch(CoroutineName("stacktrace delayer from Login")) {
|
||||
fromEvent.nextMessageOrNull(60.secondsToMillis) { it.message.contentEquals("stacktrace") }
|
||||
}
|
||||
"\n 1 分钟内发送 stacktrace 以获取堆栈信息"
|
||||
} else ""
|
||||
)
|
||||
|
||||
throw throwable
|
||||
@ -267,7 +267,9 @@ public object BuiltInCommands {
|
||||
@Description("查看所有权限列表")
|
||||
@SubCommand("listPermissions", "lp")
|
||||
public suspend fun CommandSender.listPermissions() {
|
||||
sendMessage(PermissionService.INSTANCE.getRegisteredPermissions().joinToString("\n") { it.id.toString() + " " + it.description })
|
||||
sendMessage(
|
||||
PermissionService.INSTANCE.getRegisteredPermissions()
|
||||
.joinToString("\n") { it.id.toString() + " " + it.description })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,21 +206,24 @@ public interface CommandSender : CoroutineScope, Permittee {
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("from")
|
||||
public fun GroupTempMessageEvent.toCommandSender(): GroupTempCommandSenderOnMessage = GroupTempCommandSenderOnMessage(this)
|
||||
public fun GroupTempMessageEvent.toCommandSender(): GroupTempCommandSenderOnMessage =
|
||||
GroupTempCommandSenderOnMessage(this)
|
||||
|
||||
/**
|
||||
* 构造 [StrangerCommandSenderOnMessage]
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("from")
|
||||
public fun StrangerMessageEvent.toCommandSender(): StrangerCommandSenderOnMessage = StrangerCommandSenderOnMessage(this)
|
||||
public fun StrangerMessageEvent.toCommandSender(): StrangerCommandSenderOnMessage =
|
||||
StrangerCommandSenderOnMessage(this)
|
||||
|
||||
/**
|
||||
* 构造 [OtherClientCommandSenderOnMessage]
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("from")
|
||||
public fun OtherClientMessageEvent.toCommandSender(): OtherClientCommandSenderOnMessage = OtherClientCommandSenderOnMessage(this)
|
||||
public fun OtherClientMessageEvent.toCommandSender(): OtherClientCommandSenderOnMessage =
|
||||
OtherClientCommandSenderOnMessage(this)
|
||||
|
||||
/**
|
||||
* 构造 [CommandSenderOnMessage]
|
||||
@ -599,7 +602,8 @@ public sealed class TempCommandSender(
|
||||
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||
public open class GroupTempCommandSender internal constructor(
|
||||
public final override val user: NormalMember,
|
||||
) : @Suppress("DEPRECATION_ERROR") TempCommandSender(user), CoroutineScope by user.childScope("GroupTempCommandSender") {
|
||||
) : @Suppress("DEPRECATION_ERROR") TempCommandSender(user),
|
||||
CoroutineScope by user.childScope("GroupTempCommandSender") {
|
||||
public override val group: Group get() = user.group
|
||||
public override val subject: NormalMember get() = user
|
||||
public override fun toString(): String = "GroupTempCommandSender($user)"
|
||||
@ -649,7 +653,8 @@ public open class OtherClientCommandSender internal constructor(
|
||||
public override val permitteeId: PermitteeId = AbstractPermitteeId.AnyOtherClient
|
||||
|
||||
@JvmBlockingBridge
|
||||
public override suspend fun sendMessage(message: String): MessageReceipt<OtherClient> = sendMessage(PlainText(message))
|
||||
public override suspend fun sendMessage(message: String): MessageReceipt<OtherClient> =
|
||||
sendMessage(PlainText(message))
|
||||
|
||||
@JvmBlockingBridge
|
||||
public override suspend fun sendMessage(message: Message): MessageReceipt<OtherClient> = client.sendMessage(message)
|
||||
@ -696,7 +701,10 @@ public class MemberCommandSenderOnMessage internal constructor(
|
||||
*/
|
||||
@Deprecated(
|
||||
"mirai 正计划支持其他渠道发起的临时会话, 届时此事件会变动. 原 TempCommandSenderOnMessage 已更改为 GroupTempCommandSenderOnMessage",
|
||||
replaceWith = ReplaceWith("GroupTempCommandSenderOnMessage", "net.mamoe.mirai.console.command.GroupTempCommandSenderOnMessage"),
|
||||
replaceWith = ReplaceWith(
|
||||
"GroupTempCommandSenderOnMessage",
|
||||
"net.mamoe.mirai.console.command.GroupTempCommandSenderOnMessage"
|
||||
),
|
||||
DeprecationLevel.ERROR
|
||||
)
|
||||
public sealed class TempCommandSenderOnMessage(
|
||||
|
@ -61,7 +61,12 @@ public abstract class RawCommand(
|
||||
override val overloads: List<@JvmWildcard CommandSignature> = listOf(
|
||||
CommandSignatureImpl(
|
||||
receiverParameter = CommandReceiverParameter(false, typeOf0<CommandSender>()),
|
||||
valueParameters = listOf(AbstractCommandValueParameter.UserDefinedType.createRequired<Array<out Message>>("args", true))
|
||||
valueParameters = listOf(
|
||||
AbstractCommandValueParameter.UserDefinedType.createRequired<Array<out Message>>(
|
||||
"args",
|
||||
true
|
||||
)
|
||||
)
|
||||
) { call ->
|
||||
val sender = call.caller
|
||||
val arguments = call.rawValueArguments
|
||||
|
@ -64,7 +64,10 @@ public abstract class SimpleCommand(
|
||||
reflector.findSubCommands().also {
|
||||
reflector.validate(it)
|
||||
if (it.isEmpty())
|
||||
throw IllegalCommandDeclarationException(this, "SimpleCommand must have at least one subcommand, whereas zero present.")
|
||||
throw IllegalCommandDeclarationException(
|
||||
this,
|
||||
"SimpleCommand must have at least one subcommand, whereas zero present."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,6 @@ import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.MessageContent
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
import kotlin.contracts.InvocationKind.EXACTLY_ONCE
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
@ -57,7 +55,8 @@ public interface CommandArgumentContext {
|
||||
) {
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
public fun <T : Any> ParserPair<T>.toPair(): Pair<KClass<T>, CommandValueArgumentParser<T>> = klass to parser
|
||||
public fun <T : Any> ParserPair<T>.toPair(): Pair<KClass<T>, CommandValueArgumentParser<T>> =
|
||||
klass to parser
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,10 @@ public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserE
|
||||
public object BooleanValueArgumentParser : InternalCommandValueArgumentParserExtensions<Boolean>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
|
||||
str.equals("true", ignoreCase = true)
|
||||
|| str.equals("yes", ignoreCase = true)
|
||||
|| str.equals("enabled", ignoreCase = true)
|
||||
|| str.equals("on", ignoreCase = true)
|
||||
|| str.equals("1", ignoreCase = true)
|
||||
|| str.equals("yes", ignoreCase = true)
|
||||
|| str.equals("enabled", ignoreCase = true)
|
||||
|| str.equals("on", ignoreCase = true)
|
||||
|| str.equals("1", ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,11 +217,21 @@ public object ExistingUserValueArgumentParser : InternalCommandValueArgumentPars
|
||||
""".trimIndent()
|
||||
|
||||
override fun parse(raw: String, sender: CommandSender): User {
|
||||
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
|
||||
return parseImpl(
|
||||
sender,
|
||||
raw,
|
||||
ExistingMemberValueArgumentParser::parse,
|
||||
ExistingFriendValueArgumentParser::parse
|
||||
)
|
||||
}
|
||||
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): User {
|
||||
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
|
||||
return parseImpl(
|
||||
sender,
|
||||
raw,
|
||||
ExistingMemberValueArgumentParser::parse,
|
||||
ExistingFriendValueArgumentParser::parse
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T> parseImpl(
|
||||
@ -444,8 +454,8 @@ public class EnumValueArgumentParser<T : Enum<T>>(
|
||||
}
|
||||
|
||||
val camelCaseDirection = if ((
|
||||
enums.map { it.name.lowercase() } + camelCase.map { it.first.lowercase() }
|
||||
).hasDuplicates()
|
||||
enums.map { it.name.lowercase() } + camelCase.map { it.first.lowercase() }
|
||||
).hasDuplicates()
|
||||
) { // 确认驼峰命名与源没有冲突
|
||||
emptyMap()
|
||||
} else {
|
||||
@ -469,7 +479,8 @@ public class EnumValueArgumentParser<T : Enum<T>>(
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class InternalCommandValueArgumentParserExtensions<T : Any> : AbstractCommandValueArgumentParser<T>() {
|
||||
internal abstract class InternalCommandValueArgumentParserExtensions<T : Any> :
|
||||
AbstractCommandValueArgumentParser<T>() {
|
||||
private fun String.parseToLongOrFail(): Long = toLongOrNull() ?: illegalArgument("无法解析 $this 为整数")
|
||||
|
||||
protected fun Long.findBotOrFail(): Bot = Bot.getInstanceOrNull(this) ?: illegalArgument("无法找到 Bot: $this")
|
||||
@ -502,11 +513,12 @@ internal abstract class InternalCommandValueArgumentParserExtensions<T : Any> :
|
||||
illegalArgument("无法找到成员 $idOrCard")
|
||||
} else {
|
||||
var index = 1
|
||||
illegalArgument("无法找到成员 $idOrCard。 多个成员满足搜索结果或匹配度不足: \n\n" +
|
||||
candidates.joinToString("\n", limit = 6) {
|
||||
val percentage = (it.second * 100).toDecimalPlace(0)
|
||||
"#${index++}(${percentage}%)${it.first.nameCardOrNick.truncate(10)}(${it.first.id})" // #1 15.4%
|
||||
}
|
||||
illegalArgument(
|
||||
"无法找到成员 $idOrCard。 多个成员满足搜索结果或匹配度不足: \n\n" +
|
||||
candidates.joinToString("\n", limit = 6) {
|
||||
val percentage = (it.second * 100).toDecimalPlace(0)
|
||||
"#${index++}(${percentage}%)${it.first.nameCardOrNick.truncate(10)}(${it.first.id})" // #1 15.4%
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,10 @@ public interface CommandValueParameter<T : Any?> : CommandParameter<T> {
|
||||
public fun accepts(argument: CommandValueArgument, commandArgumentContext: CommandArgumentContext?): Boolean =
|
||||
accepting(argument, commandArgumentContext).isAcceptable
|
||||
|
||||
public fun accepting(argument: CommandValueArgument, commandArgumentContext: CommandArgumentContext?): ArgumentAcceptance
|
||||
public fun accepting(
|
||||
argument: CommandValueArgument,
|
||||
commandArgumentContext: CommandArgumentContext?
|
||||
): ArgumentAcceptance
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
@ -155,7 +158,10 @@ public sealed class AbstractCommandValueParameter<T> : CommandValueParameter<T>,
|
||||
}
|
||||
}
|
||||
|
||||
public override fun accepting(argument: CommandValueArgument, commandArgumentContext: CommandArgumentContext?): ArgumentAcceptance {
|
||||
public override fun accepting(
|
||||
argument: CommandValueArgument,
|
||||
commandArgumentContext: CommandArgumentContext?
|
||||
): ArgumentAcceptance {
|
||||
if (isVararg) {
|
||||
val arrayElementType = this.type.arguments.single() // Array<T>
|
||||
return acceptingImpl(arrayElementType.type ?: ANY_TYPE, argument, commandArgumentContext)
|
||||
@ -205,7 +211,11 @@ public sealed class AbstractCommandValueParameter<T> : CommandValueParameter<T>,
|
||||
|
||||
override fun toString(): String = "<$expectingValue>"
|
||||
|
||||
override fun acceptingImpl(expectingType: KType, argument: CommandValueArgument, commandArgumentContext: CommandArgumentContext?): ArgumentAcceptance {
|
||||
override fun acceptingImpl(
|
||||
expectingType: KType,
|
||||
argument: CommandValueArgument,
|
||||
commandArgumentContext: CommandArgumentContext?
|
||||
): ArgumentAcceptance {
|
||||
return if (argument.value.content.equals(expectingValue, ignoreCase)) {
|
||||
ArgumentAcceptance.Direct
|
||||
} else ArgumentAcceptance.Impossible
|
||||
|
@ -125,7 +125,10 @@ public abstract class AbstractCommandValueArgumentParser<T : Any> : CommandValue
|
||||
@JvmStatic
|
||||
@JvmSynthetic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
protected inline fun CommandValueArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing =
|
||||
protected inline fun CommandValueArgumentParser<*>.illegalArgument(
|
||||
message: String,
|
||||
cause: Throwable? = null
|
||||
): Nothing =
|
||||
throw CommandArgumentParserException(message, cause)
|
||||
|
||||
/**
|
||||
|
@ -64,7 +64,8 @@ public object MessageContentTypeVariant : TypeVariant<MessageContent> {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override val outType: KType = typeOf<MessageContent>()
|
||||
override fun mapValue(valueArgument: Message): MessageContent =
|
||||
valueArgument.castOrNull<MessageContent>() ?: error("Accepts MessageContent only but given ${valueArgument.kClassQualifiedName}")
|
||||
valueArgument.castOrNull<MessageContent>()
|
||||
?: error("Accepts MessageContent only but given ${valueArgument.kClassQualifiedName}")
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
|
@ -28,7 +28,8 @@ import net.mamoe.mirai.message.data.toMessageChain
|
||||
@ExperimentalCommandDescriptors
|
||||
public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
override fun resolve(call: CommandCall): CommandResolveResult {
|
||||
val callee = CommandManager.matchCommand(call.calleeName) ?: return CommandResolveResult(CommandExecuteResult.UnresolvedCommand(call))
|
||||
val callee = CommandManager.matchCommand(call.calleeName)
|
||||
?: return CommandResolveResult(CommandExecuteResult.UnresolvedCommand(call))
|
||||
|
||||
val valueArguments = call.valueArguments
|
||||
val context = callee.safeCast<CommandArgumentContextAware>()?.context
|
||||
@ -95,7 +96,10 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
val receiverParameter = signature.receiverParameter
|
||||
if (receiverParameter?.type?.classifierAsKClass()?.isInstance(caller) == false) {
|
||||
errorSink.reportUnmatched(
|
||||
UnmatchedCommandSignature(signature, FailureReason.InapplicableReceiverArgument(receiverParameter, caller))
|
||||
UnmatchedCommandSignature(
|
||||
signature,
|
||||
FailureReason.InapplicableReceiverArgument(receiverParameter, caller)
|
||||
)
|
||||
)// not compatible receiver
|
||||
return null
|
||||
}
|
||||
@ -107,7 +111,12 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
val remainingParameters = valueParameters.drop(zipped.size).toMutableList()
|
||||
|
||||
if (remainingParameters.any { !it.isOptional && !it.isVararg }) {
|
||||
errorSink.reportUnmatched(UnmatchedCommandSignature(signature, FailureReason.NotEnoughArguments))// not enough args. // vararg can be empty.
|
||||
errorSink.reportUnmatched(
|
||||
UnmatchedCommandSignature(
|
||||
signature,
|
||||
FailureReason.NotEnoughArguments
|
||||
)
|
||||
)// not enough args. // vararg can be empty.
|
||||
return null
|
||||
}
|
||||
|
||||
@ -122,9 +131,13 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
if (valueArguments.size > valueParameters.size && zipped.last().first.isVararg) {
|
||||
// merge vararg arguments
|
||||
val (varargParameter, _)
|
||||
= zipped.removeLast()
|
||||
= zipped.removeLast()
|
||||
|
||||
zipped.add(varargParameter to DefaultCommandValueArgument(valueArguments.drop(zipped.size).map { it.value }.toMessageChain()))
|
||||
zipped.add(
|
||||
varargParameter to DefaultCommandValueArgument(
|
||||
valueArguments.drop(zipped.size).map { it.value }.toMessageChain()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// add default empty vararg argument
|
||||
val remainingVararg = remainingParameters.find { it.isVararg }
|
||||
@ -140,8 +153,12 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
argumentAcceptances = zipped.mapIndexed { index, (parameter, argument) ->
|
||||
val accepting = parameter.accepting(argument, context)
|
||||
if (accepting.isNotAcceptable) {
|
||||
errorSink.reportUnmatched(UnmatchedCommandSignature(signature,
|
||||
FailureReason.InapplicableValueArgument(parameter, argument)))// argument type not assignable
|
||||
errorSink.reportUnmatched(
|
||||
UnmatchedCommandSignature(
|
||||
signature,
|
||||
FailureReason.InapplicableValueArgument(parameter, argument)
|
||||
)
|
||||
)// argument type not assignable
|
||||
return null
|
||||
}
|
||||
ArgumentAcceptanceWithIndex(index, accepting)
|
||||
@ -173,7 +190,8 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
val candidates = list
|
||||
.asSequence().filterIsInstance<ResolveData>()
|
||||
.flatMap { phase ->
|
||||
phase.argumentAcceptances.filter { it.acceptance is ArgumentAcceptance.Direct }.map { phase to it }
|
||||
phase.argumentAcceptances.filter { it.acceptance is ArgumentAcceptance.Direct }
|
||||
.map { phase to it }
|
||||
}.toList()
|
||||
|
||||
candidates.singleOrNull()?.let { return it.first } // single Direct
|
||||
|
@ -77,7 +77,8 @@ public interface CommandCallResolver {
|
||||
@ExperimentalCommandDescriptors
|
||||
public fun CommandCall.resolve(): CommandResolveResult {
|
||||
GlobalComponentStorage.run {
|
||||
val instance = CommandCallResolverProvider.findSingletonInstance(CommandCallResolverProvider.builtinImplementation)
|
||||
val instance =
|
||||
CommandCallResolverProvider.findSingletonInstance(CommandCallResolverProvider.builtinImplementation)
|
||||
return instance.resolve(this@resolve)
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,10 @@ public class ResolvedCommandCallImpl(
|
||||
) : ResolvedCommandCall {
|
||||
override val resolvedValueArguments: List<ResolvedCommandValueArgument<*>> by lazy {
|
||||
calleeSignature.valueParameters.zip(rawValueArguments).map { (parameter, argument) ->
|
||||
val value = argument.mapToTypeOrNull(parameter.type) ?: context[parameter.type.classifierAsKClass()]?.parse(argument.value, caller)
|
||||
val value = argument.mapToTypeOrNull(parameter.type) ?: context[parameter.type.classifierAsKClass()]?.parse(
|
||||
argument.value,
|
||||
caller
|
||||
)
|
||||
?: throw NoValueArgumentMappingException(argument, parameter.type)
|
||||
// TODO: 2020/10/17 consider vararg and optional
|
||||
ResolvedCommandValueArgument(parameter.cast(), value)
|
||||
|
@ -60,7 +60,8 @@ public abstract class AbstractPluginData : PluginData, PluginDataImpl() {
|
||||
*/
|
||||
valueName: String,
|
||||
annotations: List<Annotation>,
|
||||
): T = value.apply { this@AbstractPluginData.valueNodes.add(ValueNode(valueName, this, annotations, this.serializer)) }
|
||||
): T =
|
||||
value.apply { this@AbstractPluginData.valueNodes.add(ValueNode(valueName, this, annotations, this.serializer)) }
|
||||
|
||||
/**
|
||||
* 使用 `by value()` 时自动调用此方法, 添加对 [Value] 的值修改的跟踪, 并创建 [ValueNode] 加入 [valueNodes]
|
||||
|
@ -18,7 +18,9 @@ import net.mamoe.mirai.console.internal.util.runIgnoreException
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import net.mamoe.mirai.console.util.TimedTask
|
||||
import net.mamoe.mirai.console.util.launchTimedTask
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.error
|
||||
import net.mamoe.mirai.utils.withSwitch
|
||||
|
||||
/**
|
||||
* 链接自动保存的 [PluginData].
|
||||
@ -52,7 +54,7 @@ public open class AutoSavePluginData private constructor(
|
||||
?.let { return }
|
||||
MiraiConsole.mainLogger.error(
|
||||
"An exception occurred when saving config ${this@AutoSavePluginData::class.qualifiedNameOrTip} " +
|
||||
"but CoroutineExceptionHandler not found in PluginDataHolder.coroutineContext for ${owner_::class.qualifiedNameOrTip}",
|
||||
"but CoroutineExceptionHandler not found in PluginDataHolder.coroutineContext for ${owner_::class.qualifiedNameOrTip}",
|
||||
e
|
||||
)
|
||||
}
|
||||
|
@ -221,7 +221,8 @@ public inline fun <reified T> PluginData.value(
|
||||
@ResolveContext(RESTRICTED_NO_ARG_CONSTRUCTOR)
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline fun <@ResolveContext(RESTRICTED_NO_ARG_CONSTRUCTOR) reified T>
|
||||
PluginData.value(apply: T.() -> Unit = {}): SerializerAwareValue<T> = valueImpl<T>(typeOf0<T>(), T::class).also { it.value.apply() }
|
||||
PluginData.value(apply: T.() -> Unit = {}): SerializerAwareValue<T> =
|
||||
valueImpl<T>(typeOf0<T>(), T::class).also { it.value.apply() }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@PublishedApi
|
||||
|
@ -37,4 +37,5 @@ import net.mamoe.mirai.console.data.PluginData
|
||||
* @see JAutoSavePluginData
|
||||
* @see PluginConfig
|
||||
*/
|
||||
public abstract class JAutoSavePluginConfig public constructor(saveName: String) : AutoSavePluginConfig(saveName), PluginConfig
|
||||
public abstract class JAutoSavePluginConfig public constructor(saveName: String) : AutoSavePluginConfig(saveName),
|
||||
PluginConfig
|
@ -69,7 +69,8 @@ import kotlin.reflect.full.createType
|
||||
*
|
||||
* @see PluginData
|
||||
*/
|
||||
public abstract class JAutoSavePluginData public constructor(saveName: String) : AutoSavePluginData(saveName), PluginConfig {
|
||||
public abstract class JAutoSavePluginData public constructor(saveName: String) : AutoSavePluginData(saveName),
|
||||
PluginConfig {
|
||||
|
||||
//// region JPluginData_value_primitives CODEGEN ////
|
||||
|
||||
|
@ -75,6 +75,11 @@ public abstract class AbstractSingletonExtensionPoint<E : SingletonExtension<T>,
|
||||
*/
|
||||
@ConsoleExperimentalApi
|
||||
public open val selectedInstance: T by lazy {
|
||||
GlobalComponentStorage.run { this@AbstractSingletonExtensionPoint.findSingletonInstance(extensionType, builtinImplementation) }
|
||||
GlobalComponentStorage.run {
|
||||
this@AbstractSingletonExtensionPoint.findSingletonInstance(
|
||||
extensionType,
|
||||
builtinImplementation
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -8,13 +8,17 @@ import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallInterceptorProvider : InstanceExtension<CommandCallInterceptor> {
|
||||
public companion object ExtensionPoint :
|
||||
AbstractInstanceExtensionPoint<CommandCallInterceptorProvider, CommandCallInterceptor>(CommandCallInterceptorProvider::class)
|
||||
AbstractInstanceExtensionPoint<CommandCallInterceptorProvider, CommandCallInterceptor>(
|
||||
CommandCallInterceptorProvider::class
|
||||
)
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallInterceptorProviderImpl(override val instance: CommandCallInterceptor) : CommandCallInterceptorProvider
|
||||
public class CommandCallInterceptorProviderImpl(override val instance: CommandCallInterceptor) :
|
||||
CommandCallInterceptorProvider
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public class CommandCallInterceptorProviderImplLazy(initializer: () -> CommandCallInterceptor) : CommandCallInterceptorProvider {
|
||||
public class CommandCallInterceptorProviderImplLazy(initializer: () -> CommandCallInterceptor) :
|
||||
CommandCallInterceptorProvider {
|
||||
override val instance: CommandCallInterceptor by lazy(initializer)
|
||||
}
|
@ -21,8 +21,10 @@ import net.mamoe.mirai.console.extension.InstanceExtension
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallParserProvider : InstanceExtension<CommandCallParser> {
|
||||
public companion object ExtensionPoint :
|
||||
AbstractInstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(CommandCallParserProvider::class,
|
||||
SpaceSeparatedCommandCallParser.Provider)
|
||||
AbstractInstanceExtensionPoint<CommandCallParserProvider, CommandCallParser>(
|
||||
CommandCallParserProvider::class,
|
||||
SpaceSeparatedCommandCallParser.Provider
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,10 @@ import net.mamoe.mirai.console.extension.SingletonExtension
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandCallResolverProvider : SingletonExtension<CommandCallResolver> {
|
||||
public companion object ExtensionPoint :
|
||||
AbstractSingletonExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(CommandCallResolverProvider::class, BuiltInCommandCallResolver)
|
||||
AbstractSingletonExtensionPoint<CommandCallResolverProvider, CommandCallResolver>(
|
||||
CommandCallResolverProvider::class,
|
||||
BuiltInCommandCallResolver
|
||||
)
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
|
@ -24,7 +24,10 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
*/
|
||||
public interface PermissionServiceProvider : SingletonExtension<PermissionService<*>> {
|
||||
public companion object ExtensionPoint :
|
||||
AbstractSingletonExtensionPoint<PermissionServiceProvider, PermissionService<*>>(PermissionServiceProvider::class, BuiltInPermissionService) {
|
||||
AbstractSingletonExtensionPoint<PermissionServiceProvider, PermissionService<*>>(
|
||||
PermissionServiceProvider::class,
|
||||
BuiltInPermissionService
|
||||
) {
|
||||
internal var permissionServiceOk = false
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
|
@ -124,7 +124,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
|
||||
mainLogger.info { "Starting mirai-console..." }
|
||||
mainLogger.info { "Backend: version $version, built on $buildDateFormatted." }
|
||||
mainLogger.info { frontEndDescription.render() }
|
||||
mainLogger.info { "Welcome to visit https://mirai.mamoe.net/"}
|
||||
mainLogger.info { "Welcome to visit https://mirai.mamoe.net/" }
|
||||
}
|
||||
|
||||
phase("check coroutineContext") {
|
||||
|
@ -61,7 +61,9 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by MiraiCons
|
||||
///// IMPL
|
||||
|
||||
|
||||
override fun getRegisteredCommands(owner: CommandOwner): List<Command> = _registeredCommands.filter { it.owner == owner }
|
||||
override fun getRegisteredCommands(owner: CommandOwner): List<Command> =
|
||||
_registeredCommands.filter { it.owner == owner }
|
||||
|
||||
override val allRegisteredCommands: List<Command> get() = _registeredCommands.toList() // copy
|
||||
override val commandPrefix: String get() = CommandConfig.commandPrefix
|
||||
override fun unregisterAllCommands(owner: CommandOwner) {
|
||||
|
@ -148,7 +148,11 @@ internal class CommandReflector(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun generateUsage(command: Command, annotationResolver: SubCommandAnnotationResolver?, overloads: Iterable<CommandSignature>): String {
|
||||
fun generateUsage(
|
||||
command: Command,
|
||||
annotationResolver: SubCommandAnnotationResolver?,
|
||||
overloads: Iterable<CommandSignature>
|
||||
): String {
|
||||
return overloads.joinToString("\n") { subcommand ->
|
||||
buildString {
|
||||
if (command.prefixOptional) {
|
||||
@ -250,7 +254,9 @@ internal class CommandReflector(
|
||||
var receiverParameter = function.extensionReceiverParameter
|
||||
if (receiverParameter == null && valueParameters.isNotEmpty()) {
|
||||
val valueFirstParameter = valueParameters[0]
|
||||
if (valueFirstParameter.type.classifierAsKClassOrNull()?.isSubclassOf(CommandSender::class) == true) {
|
||||
if (valueFirstParameter.type.classifierAsKClassOrNull()
|
||||
?.isSubclassOf(CommandSender::class) == true
|
||||
) {
|
||||
receiverParameter = valueFirstParameter
|
||||
valueParameters.removeAt(0)
|
||||
}
|
||||
@ -271,7 +277,8 @@ internal class CommandReflector(
|
||||
continue
|
||||
}
|
||||
val functionParameter =
|
||||
functionValueParameters[commandParameter] ?: error("Could not find a corresponding function parameter '${commandParameter.name}'")
|
||||
functionValueParameters[commandParameter]
|
||||
?: error("Could not find a corresponding function parameter '${commandParameter.name}'")
|
||||
args[functionParameter] = value
|
||||
}
|
||||
|
||||
@ -279,7 +286,7 @@ internal class CommandReflector(
|
||||
if (instanceParameter != null) {
|
||||
check(instanceParameter.type.classifierAsKClass().isInstance(command)) {
|
||||
"Bad command call resolved. " +
|
||||
"Function expects instance parameter ${instanceParameter.type} whereas actual instance is ${command::class}."
|
||||
"Function expects instance parameter ${instanceParameter.type} whereas actual instance is ${command::class}."
|
||||
}
|
||||
args[instanceParameter] = command
|
||||
}
|
||||
@ -287,7 +294,7 @@ internal class CommandReflector(
|
||||
if (receiverParameter != null) {
|
||||
check(receiverParameter.type.classifierAsKClass().isInstance(call.caller)) {
|
||||
"Bad command call resolved. " +
|
||||
"Function expects receiver parameter ${receiverParameter.type} whereas actual is ${call.caller::class}."
|
||||
"Function expects receiver parameter ${receiverParameter.type} whereas actual is ${call.caller::class}."
|
||||
}
|
||||
args[receiverParameter] = call.caller
|
||||
}
|
||||
@ -303,18 +310,29 @@ internal class CommandReflector(
|
||||
|
||||
private fun KParameter.toCommandReceiverParameter(): CommandReceiverParameter<out CommandSender> {
|
||||
check(!this.isVararg) { "Receiver cannot be vararg." }
|
||||
check(this.type.classifierAsKClass().isSubclassOf(CommandSender::class)) { "Receiver must be subclass of CommandSender" }
|
||||
check(
|
||||
this.type.classifierAsKClass().isSubclassOf(CommandSender::class)
|
||||
) { "Receiver must be subclass of CommandSender" }
|
||||
|
||||
return CommandReceiverParameter(this.type.isMarkedNullable, this.type)
|
||||
}
|
||||
|
||||
private fun createStringConstantParameterForName(index: Int, expectingValue: String): AbstractCommandValueParameter.StringConstant {
|
||||
private fun createStringConstantParameterForName(
|
||||
index: Int,
|
||||
expectingValue: String
|
||||
): AbstractCommandValueParameter.StringConstant {
|
||||
return AbstractCommandValueParameter.StringConstant("#$index", expectingValue, true)
|
||||
}
|
||||
|
||||
private fun KParameter.toUserDefinedCommandParameter(): AbstractCommandValueParameter.UserDefinedType<*> {
|
||||
return AbstractCommandValueParameter.UserDefinedType<Any?>(nameForCommandParameter(), this.isOptional, this.isVararg, this.type) // Any? is erased
|
||||
return AbstractCommandValueParameter.UserDefinedType<Any?>(
|
||||
nameForCommandParameter(),
|
||||
this.isOptional,
|
||||
this.isVararg,
|
||||
this.type
|
||||
) // Any? is erased
|
||||
}
|
||||
|
||||
private fun KParameter.nameForCommandParameter(): String? = annotationResolver.getAnnotatedName(command, this) ?: this.name
|
||||
private fun KParameter.nameForCommandParameter(): String? =
|
||||
annotationResolver.getAnnotatedName(command, this) ?: this.name
|
||||
}
|
@ -14,13 +14,17 @@ import net.mamoe.mirai.console.data.ValueDescription
|
||||
import net.mamoe.mirai.console.data.ValueName
|
||||
import net.mamoe.mirai.console.data.value
|
||||
|
||||
@ValueDescription("""
|
||||
@ValueDescription(
|
||||
"""
|
||||
内置指令系统配置
|
||||
""")
|
||||
"""
|
||||
)
|
||||
internal object CommandConfig : ReadOnlyPluginConfig("Command") {
|
||||
@ValueDescription("""
|
||||
@ValueDescription(
|
||||
"""
|
||||
指令前缀, 默认 "/"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
@ValueName("commandPrefix")
|
||||
val commandPrefix: String by value("/")
|
||||
}
|
@ -116,7 +116,8 @@ internal fun <K, V> PluginData.createCompositeMapValueImpl(
|
||||
valueToV: (Value<V>) -> V = Value<V>::value,
|
||||
applyToShadowedMap: ((MutableMap<K, V>) -> (MutableMap<K, V>))? = null
|
||||
): CompositeMapValueImpl<K, V> {
|
||||
return object : CompositeMapValueImpl<K, V>(mapInitializer, kToValue, vToValue, valueToK, valueToV, applyToShadowedMap) {
|
||||
return object :
|
||||
CompositeMapValueImpl<K, V>(mapInitializer, kToValue, vToValue, valueToK, valueToV, applyToShadowedMap) {
|
||||
override fun onChanged() = this@createCompositeMapValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ internal open class MultiFilePluginDataStorageImpl(
|
||||
// Just use mainLogger for convenience.
|
||||
MiraiConsole.mainLogger.warning(
|
||||
"Could not save ${instance.saveName} in YAML format due to exception in YAML encoder. " +
|
||||
"Please report this exception and relevant configurations to https://github.com/mamoe/mirai-console/issues/new",
|
||||
"Please report this exception and relevant configurations to https://github.com/mamoe/mirai-console/issues/new",
|
||||
it
|
||||
)
|
||||
json.encodeToString(instance.updaterSerializer, Unit)
|
||||
|
@ -107,6 +107,7 @@ internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue<Short>
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
||||
constructor()
|
||||
constructor(default: Int) {
|
||||
|
@ -56,7 +56,8 @@ public object AutoLoginConfig : AutoSavePluginConfig("AutoLogin") {
|
||||
|
||||
;
|
||||
|
||||
public object Parser : CommandValueArgumentParser<ConfigurationKey>, InternalCommandValueArgumentParserExtensions<ConfigurationKey>() {
|
||||
public object Parser : CommandValueArgumentParser<ConfigurationKey>,
|
||||
InternalCommandValueArgumentParserExtensions<ConfigurationKey>() {
|
||||
override fun parse(raw: String, sender: CommandSender): ConfigurationKey {
|
||||
val key = values().find { it.name.equals(raw, ignoreCase = true) }
|
||||
if (key != null) return key
|
||||
@ -70,7 +71,8 @@ public object AutoLoginConfig : AutoSavePluginConfig("AutoLogin") {
|
||||
PLAIN,
|
||||
MD5;
|
||||
|
||||
public object Parser : CommandValueArgumentParser<ConfigurationKey>, InternalCommandValueArgumentParserExtensions<ConfigurationKey>() {
|
||||
public object Parser : CommandValueArgumentParser<ConfigurationKey>,
|
||||
InternalCommandValueArgumentParserExtensions<ConfigurationKey>() {
|
||||
override fun parse(raw: String, sender: CommandSender): ConfigurationKey {
|
||||
val key = ConfigurationKey.values().find { it.name.equals(raw, ignoreCase = true) }
|
||||
if (key != null) return key
|
||||
|
@ -11,7 +11,10 @@ package net.mamoe.mirai.console.internal.data.builtins
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.data.*
|
||||
import net.mamoe.mirai.console.data.AutoSavePluginDataHolder
|
||||
import net.mamoe.mirai.console.data.PluginConfig
|
||||
import net.mamoe.mirai.console.data.PluginData
|
||||
import net.mamoe.mirai.console.data.PluginDataStorage
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope
|
||||
import net.mamoe.mirai.utils.minutesToMillis
|
||||
|
@ -15,14 +15,18 @@ import net.mamoe.mirai.console.data.value
|
||||
import net.mamoe.mirai.console.logging.AbstractLoggerController
|
||||
|
||||
internal object LoggerConfig : ReadOnlyPluginConfig("Logger") {
|
||||
@ValueDescription("""
|
||||
@ValueDescription(
|
||||
"""
|
||||
日志输出等级 可选值: ALL, VERBOSE, DEBUG, INFO, WARNING, ERROR, NONE
|
||||
""")
|
||||
"""
|
||||
)
|
||||
val defaultPriority by value(AbstractLoggerController.LogPriority.INFO)
|
||||
|
||||
@ValueDescription("""
|
||||
@ValueDescription(
|
||||
"""
|
||||
特定日志记录器输出等级
|
||||
""")
|
||||
"""
|
||||
)
|
||||
val loggers: Map<String, AbstractLoggerController.LogPriority> by value(
|
||||
mapOf(
|
||||
"example.logger" to AbstractLoggerController.LogPriority.NONE,
|
||||
|
@ -417,6 +417,7 @@ internal fun <K, V> MutableMap<K, V>.observable(onChanged: () -> Unit): MutableM
|
||||
|
||||
override fun replace(key: K, value: V): V? =
|
||||
this@observable.replace(key, value).also { onChanged() }
|
||||
|
||||
override fun computeIfAbsent(key: K, mappingFunction: Function<in K, out V>): V =
|
||||
this@observable.computeIfAbsent(key, mappingFunction).also { onChanged() }
|
||||
|
||||
|
@ -44,8 +44,8 @@ internal inline fun <reified T : PluginData> newPluginDataInstanceUsingReflectio
|
||||
?: createInstanceOrNull()
|
||||
?: throw IllegalArgumentException(
|
||||
"Cannot create PluginData instance. " +
|
||||
"PluginDataHolder supports PluginData implemented as an object " +
|
||||
"or the ones with a constructor which either has no parameters or all parameters of which are optional, by default newPluginDataInstance implementation."
|
||||
"PluginDataHolder supports PluginData implemented as an object " +
|
||||
"or the ones with a constructor which either has no parameters or all parameters of which are optional, by default newPluginDataInstance implementation."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ internal fun serializerMirai(type: KType): KSerializer<Any?> {
|
||||
}
|
||||
requireNotNull(rootClass.constructSerializerForGivenTypeArgs(*serializers.toTypedArray())) {
|
||||
"Can't find a method to construct serializer for type ${rootClass.simpleName}. " +
|
||||
"Make sure this class is marked as @Serializable or provide serializer explicitly."
|
||||
"Make sure this class is marked as @Serializable or provide serializer explicitly."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ internal fun KClass<*>.createInstanceSmart(): Any {
|
||||
|
||||
ConcurrentHashMap::class,
|
||||
ConcurrentMap::class,
|
||||
-> ConcurrentHashMap<Any?,Any?>()
|
||||
-> ConcurrentHashMap<Any?, Any?>()
|
||||
|
||||
else -> createInstanceOrNull()
|
||||
?: error("Cannot create instance or find a initial value for ${this.qualifiedNameOrTip}")
|
||||
|
@ -57,7 +57,12 @@ internal abstract class AbstractConcurrentComponentStorage : ComponentStorage {
|
||||
val userDefined = instances.getOrPut(this, ::CopyOnWriteArraySet) as Set<ExtensionRegistry<T>>
|
||||
|
||||
val builtins = if (this is AbstractInstanceExtensionPoint<*, *>) {
|
||||
this.builtinImplementations.mapTo(HashSet()) { DataExtensionRegistry(null, it) } as Set<ExtensionRegistry<T>>
|
||||
this.builtinImplementations.mapTo(HashSet()) {
|
||||
DataExtensionRegistry(
|
||||
null,
|
||||
it
|
||||
)
|
||||
} as Set<ExtensionRegistry<T>>
|
||||
} else null
|
||||
|
||||
return builtins?.plus(userDefined) ?: userDefined
|
||||
|
@ -121,8 +121,8 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService<P
|
||||
@Suppress("UNUSED_PARAMETER") primaryConstructorMark: Any?,
|
||||
) : AutoSavePluginConfig(saveName) {
|
||||
public val grantedPermissionMap: PluginDataExtensions.NotNullMutableMap<PermissionId, MutableSet<AbstractPermitteeId>>
|
||||
by value<MutableMap<PermissionId, MutableSet<AbstractPermitteeId>>>(ConcurrentHashMap())
|
||||
.withDefault { CopyOnWriteArraySet() }
|
||||
by value<MutableMap<PermissionId, MutableSet<AbstractPermitteeId>>>(ConcurrentHashMap())
|
||||
.withDefault { CopyOnWriteArraySet() }
|
||||
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
|
@ -271,7 +271,10 @@ internal class RequirementParser {
|
||||
val isStartingOfGroup = nextToken is Token.GroupBod.Left
|
||||
if (isStartingOfGroup != isEndingOfGroup) {
|
||||
fun getType(type: Boolean) = if (type) "`}`" else "<EOF>"
|
||||
next.ia(reader, "Except ${getType(isStartingOfGroup)} but got ${getType(isEndingOfGroup)}")
|
||||
next.ia(
|
||||
reader,
|
||||
"Except ${getType(isStartingOfGroup)} but got ${getType(isEndingOfGroup)}"
|
||||
)
|
||||
} else {
|
||||
// reader.insertToken = next
|
||||
break
|
||||
@ -284,7 +287,7 @@ internal class RequirementParser {
|
||||
fun getMode(type: Boolean) = if (type) "`&&`" else "`||`"
|
||||
next.ia(
|
||||
reader, "Cannot change logic mode after setting. " +
|
||||
"Except ${getMode(mode)} but got ${getMode(stx)}"
|
||||
"Except ${getMode(mode)} but got ${getMode(stx)}"
|
||||
)
|
||||
}
|
||||
chunks.add(process(reader))
|
||||
|
@ -84,10 +84,10 @@ internal object SemVersionInternal {
|
||||
}
|
||||
if (versionSelect.matches(trimmed)) {
|
||||
val regex = ("^" +
|
||||
trimmed.replace(".", "\\.")
|
||||
.replace("x", ".+") +
|
||||
"$"
|
||||
).toRegex()
|
||||
trimmed.replace(".", "\\.")
|
||||
.replace("x", ".+") +
|
||||
"$"
|
||||
).toRegex()
|
||||
return object : RequirementInternal {
|
||||
override fun test(version: SemVersion): Boolean = regex.matches(version.toString())
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ public interface JvmPlugin : Plugin, CoroutineScope,
|
||||
* @receiver 组件容器
|
||||
*/
|
||||
@RestrictedScope(COMMAND_REGISTER, PERMISSION_REGISTER)
|
||||
public fun PluginComponentStorage.onLoad() {}
|
||||
public fun PluginComponentStorage.onLoad() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 在插件被启用时调用, 可能会被调用多次
|
||||
|
@ -44,13 +44,16 @@ public interface JvmPluginDescription : PluginDescription {
|
||||
@JvmStatic
|
||||
public fun loadFromResource(
|
||||
filename: String = "plugin.yml",
|
||||
pluginClassloader: ClassLoader = CallerFinder.getCaller()?.findLoader() ?: error("Cannot find caller classloader, please specify manually."),
|
||||
pluginClassloader: ClassLoader = CallerFinder.getCaller()?.findLoader()
|
||||
?: error("Cannot find caller classloader, please specify manually."),
|
||||
): JvmPluginDescription {
|
||||
val stream = pluginClassloader.getResourceAsStream(filename) ?: error("Cannot find plugin description resource '$filename'")
|
||||
val stream = pluginClassloader.getResourceAsStream(filename)
|
||||
?: error("Cannot find plugin description resource '$filename'")
|
||||
|
||||
val bytes = stream.use { it.readBytes() }
|
||||
|
||||
return Yaml.decodeFromString(SimpleJvmPluginDescription.SerialData.serializer(), String(bytes)).toJvmPluginDescription()
|
||||
return Yaml.decodeFromString(SimpleJvmPluginDescription.SerialData.serializer(), String(bytes))
|
||||
.toJvmPluginDescription()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +125,14 @@ public open class AnsiMessageBuilder public constructor(
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
override fun append(c: Char): AnsiMessageBuilder = apply { delegate.append(c) }
|
||||
override fun append(csq: CharSequence?): AnsiMessageBuilder = apply { delegate.append(csq) }
|
||||
override fun append(csq: CharSequence?, start: Int, end: Int): AnsiMessageBuilder = apply { delegate.append(csq, start, end) }
|
||||
override fun append(csq: CharSequence?, start: Int, end: Int): AnsiMessageBuilder =
|
||||
apply { delegate.append(csq, start, end) }
|
||||
|
||||
public fun append(any: Any?): AnsiMessageBuilder = apply { delegate.append(any) }
|
||||
public fun append(value: String): AnsiMessageBuilder = apply { delegate.append(value) }
|
||||
public fun append(value: String, start: Int, end: Int): AnsiMessageBuilder = apply { delegate.append(value, start, end) }
|
||||
public fun append(value: String, start: Int, end: Int): AnsiMessageBuilder =
|
||||
apply { delegate.append(value, start, end) }
|
||||
|
||||
public fun append(value: Boolean): AnsiMessageBuilder = apply { delegate.append(value) }
|
||||
public fun append(value: Float): AnsiMessageBuilder = apply { delegate.append(value) }
|
||||
public fun append(value: Double): AnsiMessageBuilder = apply { delegate.append(value) }
|
||||
|
@ -18,7 +18,7 @@ import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.internal.util.ConsoleInputImpl
|
||||
|
||||
/**
|
||||
* Console 输入. 由于 console 接管了 [标准输入][System.in], [readLine] 等操作需要在这里进行.
|
||||
* Console 输入. 由于 console 接管了 [标准输入][System. in], [readLine] 等操作需要在这里进行.
|
||||
*/
|
||||
public interface ConsoleInput {
|
||||
/**
|
||||
|
@ -17,7 +17,8 @@ import net.mamoe.mirai.message.data.MessageContent
|
||||
@ConsoleExperimentalApi
|
||||
public object MessageUtils {
|
||||
@JvmStatic
|
||||
public fun MessageChain.messageContentsSequence(): Sequence<MessageContent> = asSequence().filterIsInstance<MessageContent>()
|
||||
public fun MessageChain.messageContentsSequence(): Sequence<MessageContent> =
|
||||
asSequence().filterIsInstance<MessageContent>()
|
||||
|
||||
@JvmStatic
|
||||
public fun MessageChain.firstContent(): MessageContent = messageContentsSequence().first()
|
||||
|
@ -154,7 +154,8 @@ internal constructor(
|
||||
@JvmStatic
|
||||
@JvmName("parse")
|
||||
@Throws(IllegalArgumentException::class, NumberFormatException::class)
|
||||
public operator fun invoke(@ResolveContext(SEMANTIC_VERSION) version: String): SemVersion = SemVersionInternal.parse(version)
|
||||
public operator fun invoke(@ResolveContext(SEMANTIC_VERSION) version: String): SemVersion =
|
||||
SemVersionInternal.parse(version)
|
||||
|
||||
/**
|
||||
* 解析一条依赖需求描述, 在无法解析的时候抛出 [IllegalArgumentException]
|
||||
@ -207,7 +208,8 @@ internal constructor(
|
||||
*/
|
||||
@JvmStatic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
public fun SemVersion.satisfies(@ResolveContext(VERSION_REQUIREMENT) requirement: String): Boolean = parseRangeRequirement(requirement).test(this)
|
||||
public fun SemVersion.satisfies(@ResolveContext(VERSION_REQUIREMENT) requirement: String): Boolean =
|
||||
parseRangeRequirement(requirement).test(this)
|
||||
|
||||
/** for Kotlin only */
|
||||
@JvmStatic
|
||||
@ -217,7 +219,8 @@ internal constructor(
|
||||
/** for Kotlin only */
|
||||
@JvmStatic
|
||||
@JvmSynthetic
|
||||
public operator fun Requirement.contains(@ResolveContext(SEMANTIC_VERSION) version: String): Boolean = test(version)
|
||||
public operator fun Requirement.contains(@ResolveContext(SEMANTIC_VERSION) version: String): Boolean =
|
||||
test(version)
|
||||
}
|
||||
|
||||
@Transient
|
||||
@ -260,10 +263,10 @@ internal constructor(
|
||||
public fun equals(other: SemVersion, deep: Boolean): Boolean {
|
||||
return if (deep) {
|
||||
(other.major == major
|
||||
&& other.minor == minor
|
||||
&& other.patch == patch
|
||||
&& other.identifier == identifier
|
||||
&& other.metadata == metadata)
|
||||
&& other.minor == minor
|
||||
&& other.patch == patch
|
||||
&& other.identifier == identifier
|
||||
&& other.metadata == metadata)
|
||||
} else {
|
||||
this.compareTo(other) == 0
|
||||
}
|
||||
|
@ -103,7 +103,12 @@ internal fun startupConsoleThread() {
|
||||
consoleLogger.warning { "权限不足." }
|
||||
}
|
||||
is UnmatchedSignature -> {
|
||||
consoleLogger.warning { "参数不匹配, 你是否想执行: \n" + result.failureReasons.render(result.command, result.call) }
|
||||
consoleLogger.warning {
|
||||
"参数不匹配, 你是否想执行: \n" + result.failureReasons.render(
|
||||
result.command,
|
||||
result.call
|
||||
)
|
||||
}
|
||||
}
|
||||
is Failure -> {
|
||||
consoleLogger.warning { result.toString() }
|
||||
@ -143,7 +148,8 @@ private fun List<CommandValueParameter<*>>.anyStringConstantUnmatched(arguments:
|
||||
@OptIn(ExperimentalCommandDescriptors::class)
|
||||
internal fun UnmatchedCommandSignature.render(command: Command): String {
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
val usage = net.mamoe.mirai.console.internal.command.CommandReflector.generateUsage(command, null, listOf(this.signature))
|
||||
val usage =
|
||||
net.mamoe.mirai.console.internal.command.CommandReflector.generateUsage(command, null, listOf(this.signature))
|
||||
return usage.trim() + " (${failureReason.render()})"
|
||||
}
|
||||
|
||||
|
@ -67,13 +67,13 @@ open class MiraiConsoleImplementationTerminal
|
||||
override val configStorageForBuiltIns: PluginDataStorage = MultiFilePluginDataStorage(rootPath.resolve("config")),
|
||||
) : MiraiConsoleImplementation, CoroutineScope by CoroutineScope(
|
||||
NamedSupervisorJob("MiraiConsoleImplementationTerminal") +
|
||||
CoroutineExceptionHandler { coroutineContext, throwable ->
|
||||
if (throwable is CancellationException) {
|
||||
return@CoroutineExceptionHandler
|
||||
}
|
||||
val coroutineName = coroutineContext[CoroutineName]?.name ?: "<unnamed>"
|
||||
MiraiConsole.mainLogger.error("Exception in coroutine $coroutineName", throwable)
|
||||
}) {
|
||||
CoroutineExceptionHandler { coroutineContext, throwable ->
|
||||
if (throwable is CancellationException) {
|
||||
return@CoroutineExceptionHandler
|
||||
}
|
||||
val coroutineName = coroutineContext[CoroutineName]?.name ?: "<unnamed>"
|
||||
MiraiConsole.mainLogger.error("Exception in coroutine $coroutineName", throwable)
|
||||
}) {
|
||||
override val consoleInput: ConsoleInput get() = ConsoleInputImpl
|
||||
override val isAnsiSupported: Boolean get() = true
|
||||
|
||||
@ -145,7 +145,8 @@ private object ConsoleFrontEndDescImpl : MiraiConsoleFrontEndDescription {
|
||||
|
||||
// net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.version
|
||||
// is console's version not frontend's version
|
||||
override val version: SemVersion = SemVersion(net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.versionConst)
|
||||
override val version: SemVersion =
|
||||
SemVersion(net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.versionConst)
|
||||
}
|
||||
|
||||
internal val ANSI_RESET = Ansi().reset().toString()
|
||||
|
@ -63,7 +63,8 @@ val RESOLVE_CONTEXT_FQ_NAME = FqName("net.mamoe.mirai.console.compiler.common.Re
|
||||
*/
|
||||
typealias ResolveContextKind = ResolveContext.Kind
|
||||
|
||||
fun ResolveContext.Kind.Companion.valueOfOrNull(string: String) = ResolveContext.Kind.values().find { it.name == string }
|
||||
fun ResolveContext.Kind.Companion.valueOfOrNull(string: String) =
|
||||
ResolveContext.Kind.values().find { it.name == string }
|
||||
|
||||
val Annotated.resolveContextKinds: List<ResolveContextKind>?
|
||||
get() {
|
||||
|
@ -143,4 +143,6 @@ internal val IGNORED_DEPENDENCIES_IN_SHADOW = arrayOf(
|
||||
"net.mamoe:kotlin-jvm-blocking-bridge-common",
|
||||
"net.mamoe:kotlin-jvm-blocking-bridge-metadata",
|
||||
"net.mamoe:kotlin-jvm-blocking-bridge-jvm"
|
||||
).map { it.toLowerCase() }.map { MiraiConsoleExtension.ExcludedDependency(it.substringBefore(':'), it.substringAfterLast(':')) }.toTypedArray()
|
||||
).map { it.toLowerCase() }
|
||||
.map { MiraiConsoleExtension.ExcludedDependency(it.substringBefore(':'), it.substringAfterLast(':')) }
|
||||
.toTypedArray()
|
@ -46,7 +46,8 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
kotlinOptions {
|
||||
if (this !is KotlinJvmOptions) return@kotlinOptions
|
||||
jvmTarget = miraiExtension.jvmTarget.toString()
|
||||
if (!miraiExtension.dontConfigureKotlinJvmDefault) freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||
if (!miraiExtension.dontConfigureKotlinJvmDefault) freeCompilerArgs =
|
||||
freeCompilerArgs + "-Xjvm-default=all"
|
||||
}
|
||||
}
|
||||
when (target.platformType) {
|
||||
@ -64,10 +65,15 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
private fun KotlinDependencyHandler.configureDependencies(project: Project, sourceSet: KotlinSourceSet, target: KotlinTarget) {
|
||||
private fun KotlinDependencyHandler.configureDependencies(
|
||||
project: Project,
|
||||
sourceSet: KotlinSourceSet,
|
||||
target: KotlinTarget
|
||||
) {
|
||||
val miraiExtension = project.miraiExtension
|
||||
|
||||
val isJvm = target.platformType == KotlinPlatformType.jvm || target.platformType == KotlinPlatformType.androidJvm
|
||||
val isJvm =
|
||||
target.platformType == KotlinPlatformType.jvm || target.platformType == KotlinPlatformType.androidJvm
|
||||
|
||||
if (!miraiExtension.noCoreApi) compileOnly("net.mamoe:mirai-core-api:${miraiExtension.coreVersion}")
|
||||
if (!miraiExtension.noConsole && isJvm) compileOnly("net.mamoe:mirai-console:${miraiExtension.consoleVersion}")
|
||||
@ -102,7 +108,11 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
tasks.findByName("shadowJar")?.enabled = false
|
||||
|
||||
fun registerBuildPluginTask(target: KotlinTarget, isSingleTarget: Boolean) {
|
||||
tasks.create("buildPlugin".wrapNameWithPlatform(target, isSingleTarget), BuildMiraiPluginTask::class.java, target).apply shadow@{
|
||||
tasks.create(
|
||||
"buildPlugin".wrapNameWithPlatform(target, isSingleTarget),
|
||||
BuildMiraiPluginTask::class.java,
|
||||
target
|
||||
).apply shadow@{
|
||||
group = "mirai"
|
||||
|
||||
archiveExtension.set("mirai.jar")
|
||||
@ -160,7 +170,8 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
}
|
||||
|
||||
internal val Project.miraiExtension: MiraiConsoleExtension
|
||||
get() = extensions.findByType(MiraiConsoleExtension::class.java) ?: error("Cannot find MiraiConsoleExtension in project ${this.name}")
|
||||
get() = extensions.findByType(MiraiConsoleExtension::class.java)
|
||||
?: error("Cannot find MiraiConsoleExtension in project ${this.name}")
|
||||
|
||||
internal val Project.kotlinTargets: Collection<KotlinTarget>
|
||||
get() {
|
||||
|
@ -89,7 +89,8 @@ private fun Project.registerPublishPluginTasks(target: KotlinTarget, isSingleTar
|
||||
group = "mirai"
|
||||
|
||||
val metadataFile =
|
||||
project.buildDir.resolve("mirai").resolve(if (isSingleTarget) "mirai-plugin.metadata" else "mirai-plugin-${target.name}.metadata")
|
||||
project.buildDir.resolve("mirai")
|
||||
.resolve(if (isSingleTarget) "mirai-plugin.metadata" else "mirai-plugin-${target.name}.metadata")
|
||||
outputs.file(metadataFile)
|
||||
|
||||
|
||||
@ -140,7 +141,8 @@ private fun Project.registerPublishPluginTasks(target: KotlinTarget, isSingleTar
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun File.renamed(block: File.(nameWithoutExtension: String) -> String): File = this.resolveSibling(block(this, nameWithoutExtension))
|
||||
internal inline fun File.renamed(block: File.(nameWithoutExtension: String) -> String): File =
|
||||
this.resolveSibling(block(this, nameWithoutExtension))
|
||||
|
||||
private fun Project.registerBintrayPublish() {
|
||||
val mirai = miraiExtension
|
||||
@ -191,7 +193,10 @@ private fun Project.registerMavenPublications(target: KotlinTarget, isSingleTarg
|
||||
url = uri("$buildDir/repo")
|
||||
}
|
||||
}*/
|
||||
publications.register("mavenJava".wrapNameWithPlatform(target, isSingleTarget), MavenPublication::class.java) { publication ->
|
||||
publications.register(
|
||||
"mavenJava".wrapNameWithPlatform(target, isSingleTarget),
|
||||
MavenPublication::class.java
|
||||
) { publication ->
|
||||
with(publication) {
|
||||
from(components["java"])
|
||||
|
||||
@ -213,7 +218,12 @@ private fun Project.registerMavenPublications(target: KotlinTarget, isSingleTarg
|
||||
artifact(tasks.filterIsInstance<BuildMiraiPluginTask>().single { it.target == target })
|
||||
artifact(
|
||||
mapOf(
|
||||
"source" to tasks.getByName("generatePluginMetadata".wrapNameWithPlatform(target, isSingleTarget)).outputs.files.singleFile,
|
||||
"source" to tasks.getByName(
|
||||
"generatePluginMetadata".wrapNameWithPlatform(
|
||||
target,
|
||||
isSingleTarget
|
||||
)
|
||||
).outputs.files.singleFile,
|
||||
"extension" to "mirai.metadata"
|
||||
)
|
||||
)
|
||||
|
@ -25,7 +25,8 @@
|
||||
<depends>com.intellij.gradle</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<moduleType id="MIRAI_MODULE_TYPE" implementationClass="net.mamoe.mirai.console.intellij.creator.MiraiModuleType"/>
|
||||
<moduleType id="MIRAI_MODULE_TYPE"
|
||||
implementationClass="net.mamoe.mirai.console.intellij.creator.MiraiModuleType"/>
|
||||
<moduleBuilder id="MIRAI_MODULE" builderClass="net.mamoe.mirai.console.intellij.creator.MiraiModuleBuilder"/>
|
||||
|
||||
<fileTemplateGroup implementation="net.mamoe.mirai.console.intellij.assets.FileTemplateRegistrar"/>
|
||||
|
@ -3,25 +3,26 @@ package $PACKAGE_NAME;
|
||||
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescriptionBuilder;
|
||||
|
||||
public final class ${CLASS_NAME} extends JavaPlugin {
|
||||
public static final ${CLASS_NAME} INSTANCE = new ${CLASS_NAME}();
|
||||
public final class ${CLASS_NAME} extends JavaPlugin{
|
||||
public static final ${CLASS_NAME} INSTANCE=new ${CLASS_NAME}();
|
||||
|
||||
#set($HAS_DETAILS = ${PLUGIN_AUTHOR} != "" || ${PLUGIN_DEPENDS_ON} != "" || ${PLUGIN_INFO} != "" || ${PLUGIN_NAME} != "")
|
||||
private ${CLASS_NAME}() {
|
||||
#if($HAS_DETAILS == false)
|
||||
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID", "$PLUGIN_VERSION").build());#end
|
||||
#if($HAS_DETAILS)
|
||||
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID", "$PLUGIN_VERSION")
|
||||
#if($PLUGIN_NAME != "").name("$PLUGIN_NAME")
|
||||
#end#if($PLUGIN_INFO != "").info("$PLUGIN_INFO")
|
||||
#end#if($PLUGIN_AUTHOR != "").author("$PLUGIN_AUTHOR")
|
||||
#end#if($PLUGIN_DEPENDS_ON != "").dependsOn("$PLUGIN_DEPENDS_ON")
|
||||
#end
|
||||
.build());#end
|
||||
}
|
||||
#set($HAS_DETAILS = ${PLUGIN_AUTHOR} != "" || ${PLUGIN_DEPENDS_ON} != "" || ${PLUGIN_INFO} != "" || ${PLUGIN_NAME} !=
|
||||
"")
|
||||
private ${CLASS_NAME}(){
|
||||
#if($HAS_DETAILS == false)
|
||||
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID","$PLUGIN_VERSION").build());#end
|
||||
#if($HAS_DETAILS)
|
||||
super(new JvmPluginDescriptionBuilder("$PLUGIN_ID","$PLUGIN_VERSION")
|
||||
#if($PLUGIN_NAME != "").name("$PLUGIN_NAME")
|
||||
#end#if($PLUGIN_INFO != "").info("$PLUGIN_INFO")
|
||||
#end#if($PLUGIN_AUTHOR != "").author("$PLUGIN_AUTHOR")
|
||||
#end#if($PLUGIN_DEPENDS_ON != "").dependsOn("$PLUGIN_DEPENDS_ON")
|
||||
#end
|
||||
.build());#end
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@Override
|
||||
public void onEnable(){
|
||||
getLogger().info("Plugin loaded!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
|
||||
package net.mamoe.mirai.console.intellij
|
||||
|
||||
import net.mamoe.mirai.console.compiler.common.castOrNull
|
||||
import net.mamoe.mirai.console.intellij.diagnostics.CommandDeclarationChecker
|
||||
import net.mamoe.mirai.console.intellij.diagnostics.ContextualParametersChecker
|
||||
import net.mamoe.mirai.console.intellij.diagnostics.PluginDataValuesChecker
|
||||
@ -52,7 +51,11 @@ class IDEContainerContributor : StorageComponentContainerContributor {
|
||||
class DeclarationCheckerIgnoringExceptions(
|
||||
private val delegate: DeclarationChecker
|
||||
) : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
runIgnoringErrors { delegate.check(declaration, descriptor, context) }
|
||||
}
|
||||
|
||||
@ -67,7 +70,8 @@ fun ModuleDescriptor.hasMiraiConsoleDependency(): Boolean {
|
||||
?: return false
|
||||
val facet = KotlinFacet.get(module) ?: return false
|
||||
val pluginClasspath =
|
||||
facet.configuration.settings.compilerArguments?.castOrNull<K2JVMCompilerArguments>()?.classpathAsList0 ?: return false
|
||||
facet.configuration.settings.compilerArguments?.castOrNull<K2JVMCompilerArguments>()?.classpathAsList0
|
||||
?: return false
|
||||
|
||||
if (pluginClasspath.none { path -> path.name.contains(pluginJpsJarName) }) return false
|
||||
return true
|
||||
|
@ -21,7 +21,8 @@ enum class MiraiVersionKind {
|
||||
override fun isThatKind(version: String): Boolean = version matches REGEX_STABLE
|
||||
},
|
||||
Prerelease {
|
||||
override fun isThatKind(version: String): Boolean = !version.contains("-dev") // && (version.contains("-M") || version.contains("-RC"))
|
||||
override fun isThatKind(version: String): Boolean =
|
||||
!version.contains("-dev") // && (version.contains("-M") || version.contains("-RC"))
|
||||
},
|
||||
Nightly {
|
||||
override fun isThatKind(version: String): Boolean = true // version.contains("-dev")
|
||||
|
@ -70,7 +70,12 @@ sealed class GradleProjectCreator(
|
||||
VfsUtil.createDirectoryIfMissing(root, "src/main/${model.languageType.sourceSetDirName}")
|
||||
VfsUtil.createDirectoryIfMissing(root, "src/main/resources")
|
||||
addFileChanged(root.writeChild(model.languageType.pluginMainClassFile(this)))
|
||||
addFileChanged(root.writeChild("src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin", model.mainClassQualifiedName))
|
||||
addFileChanged(
|
||||
root.writeChild(
|
||||
"src/main/resources/META-INF/services/net.mamoe.mirai.console.plugin.jvm.JvmPlugin",
|
||||
model.mainClassQualifiedName
|
||||
)
|
||||
)
|
||||
addFileChanged(root.writeChild(".gitignore", getTemplate(FT.Gitignore)))
|
||||
addFileChanged(root.writeChild("gradle.properties", getTemplate(FT.GradleProperties)))
|
||||
addFileChanged(root.writeChild("src/test/kotlin/RunTerminal.kt", getTemplate(FT.RunTerminal)))
|
||||
|
@ -26,14 +26,15 @@ interface ILanguageType {
|
||||
|
||||
sealed class LanguageType : ILanguageType {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T: String?> escapeString(string: T): T {
|
||||
fun <T : String?> escapeString(string: T): T {
|
||||
string ?: return null as T
|
||||
return string
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\"", "\\\"") as T
|
||||
}
|
||||
abstract fun <T: String?> escapeRawString(string: T): T
|
||||
|
||||
abstract fun <T : String?> escapeRawString(string: T): T
|
||||
|
||||
companion object {
|
||||
val DEFAULT = Kotlin
|
||||
@ -66,6 +67,7 @@ sealed class LanguageType : ILanguageType {
|
||||
content = creator.project.getTemplate(FT.PluginMainJava, templateProperties)
|
||||
)
|
||||
}
|
||||
|
||||
override fun <T : String?> escapeRawString(string: T): T = escapeString(string)
|
||||
}
|
||||
}
|
@ -103,7 +103,10 @@ class PluginCoordinatesStep(
|
||||
.forEach { v -> miraiVersionBox.addItem(v) }
|
||||
},
|
||||
onFailure = { e ->
|
||||
Validation.popup("Failed to download version list, please select a version by yourself. \nCause: ${e.cause ?: e}", miraiVersionBox)
|
||||
Validation.popup(
|
||||
"Failed to download version list, please select a version by yourself. \nCause: ${e.cause ?: e}",
|
||||
miraiVersionBox
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -118,6 +118,7 @@ class Validation {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var result = true
|
||||
for (prop in step::class.java.declaredFields) {
|
||||
if (!validateProperty(prop)) result = false
|
||||
|
@ -32,7 +32,9 @@ val Path.vfOrNull: VirtualFile?
|
||||
val Path.vf: VirtualFile
|
||||
get() = vfOrNull ?: error("Failed to resolve VirtualFile ${this.toAbsolutePath()}")
|
||||
|
||||
fun VirtualFile.readText(): String? = if (this.exists() && !this.isDirectory) String(inputStream.use { it.readBytes() }) else null
|
||||
fun VirtualFile.readText(): String? =
|
||||
if (this.exists() && !this.isDirectory) String(inputStream.use { it.readBytes() }) else null
|
||||
|
||||
fun VirtualFile.readChildText(relative: String): String? = this.resolve(relative)?.readText()
|
||||
|
||||
fun VirtualFile.resolve(relative: String): VirtualFile? = VfsUtil.findRelativeFile(
|
||||
|
@ -23,7 +23,11 @@ import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
|
||||
class CommandDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
if (declaration !is KtNamedFunction) return
|
||||
|
||||
// exclusive checks or return
|
||||
|
@ -72,7 +72,12 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
elementChecker(context, argument.asElement(), argument, null)?.let { context.report(it) }
|
||||
} else {
|
||||
for (resolvedConstant in resolvedConstants) {
|
||||
elementChecker(context, argument.asElement(), argument, resolvedConstant)?.let { context.report(it) }
|
||||
elementChecker(
|
||||
context,
|
||||
argument.asElement(),
|
||||
argument,
|
||||
resolvedConstant
|
||||
)?.let { context.report(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,7 +87,8 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
private val ID_REGEX: Regex = CheckerConstants.PLUGIN_ID_REGEX
|
||||
private val FORBIDDEN_ID_NAMES: Array<String> = CheckerConstants.PLUGIN_FORBIDDEN_NAMES
|
||||
|
||||
private const val syntax = """类似于 "net.mamoe.mirai.example-plugin", 其中 "net.mamoe.mirai" 为 groupId, "example-plugin" 为插件名"""
|
||||
private const val syntax =
|
||||
"""类似于 "net.mamoe.mirai.example-plugin", 其中 "net.mamoe.mirai" 为 groupId, "example-plugin" 为插件名"""
|
||||
|
||||
const val SEMANTIC_VERSIONING_PATTERN =
|
||||
"""^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?${'$'}"""
|
||||
@ -102,7 +108,10 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
val lowercaseId = value.toLowerCase()
|
||||
|
||||
if (ID_REGEX.matchEntire(value) == null) {
|
||||
return ILLEGAL_PLUGIN_DESCRIPTION.on(inspectionTarget, "插件 Id 无效. 正确的插件 Id 应该满足正则表达式 '${ID_REGEX.pattern}', \n$syntax")
|
||||
return ILLEGAL_PLUGIN_DESCRIPTION.on(
|
||||
inspectionTarget,
|
||||
"插件 Id 无效. 正确的插件 Id 应该满足正则表达式 '${ID_REGEX.pattern}', \n$syntax"
|
||||
)
|
||||
}
|
||||
|
||||
FORBIDDEN_ID_NAMES.firstOrNull { it == lowercaseId }?.let { illegal ->
|
||||
@ -122,7 +131,10 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
|
||||
fun checkPluginVersion(inspectionTarget: KtElement, value: String): Diagnostic? {
|
||||
if (!SEMANTIC_VERSIONING_REGEX.matches(value)) {
|
||||
return ILLEGAL_PLUGIN_DESCRIPTION.on(inspectionTarget, "版本号无效: '$value'. \nhttps://semver.org/lang/zh-CN/")
|
||||
return ILLEGAL_PLUGIN_DESCRIPTION.on(
|
||||
inspectionTarget,
|
||||
"版本号无效: '$value'. \nhttps://semver.org/lang/zh-CN/"
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -140,7 +152,11 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
fun checkPermissionNamespace(inspectionTarget: KtElement, value: String): Diagnostic? {
|
||||
return when {
|
||||
value.isBlank() -> ILLEGAL_PERMISSION_NAMESPACE.on(inspectionTarget, value, "权限命名空间不能为空")
|
||||
value.any { it.isWhitespace() } -> ILLEGAL_PERMISSION_NAMESPACE.on(inspectionTarget, value, "不允许权限命名空间中存在空格")
|
||||
value.any { it.isWhitespace() } -> ILLEGAL_PERMISSION_NAMESPACE.on(
|
||||
inspectionTarget,
|
||||
value,
|
||||
"不允许权限命名空间中存在空格"
|
||||
)
|
||||
value.contains(':') -> ILLEGAL_PERMISSION_NAMESPACE.on(inspectionTarget, value, "权限命名空间不允许包含 ':'")
|
||||
else -> null
|
||||
}
|
||||
@ -159,7 +175,11 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
return when {
|
||||
value.isBlank() -> ILLEGAL_PERMISSION_ID.on(inspectionTarget, value, "权限 Id 不能为空")
|
||||
value.any { it.isWhitespace() } -> ILLEGAL_PERMISSION_ID.on(inspectionTarget, value, "暂时不允许权限 Id 中存在空格")
|
||||
value.count { it == ':' } != 1 -> ILLEGAL_PERMISSION_ID.on(inspectionTarget, value, "权限 Id 必须为 \"命名空间:名称\". 且命名空间和名称均不能包含 ':'")
|
||||
value.count { it == ':' } != 1 -> ILLEGAL_PERMISSION_ID.on(
|
||||
inspectionTarget,
|
||||
value,
|
||||
"权限 Id 必须为 \"命名空间:名称\". 且命名空间和名称均不能包含 ':'"
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@ -174,7 +194,11 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
fun checkConsoleCommandOwner(context: DeclarationCheckerContext, inspectionTarget: KtElement, argument: ValueArgument): Diagnostic? {
|
||||
fun checkConsoleCommandOwner(
|
||||
context: DeclarationCheckerContext,
|
||||
inspectionTarget: KtElement,
|
||||
argument: ValueArgument
|
||||
): Diagnostic? {
|
||||
val expr = argument.getArgumentExpression() ?: return null
|
||||
|
||||
if (expr is KtReferenceExpression) {
|
||||
@ -188,7 +212,12 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
}
|
||||
|
||||
fun interface ElementChecker {
|
||||
operator fun invoke(context: DeclarationCheckerContext, declaration: KtElement, valueArgument: ValueArgument, value: String?): Diagnostic?
|
||||
operator fun invoke(
|
||||
context: DeclarationCheckerContext,
|
||||
declaration: KtElement,
|
||||
valueArgument: ValueArgument,
|
||||
value: String?
|
||||
): Diagnostic?
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@ -202,13 +231,19 @@ class ContextualParametersChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
fun put(key: ResolveContextKind, value: KFunction2<KtElement, ValueArgument, Diagnostic?>): ElementChecker? {
|
||||
fun put(
|
||||
key: ResolveContextKind,
|
||||
value: KFunction2<KtElement, ValueArgument, Diagnostic?>
|
||||
): ElementChecker? {
|
||||
return put(key) { _, d, v, _ ->
|
||||
value(d, v)
|
||||
}
|
||||
}
|
||||
|
||||
fun put(key: ResolveContextKind, value: (DeclarationCheckerContext, KtElement, ValueArgument) -> Diagnostic?): ElementChecker? {
|
||||
fun put(
|
||||
key: ResolveContextKind,
|
||||
value: (DeclarationCheckerContext, KtElement, ValueArgument) -> Diagnostic?
|
||||
): ElementChecker? {
|
||||
return put(key) { c, d, v, _ ->
|
||||
value(c, d, v)
|
||||
}
|
||||
|
@ -37,7 +37,11 @@ class PluginDataValuesChecker : DeclarationChecker {
|
||||
/**
|
||||
* [KtObjectDeclaration], [KtParameter], [KtPrimaryConstructor], [KtClass], [KtNamedFunction], [KtProperty]
|
||||
*/
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
val bindingContext = context.bindingContext
|
||||
|
||||
//println(declaration::class.qualifiedName + "\t:" + declaration.text.take(10))
|
||||
@ -65,25 +69,32 @@ class PluginDataValuesChecker : DeclarationChecker {
|
||||
|
||||
private fun KtProperty.isInsideOrExtensionOfReadOnlyPluginData(): Boolean {
|
||||
return containingClassOrObject?.hasSuperType(READ_ONLY_PLUGIN_DATA_FQ_NAME) == true // inside
|
||||
|| receiverTypeReference?.hasSuperType(READ_ONLY_PLUGIN_DATA_FQ_NAME) == true // extension
|
||||
|| receiverTypeReference?.hasSuperType(READ_ONLY_PLUGIN_DATA_FQ_NAME) == true // extension
|
||||
}
|
||||
|
||||
private fun checkReadOnly(property: KtProperty, context: DeclarationCheckerContext) {
|
||||
// first parent is KtPropertyDelegate, next is KtProperty
|
||||
|
||||
if (property.isVar // var
|
||||
&& property.delegateExpression?.getResolvedCall(context)?.isCalling(PLUGIN_DATA_VALUE_FUNCTIONS_FQ_FQ_NAME) == true // by value()
|
||||
&& property.delegateExpression?.getResolvedCall(context)
|
||||
?.isCalling(PLUGIN_DATA_VALUE_FUNCTIONS_FQ_FQ_NAME) == true // by value()
|
||||
&& property.isInsideOrExtensionOfReadOnlyPluginData() // extensionReceiver is ReadOnlyPluginData or null
|
||||
) {
|
||||
context.report(MiraiConsoleErrors.READ_ONLY_VALUE_CANNOT_BE_VAR.on(property.valOrVarKeyword))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkConstructableAndSerializable(call: ResolvedCall<out CallableDescriptor>, expr: KtCallExpression, context: DeclarationCheckerContext) {
|
||||
private fun checkConstructableAndSerializable(
|
||||
call: ResolvedCall<out CallableDescriptor>,
|
||||
expr: KtCallExpression,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
if (call.resultingDescriptor.resolveContextKinds?.contains(ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR) != true) return
|
||||
|
||||
for ((typeParameterDescriptor, kotlinType) in call.typeArguments.entries) {
|
||||
if ((typeParameterDescriptor.isReified || typeParameterDescriptor.resolveContextKinds?.contains(ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR) == true)
|
||||
if ((typeParameterDescriptor.isReified || typeParameterDescriptor.resolveContextKinds?.contains(
|
||||
ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR
|
||||
) == true)
|
||||
&& kotlinType is SimpleType
|
||||
) {
|
||||
|
||||
@ -124,7 +135,11 @@ class PluginDataValuesChecker : DeclarationChecker {
|
||||
context.report(factory.on(inspectionTarget, callExpr, jetTypeFqn.substringAfterLast('.')))
|
||||
}
|
||||
|
||||
private fun checkConstructableAndSerializable(type: KotlinType, callExpr: KtCallExpression, context: DeclarationCheckerContext) {
|
||||
private fun checkConstructableAndSerializable(
|
||||
type: KotlinType,
|
||||
callExpr: KtCallExpression,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
val classDescriptor = type.classDescriptor() ?: return
|
||||
|
||||
if (canBeSerializedInternally(classDescriptor)) return
|
||||
|
@ -21,7 +21,6 @@ import net.mamoe.mirai.console.compiler.common.resolve.PLUGIN_FQ_NAME
|
||||
import net.mamoe.mirai.console.intellij.diagnostics.fix.ConfigurePluginMainServiceFix
|
||||
import net.mamoe.mirai.console.intellij.resolve.allSuperNames
|
||||
import net.mamoe.mirai.console.intellij.resolve.hasAnnotation
|
||||
import org.jetbrains.kotlin.idea.debugger.readAction
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||
import org.jetbrains.kotlin.idea.util.module
|
||||
import org.jetbrains.kotlin.idea.util.rootManager
|
||||
@ -51,7 +50,7 @@ class PluginMainServiceNotConfiguredInspection : AbstractKotlinInspection() {
|
||||
val fqName = element.fqName?.asString() ?: return@visitor
|
||||
|
||||
val found = isServiceConfiguredWithAutoService(element)
|
||||
|| isServiceConfiguredWithResource(element, fqName)
|
||||
|| isServiceConfiguredWithResource(element, fqName)
|
||||
|
||||
if (!found) {
|
||||
registerProblemImpl(holder, element, fqName)
|
||||
|
@ -18,8 +18,12 @@ import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinCrossLanguageQuickFixAction
|
||||
|
||||
|
||||
fun <T: PsiElement> LocalQuickFix(text: String, element: T, invokeAction: QuickFixInvoke<T>.() -> Unit): LocalQuickFix {
|
||||
return object: KotlinCrossLanguageQuickFixAction<T>(element), KotlinUniversalQuickFix {
|
||||
fun <T : PsiElement> LocalQuickFix(
|
||||
text: String,
|
||||
element: T,
|
||||
invokeAction: QuickFixInvoke<T>.() -> Unit
|
||||
): LocalQuickFix {
|
||||
return object : KotlinCrossLanguageQuickFixAction<T>(element), KotlinUniversalQuickFix {
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
override fun getFamilyName(): String = "Mirai console"
|
||||
override fun getText(): String = text
|
||||
|
@ -71,11 +71,19 @@ fun KtReferenceExpression.resolveCalleeFunction(): KtNamedFunction? {
|
||||
return originalCallee
|
||||
}
|
||||
|
||||
fun KtNamedFunction.isNamedMemberFunctionOf(className: String, functionName: String, extensionReceiver: String? = null): Boolean {
|
||||
fun KtNamedFunction.isNamedMemberFunctionOf(
|
||||
className: String,
|
||||
functionName: String,
|
||||
extensionReceiver: String? = null
|
||||
): Boolean {
|
||||
if (extensionReceiver != null) {
|
||||
if (this.receiverTypeReference?.resolveReferencedType()?.getKotlinFqName()?.toString() != extensionReceiver) return false
|
||||
if (this.receiverTypeReference?.resolveReferencedType()?.getKotlinFqName()
|
||||
?.toString() != extensionReceiver
|
||||
) return false
|
||||
}
|
||||
return this.name == functionName && this.containingClassOrObject?.allSuperTypes?.any { it.getKotlinFqName()?.toString() == className } == true
|
||||
return this.name == functionName && this.containingClassOrObject?.allSuperTypes?.any {
|
||||
it.getKotlinFqName()?.toString() == className
|
||||
} == true
|
||||
}
|
||||
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
@ -110,7 +118,8 @@ object ResourceNotClosedInspectionProcessors {
|
||||
|
||||
if (!parent.receiverExpression.isCallingExternalResourceCreators()) return
|
||||
|
||||
class Fix(private val functionName: String) : KotlinCrossLanguageQuickFixAction<KtDotQualifiedExpression>(parent), KotlinUniversalQuickFix {
|
||||
class Fix(private val functionName: String) :
|
||||
KotlinCrossLanguageQuickFixAction<KtDotQualifiedExpression>(parent), KotlinUniversalQuickFix {
|
||||
override fun getFamilyName(): String = FAMILY_NAME
|
||||
override fun getText(): String = "修复 $functionName"
|
||||
|
||||
|
@ -14,7 +14,6 @@ import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementFactory
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.PsiFile
|
||||
import net.mamoe.mirai.console.intellij.resolve.*
|
||||
@ -68,7 +67,7 @@ class UsingStringPlusMessageInspection : AbstractKotlinInspection() {
|
||||
// complex expressions, e.g. `str.toString().plus(msg)`, `"".also { }.plus(msg)`
|
||||
val replaced =
|
||||
element.replace(KtPsiFactory(project).createExpression("net.mamoe.mirai.message.data.PlainText(${element.text})"))
|
||||
as? KtElement ?: return
|
||||
as? KtElement ?: return
|
||||
ShortenReferences.DEFAULT.process(replaced)
|
||||
return
|
||||
}
|
||||
@ -77,7 +76,7 @@ class UsingStringPlusMessageInspection : AbstractKotlinInspection() {
|
||||
val receiver = element.getQualifiedExpressionForReceiver() ?: return
|
||||
val replaced = receiver
|
||||
.replace(KtPsiFactory(project).createExpression("net.mamoe.mirai.message.data.PlainText(${receiver.text})"))
|
||||
as? KtElement ?: return
|
||||
as? KtElement ?: return
|
||||
|
||||
ShortenReferences.DEFAULT.process(replaced)
|
||||
}
|
||||
@ -118,7 +117,8 @@ class UsingStringPlusMessageInspection : AbstractKotlinInspection() {
|
||||
}
|
||||
)
|
||||
} else {
|
||||
val nameReferenceExpression = expression.findChild<KtNameReferenceExpression>() ?: expression.calleeExpression ?: expression
|
||||
val nameReferenceExpression =
|
||||
expression.findChild<KtNameReferenceExpression>() ?: expression.calleeExpression ?: expression
|
||||
holder.registerProblem(
|
||||
nameReferenceExpression,
|
||||
DESCRIPTION,
|
||||
@ -138,7 +138,8 @@ class UsingStringPlusMessageInspection : AbstractKotlinInspection() {
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = Visitor(holder)
|
||||
|
||||
abstract class ConvertToPlainTextFix<T : PsiElement>(element: T) : KotlinCrossLanguageQuickFixAction<T>(element), KotlinUniversalQuickFix {
|
||||
abstract class ConvertToPlainTextFix<T : PsiElement>(element: T) : KotlinCrossLanguageQuickFixAction<T>(element),
|
||||
KotlinUniversalQuickFix {
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
override fun getFamilyName(): String = "Mirai Console"
|
||||
|
||||
|
@ -30,7 +30,8 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
|
||||
|
||||
fun KotlinType.isSubtypeOfReadOnlyPluginData(): Boolean {
|
||||
return this.toClassDescriptor?.getAllSuperClassifiers()?.any { it.fqNameOrNull() == READ_ONLY_PLUGIN_DATA_FQ_NAME } == true
|
||||
return this.toClassDescriptor?.getAllSuperClassifiers()
|
||||
?.any { it.fqNameOrNull() == READ_ONLY_PLUGIN_DATA_FQ_NAME } == true
|
||||
}
|
||||
|
||||
fun DeclarationCheckerContext.report(diagnostic: Diagnostic) {
|
||||
|
@ -43,7 +43,9 @@ class AddSerializerFix(
|
||||
|
||||
companion object : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val classDescriptor = diagnostic.castOrNull<DiagnosticWithParameters1<*, *>>()?.a?.castOrNull<ClassDescriptor>() ?: return null
|
||||
val classDescriptor =
|
||||
diagnostic.castOrNull<DiagnosticWithParameters1<*, *>>()?.a?.castOrNull<ClassDescriptor>()
|
||||
?: return null
|
||||
val ktClassOrObject = classDescriptor.findPsi()?.castOrNull<KtClassOrObject>() ?: return null
|
||||
return AddSerializerFix(ktClassOrObject)
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ class ProvideDefaultValueFix(
|
||||
ImportInsertHelper.getInstance(project).importDescriptor(file, referee)
|
||||
*/
|
||||
|
||||
val typeName = typeProjection.element?.typeReference?.typeElement?.castOrNull<KtUserType>()?.referencedName ?: return
|
||||
val typeName =
|
||||
typeProjection.element?.typeReference?.typeElement?.castOrNull<KtUserType>()?.referencedName ?: return
|
||||
val argumentList = element.findChild<KtValueArgumentList>() ?: return
|
||||
val offset = argumentList.leftParenthesis?.endOffset ?: return
|
||||
|
||||
@ -62,7 +63,8 @@ class ProvideDefaultValueFix(
|
||||
|
||||
companion object : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val diagnostic1 = diagnostic.castOrNull<DiagnosticWithParameters2<KtTypeProjection, KtCallExpression, *>>() ?: return null
|
||||
val diagnostic1 =
|
||||
diagnostic.castOrNull<DiagnosticWithParameters2<KtTypeProjection, KtCallExpression, *>>() ?: return null
|
||||
return ProvideDefaultValueFix(diagnostic1.a, SmartPointerManager.createPointer(diagnostic1.psiElement))
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,8 @@ import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
/**
|
||||
* @since 2.4
|
||||
*/
|
||||
class WrapWithResourceUseCallIntention : SelfTargetingIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, { "转换为 .use" }) {
|
||||
class WrapWithResourceUseCallIntention :
|
||||
SelfTargetingIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, { "转换为 .use" }) {
|
||||
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) {
|
||||
val selectorExpression = element.selectorExpression ?: return
|
||||
selectorExpression.replaceExpressionAndShortenReferences("use { it.${selectorExpression.text} }")
|
||||
@ -48,7 +49,8 @@ class WrapWithResourceUseCallIntention : SelfTargetingIntention<KtDotQualifiedEx
|
||||
* to be supported by 2.5
|
||||
* @since 2.4
|
||||
*/
|
||||
class WrapWithResourceUseCallJavaIntention : SelfTargetingIntention<PsiMethodCallExpression>(PsiMethodCallExpression::class.java, { "转换为 .use" }) {
|
||||
class WrapWithResourceUseCallJavaIntention :
|
||||
SelfTargetingIntention<PsiMethodCallExpression>(PsiMethodCallExpression::class.java, { "转换为 .use" }) {
|
||||
override fun applyTo(element: PsiMethodCallExpression, editor: Editor?) {
|
||||
// val selectorExpression = element.methodExpression
|
||||
|
||||
|
@ -65,7 +65,8 @@ class FunctionSignatureBuilder {
|
||||
this.returnType = FqName(returnType)
|
||||
}
|
||||
|
||||
fun build(): FunctionSignature = FunctionSignature(name, dispatchReceiver, extensionReceiver, parameters, returnType)
|
||||
fun build(): FunctionSignature =
|
||||
FunctionSignature(name, dispatchReceiver, extensionReceiver, parameters, returnType)
|
||||
}
|
||||
|
||||
fun FunctionSignatureBuilder.dispatchReceiver(dispatchReceiver: FqName) {
|
||||
@ -85,13 +86,19 @@ fun KtFunction.hasSignature(functionSignature: FunctionSignature): Boolean {
|
||||
if (this.containingClassOrObject?.fqName != functionSignature.dispatchReceiver) return false
|
||||
}
|
||||
if (functionSignature.extensionReceiver != null) {
|
||||
if (this.receiverTypeReference?.resolveReferencedType()?.getKotlinFqName() != functionSignature.extensionReceiver) return false
|
||||
if (this.receiverTypeReference?.resolveReferencedType()
|
||||
?.getKotlinFqName() != functionSignature.extensionReceiver
|
||||
) return false
|
||||
}
|
||||
if (functionSignature.parameters != null) {
|
||||
if (this.valueParameters.zip(functionSignature.parameters).any { it.first.type()?.fqName != it.second }) return false
|
||||
if (this.valueParameters.zip(functionSignature.parameters)
|
||||
.any { it.first.type()?.fqName != it.second }
|
||||
) return false
|
||||
}
|
||||
if (functionSignature.returnType != null) {
|
||||
if (this.getReturnTypeReference()?.resolveReferencedType()?.getKotlinFqName() != functionSignature.returnType) return false
|
||||
if (this.getReturnTypeReference()?.resolveReferencedType()
|
||||
?.getKotlinFqName() != functionSignature.returnType
|
||||
) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -118,7 +125,9 @@ fun PsiMethod.hasSignature(functionSignature: FunctionSignature): Boolean {
|
||||
if (receiver.type.canonicalText != functionSignature.extensionReceiver.toString()) return false
|
||||
}
|
||||
if (functionSignature.parameters != null) {
|
||||
if (parameters.zip(functionSignature.parameters).any { it.first.type.canonicalText != it.second.toString() }) return false
|
||||
if (parameters.zip(functionSignature.parameters)
|
||||
.any { it.first.type.canonicalText != it.second.toString() }
|
||||
) return false
|
||||
}
|
||||
if (functionSignature.returnType != null) {
|
||||
if (returnType?.canonicalText != functionSignature.returnType.toString()) return false
|
||||
@ -143,7 +152,9 @@ fun CallableDescriptor.hasSignature(functionSignature: FunctionSignature): Boole
|
||||
if (this.containingDeclaration.fqNameUnsafe != functionSignature.dispatchReceiver.toUnsafe()) return false
|
||||
}
|
||||
if (functionSignature.parameters != null) {
|
||||
if (this.valueParameters.zip(functionSignature.parameters).any { it.first.type.fqName != it.second }) return false
|
||||
if (this.valueParameters.zip(functionSignature.parameters)
|
||||
.any { it.first.type.fqName != it.second }
|
||||
) return false
|
||||
}
|
||||
if (functionSignature.returnType != null) {
|
||||
if (this.returnType?.fqName != functionSignature.returnType) return false
|
||||
|
@ -16,6 +16,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.fqName
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@ -26,6 +27,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.referenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
@ -36,15 +38,14 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
|
||||
|
||||
/**
|
||||
* For CompositeCommand.SubCommand
|
||||
*/
|
||||
fun KtNamedFunction.isCompositeCommandSubCommand(): Boolean = this.hasAnnotation(COMPOSITE_COMMAND_SUB_COMMAND_FQ_NAME)
|
||||
fun PsiModifierListOwner.isCompositeCommandSubCommand(): Boolean = this.hasAnnotation(COMPOSITE_COMMAND_SUB_COMMAND_FQ_NAME)
|
||||
fun PsiModifierListOwner.isCompositeCommandSubCommand(): Boolean =
|
||||
this.hasAnnotation(COMPOSITE_COMMAND_SUB_COMMAND_FQ_NAME)
|
||||
|
||||
internal fun PsiModifierListOwner.hasAnnotation(fqName: FqName): Boolean = this.hasAnnotation(fqName.asString())
|
||||
|
||||
@ -118,7 +119,14 @@ fun KtClass.hasSuperType(fqName: FqName): Boolean = allSuperNames.contains(fqNam
|
||||
fun PsiElement.hasSuperType(fqName: FqName): Boolean = allSuperNames.contains(fqName)
|
||||
|
||||
val KtClassOrObject.allSuperNames: Sequence<FqName> get() = allSuperTypes.mapNotNull { it.getKotlinFqName() }
|
||||
val PsiClass.allSuperNames: Sequence<FqName> get() = allSuperTypes.mapNotNull { clazz -> clazz.qualifiedName?.let { FqName(it) } }
|
||||
val PsiClass.allSuperNames: Sequence<FqName>
|
||||
get() = allSuperTypes.mapNotNull { clazz ->
|
||||
clazz.qualifiedName?.let {
|
||||
FqName(
|
||||
it
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@kotlin.internal.LowPriorityInOverloadResolution
|
||||
@ -247,7 +255,8 @@ fun ConstantValue<*>.selfOrChildrenConstantStrings(): Sequence<String> {
|
||||
}
|
||||
|
||||
fun ClassDescriptor.findMemberFunction(name: Name, vararg typeProjection: TypeProjection): SimpleFunctionDescriptor? {
|
||||
return getMemberScope(typeProjection.toList()).getContributedFunctions(name, NoLookupLocation.FROM_IDE).firstOrNull()
|
||||
return getMemberScope(typeProjection.toList()).getContributedFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.companionObjectDescriptor(): ClassDescriptor? {
|
||||
@ -260,7 +269,9 @@ fun DeclarationDescriptor.companionObjectDescriptor(): ClassDescriptor? {
|
||||
fun KtExpression.resolveStringConstantValues(bindingContext: BindingContext): Sequence<String> {
|
||||
when (this) {
|
||||
is KtNameReferenceExpression -> {
|
||||
when (val descriptor = references.firstIsInstance<KtSimpleNameReference>().resolveToDescriptors(bindingContext).singleOrNull()) {
|
||||
when (val descriptor =
|
||||
references.firstIsInstance<KtSimpleNameReference>().resolveToDescriptors(bindingContext)
|
||||
.singleOrNull()) {
|
||||
is VariableDescriptor -> {
|
||||
val compileTimeConstant = descriptor.compileTimeInitializer ?: return emptySequence()
|
||||
return compileTimeConstant.selfOrChildrenConstantStrings()
|
||||
|
@ -23,9 +23,9 @@ object RequirementHelper {
|
||||
fun isValid(rule: String): Boolean {
|
||||
return rule.trim().let {
|
||||
directVersion.matches(it) ||
|
||||
versionSelect.matches(it) ||
|
||||
versionMathRange.matches(it) ||
|
||||
versionRule.matches(it)
|
||||
versionSelect.matches(it) ||
|
||||
versionMathRange.matches(it) ||
|
||||
versionRule.matches(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,10 @@ internal class RequirementParser {
|
||||
val isStartingOfGroup = nextToken is Token.GroupBod.Left
|
||||
if (isStartingOfGroup != isEndingOfGroup) {
|
||||
fun getType(type: Boolean) = if (type) "`}`" else "<结束>"
|
||||
next.ia(reader, "需要 ${getType(isStartingOfGroup)}, 但是找到了 ${getType(isEndingOfGroup)}")
|
||||
next.ia(
|
||||
reader,
|
||||
"需要 ${getType(isStartingOfGroup)}, 但是找到了 ${getType(isEndingOfGroup)}"
|
||||
)
|
||||
} else {
|
||||
// reader.insertToken = next
|
||||
break
|
||||
@ -284,21 +287,21 @@ internal class RequirementParser {
|
||||
fun getMode(type: Boolean) = if (type) "`&&`" else "`||`"
|
||||
next.ia(
|
||||
reader, "为了避免语义混乱, 不允许在一层规则组混合使用 `&&` 和 `||`, 请显式使用 `{}` 分离. " +
|
||||
"需要 ${getMode(mode)}, 但是找到了 ${getMode(stx)}"
|
||||
"需要 ${getMode(mode)}, 但是找到了 ${getMode(stx)}"
|
||||
)
|
||||
}
|
||||
chunks.add(process(reader))
|
||||
}
|
||||
else -> {
|
||||
next.ia(
|
||||
reader, "Except ${
|
||||
when (mode) {
|
||||
null -> "`&&` or `||`"
|
||||
true -> "`&&`"
|
||||
false -> "`||`"
|
||||
}
|
||||
} but get `${next.content}`"
|
||||
)
|
||||
next.ia(
|
||||
reader, "Except ${
|
||||
when (mode) {
|
||||
null -> "`&&` or `||`"
|
||||
true -> "`&&`"
|
||||
false -> "`||`"
|
||||
}
|
||||
} but get `${next.content}`"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user