Reformat and cleanup code

This commit is contained in:
Him188 2021-07-02 00:55:00 +08:00
parent f341d2f1f6
commit f096d0d042
78 changed files with 522 additions and 227 deletions

View File

@ -42,7 +42,8 @@ public interface MiraiConsoleFrontEndDescription {
* 返回 `null` 表示禁止 [MiraiConsole] 后端检查版本兼容性.
*/
@MiraiExperimentalApi
public val compatibleBackendVersion: SemVersion? get() = null
public val compatibleBackendVersion: SemVersion?
get() = null
/**
* 返回显示在 [MiraiConsole] 启动时的信息

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -63,7 +63,8 @@ public interface JvmPlugin : Plugin, CoroutineScope,
* @receiver 组件容器
*/
@RestrictedScope(COMMAND_REGISTER, PERMISSION_REGISTER)
public fun PluginComponentStorage.onLoad() {}
public fun PluginComponentStorage.onLoad() {
}
/**
* 在插件被启用时调用, 可能会被调用多次

View File

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

View File

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

View File

@ -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 {
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -118,6 +118,7 @@ class Validation {
}
return true
}
var result = true
for (prop in step::class.java.declaredFields) {
if (!validateProperty(prop)) result = false

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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