diff --git a/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt b/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt index 4a39b56e5..4b0dfda16 100644 --- a/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt +++ b/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt @@ -128,13 +128,11 @@ object MyCompositeCommand : CompositeCommand( ) { // 会自动创建一个 ID 为 "org.example.example-plugin:command.manage" 的权限. - // [参数智能解析] // // 在控制台执行 "/manage <群号>.<群员> <持续时间>", // 或在聊天群内发送 "/manage <@一个群员> <持续时间>", // 或在聊天群内发送 "/manage <目标群员的群名> <持续时间>", // 或在聊天群内发送 "/manage <目标群员的账号> <持续时间>" - // 时调用这个函数 @SubCommand suspend fun CommandSender.mute(target: Member, duration: Int) { // 通过 /manage mute 调用 sendMessage("/manage mute 被调用了, 参数为: $target, $duration") diff --git a/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MySimpleCommand.kt b/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MySimpleCommand.kt new file mode 100644 index 000000000..30699c49a --- /dev/null +++ b/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MySimpleCommand.kt @@ -0,0 +1,14 @@ +package org.example.myplugin + +import net.mamoe.mirai.console.command.CommandSender +import net.mamoe.mirai.console.command.SimpleCommand + +object MySimpleCommand000 : SimpleCommand( + MyPluginMain, "foo", + description = "示例指令" +) { + @Handler + suspend fun CommandSender.handle(int: Int, str: String) { + + } +} diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/CommandDeclarationLineMarkerProvider.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/CommandDeclarationLineMarkerProvider.kt new file mode 100644 index 000000000..b05df3175 --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/CommandDeclarationLineMarkerProvider.kt @@ -0,0 +1,40 @@ +package net.mamoe.mirai.console.intellij.line.marker + +import com.intellij.codeHighlighting.Pass +import com.intellij.codeInsight.daemon.LineMarkerInfo +import com.intellij.codeInsight.daemon.LineMarkerProvider +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.editor.markup.GutterIconRenderer +import com.intellij.psi.PsiElement +import net.mamoe.mirai.console.intellij.Icons +import net.mamoe.mirai.console.intellij.resolve.isSimpleCommandHandlerOrCompositeCommandSubCommand +import org.jetbrains.kotlin.psi.KtNamedFunction + +class CommandDeclarationLineMarkerProvider : LineMarkerProvider { + override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? { + if (element !is KtNamedFunction) return null + if (!element.isSimpleCommandHandlerOrCompositeCommandSubCommand()) return null + return Info(getElementForLineMark(element.funKeyword ?: element.identifyingElement ?: element)) + } + + @Suppress("DEPRECATION") + class Info( + callElement: PsiElement, + ) : LineMarkerInfo( + callElement, + callElement.textRange, + Icons.CommandDeclaration, + Pass.LINE_MARKERS, + { + "子指令定义" + }, + null, + GutterIconRenderer.Alignment.RIGHT + ) { + override fun createGutterRenderer(): GutterIconRenderer? { + return object : LineMarkerInfo.LineMarkerGutterIconRenderer(this) { + override fun getClickAction(): AnAction? = null + } + } + } +} \ No newline at end of file diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/PluginMainLineMarkerProvider.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/PluginMainLineMarkerProvider.kt index 45c6b1aed..22d8407f4 100644 --- a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/PluginMainLineMarkerProvider.kt +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/PluginMainLineMarkerProvider.kt @@ -5,12 +5,10 @@ import com.intellij.codeInsight.daemon.LineMarkerInfo import com.intellij.codeInsight.daemon.LineMarkerProvider import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.editor.markup.GutterIconRenderer -import com.intellij.openapi.progress.ProgressManager import com.intellij.psi.PsiElement -import com.intellij.psi.PsiJavaCodeReferenceCodeFragment +import com.intellij.util.castSafelyTo import net.mamoe.mirai.console.intellij.Icons import net.mamoe.mirai.console.intellij.Plugin_FQ_NAME -import org.jetbrains.kotlin.idea.core.util.getLineNumber import org.jetbrains.kotlin.nj2k.postProcessing.resolve import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtConstructor @@ -19,50 +17,13 @@ import org.jetbrains.kotlin.psi.KtReferenceExpression class PluginMainLineMarkerProvider : LineMarkerProvider { override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? { - return null - } - - override fun collectSlowLineMarkers( - elements: MutableList, - result: MutableCollection>, - ) { - val markedLineNumbers = HashSet() - - for (element in elements) { - ProgressManager.checkCanceled() - - - val containingFile = element.containingFile - if (containingFile is PsiJavaCodeReferenceCodeFragment) { - continue - } - - - - - when { - element is KtReferenceExpression // constructor call - -> { - val objectDeclaration = - element.parents.filterIsInstance().firstOrNull() ?: continue - - val resolved = element.resolve() as? KtConstructor<*> ?: continue - - val kotlinPluginClass = resolved.parent as? KtClass ?: continue - - if (kotlinPluginClass.allSuperNames.none { it == Plugin_FQ_NAME }) continue - - val lineNumber = objectDeclaration.getLineNumber() - if (lineNumber in markedLineNumbers) continue - - markedLineNumbers += lineNumber - result += Info(getElementForLineMark(objectDeclaration)) - } - } - - // if (!element.hasBridgeCalls()) continue - - } + if (element !is KtReferenceExpression) return null + val objectDeclaration = + element.parents.filterIsInstance().firstOrNull() ?: return null + val kotlinPluginClass = + element.resolve().castSafelyTo>()?.parent?.castSafelyTo() ?: return null + if (kotlinPluginClass.allSuperNames.none { it == Plugin_FQ_NAME }) return null + return Info(getElementForLineMark(objectDeclaration)) } @Suppress("DEPRECATION") diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/util.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/util.kt index 38c96eb3c..4e93675e5 100644 --- a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/util.kt +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/line/marker/util.kt @@ -49,4 +49,10 @@ internal fun getElementForLineMark(callElement: PsiElement): PsiElement = // a fallback, //but who knows what to reference in KtArrayAccessExpression ? generateSequence(callElement, { it.firstChild }).last() - } \ No newline at end of file + } + +internal val KtAnnotationEntry.annotationClass: KtClass? + get() = calleeExpression?.constructorReferenceExpression?.resolve()?.findParent() + +internal fun KtAnnotated.hasAnnotation(fqName: FqName): Boolean = + this.annotationEntries.any { it.annotationClass?.getKotlinFqName() == fqName } \ No newline at end of file diff --git a/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/resolve/psiResolve.kt b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/resolve/psiResolve.kt new file mode 100644 index 000000000..0504c573f --- /dev/null +++ b/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/resolve/psiResolve.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.intellij.resolve + +import net.mamoe.mirai.console.intellij.line.marker.hasAnnotation +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtNamedFunction + +val COMPOSITE_COMMAND_SUB_COMMAND_FQ_NAME = FqName("net.mamoe.mirai.console.command.CompositeCommand.SubCommand") +val SIMPLE_COMMAND_HANDLER_COMMAND_FQ_NAME = FqName("net.mamoe.mirai.console.command.SimpleCommand.Handler") + +/** + * For CompositeCommand.SubCommand + */ +fun KtNamedFunction.isCompositeCommandSubCommand(): Boolean = this.hasAnnotation(COMPOSITE_COMMAND_SUB_COMMAND_FQ_NAME) + +/** + * SimpleCommand.Handler + */ +fun KtNamedFunction.isSimpleCommandHandler(): Boolean = this.hasAnnotation(SIMPLE_COMMAND_HANDLER_COMMAND_FQ_NAME) + +fun KtNamedFunction.isSimpleCommandHandlerOrCompositeCommandSubCommand(): Boolean = + this.isSimpleCommandHandler() || this.isCompositeCommandSubCommand() \ No newline at end of file diff --git a/intellij-plugin/src/main/resources/META-INF/plugin.xml b/intellij-plugin/src/main/resources/META-INF/plugin.xml index 969686c19..c7d524f96 100644 --- a/intellij-plugin/src/main/resources/META-INF/plugin.xml +++ b/intellij-plugin/src/main/resources/META-INF/plugin.xml @@ -17,6 +17,10 @@ implementationClass="net.mamoe.mirai.console.intellij.line.marker.PluginMainLineMarkerProvider"/> + +