IntelliJ IDE 插件开发 | (六)内部模式的使用

系列文章

前言

前几篇文章主要介绍了 IntelliJ IDE 插件开发的基础知识和实战内容,作为后续内容的过渡,本文会讲解前几篇文章中提到过的内部模式的使用。内部模式通过菜单形式提供了一系列实用工具,能够帮助初学 IntelliJ IDE 插件的同学极大提升开发效率,由于内部模式提供的工具过多,本文则会挑选几个比较实用的工具进行介绍。

启用内部模式

首先在帮助菜单中找到Edit Custom Properties...

然后加入如下配置:

properties 复制代码
idea.is.internal=true

保存后重启 IDEA,就可以在 Tools 菜单中发现多了一个 Internal Actions:

下面介绍的工具都是基于 Internal Actions 下的,按照实用性,顺序会有所差异。

UI Debugger

在 Internal Actions 下找到 UI Debugger 菜单,点击后会出现以下弹框:

可以发现这里有 Playback 和 Actions 两个标签页,其中 Playback 用于执行给定的脚本,例如以下脚本会自动执行 CTRL + F 显示搜索框,然后先开启大写,最后输入 HELLO:

%[control F]
%type 20:16;72:16;69:16;76:16;76:16;79:16

第一行用于执行 CTRL + F,第二行中的所有的数字都对应键盘编码(不是ASCII码),例如 20代表开启大写,72代表字符 h,所有的输入用 ; 进行分割,: 前表示字符编码,: 后表示控制字符的编码。所有支持的命令和语法规则可以参考源码,由于这个功能在插件开发中用处不大,这里就不展开介绍了。

效果如下:

上面关于 Playback 的使用了解即可,这里主要讲解一下 Actions 的使用,通过前面的文章我们可以知道,在 IntelliJ IDE 中各种操作(不管是点击菜单项还是通过快捷键)都有相对应的 Action,而 Actions 这个菜单就是用于帮助我们查看每个操作所对应的 Action 类名和 id(如果存在),而知道了 Action 的 id,我们就可以调用相应的操作,这样就实现了对 IDEA 自带功能的使用(也可以直接根据 Action 的类名去找相应的文件去看实现方式),下面以一个具体的例子去介绍使用方式:

例如我们想实现一个根据 Kotlin 类定位到对应的 class 文件并打开的功能,我们首先通过 UI Debugger 去查看 IDEA 定位文件并打开对应的 Action:

这里可以看到该操作对应的 ActionId 为 SelectInProjectView,然后我们只需要实现根据 Kotlin 文件名找到同名的 class 文件的逻辑即可,最终实现方式如下:

kotlin 复制代码
class FindClassAction: AnAction() {
    
    override fun actionPerformed(e: AnActionEvent) {
        val project = e.project ?: return
        val file = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY)?.get(0) ?: return
        val kotlinSuffix = ".kt"
        val classSuffix = ".class"
        
        if (!file.name.endsWith(kotlinSuffix)) {
            Utils.info("请选择 Kotlin 文件")
            return
        }
        // 查找 class 文件路径
        val className = file.name.replace(kotlinSuffix, classSuffix)
        val fileList = findFiles(project.basePath.toString(), className, setOf(".idea"))
        if (fileList.isEmpty()) {
            Utils.info("未找到对应类文件")
            return
        }
        val classFile = fileList[0]
        LocalFileSystem.getInstance().findFileByIoFile(classFile)
            ?.let {
                // 打开文件
                FileEditorManager.getInstance(project).openFile(it, true)
                // 定位文件
                ActionManager.getInstance().getAction("SelectInProjectView").actionPerformed(e)
            }
    }
    
    // 在指定路径递归查询某个文件, 同时排除指定的路径
    private fun findFiles(rootDir: String, targetFileName: String, excludedDirs: Set<String> = emptySet()): List<File> { 
        val result = mutableListOf<File>()
        fun searchFiles(directory: File) {
            val files = directory.listFiles() ?: return
            for (file in files) {
                if (file.isDirectory) {
                    if (file.name !in excludedDirs) {
                        searchFiles(file)
                    }
                } else {
                    if (file.name == targetFileName && file.path.contains("classes")) {
                        result.add(file)
                    }
                }
            }
        }
        searchFiles(File(rootDir))
        return result
    }
}

假如我们想知道格式化代码的实现方式,也是先去获取对应的 action:

这里可以看到对应的 Action 类路径是 com.intellij.codeInsight.actions.ReformatCodeAction,这样我们就可以去找对应的源代码,查看其实现方式:

通过这种方式,我们就可以在对 IDEA 自带功能有某些定制化需求的时候,通过继承原有类,然后重写某些逻辑去实现我们的需求。

UI Inspector

通过 UI -> UI Inspector 可以找到该菜单,不过我们在实际使用的时候并不需要从菜单里点击,只需要选择 IDEA 界面中某个 UI 组件,然后使用 CTRL + ALT + 点击鼠标左键即可显示该组件的 UI 信息,如下所示:

这里查看的是 debug 按钮所对应的布局信息,具体如下:

可以发现这里也有 Action ID 和 Action Class 属性,因此上面想查找定位按钮的 Action ID 也可以通过这种方式进行查看:

可以看到这里的 id 和我们通过 UI Debugger 获取的内容一样,当然除了 Action 相关的信息,根据查看的组件类型不同,所对应的属性也会有区别(例如设置页面和这里的按钮属性就有些不同),具体的不同可以查看官网

LaF Defaults

通过 UI -> LaF Defaults 可以找到该菜单,点击后会出现以下弹框:

这里展示了 IDEA 中所有的颜色和外观设置(例如各种间距),我们可以点击对应的 Value 值进行修改,同时修改的设置会立即生效,因此如果有开发主题类插件需求的时候,我们就可以很方便地先通过该工具获取实时的预览效果,例如我们去修改按钮的圆角大小为 0:

修改完就可以发现按钮的圆角消失了:

或者是修改按钮的背景色:

点击 OK 后会出现以下效果:

Kotlin UI DSL

在前几篇文章中我们有简单地使用 Kotlin UI DSL 去实现一些 UI 界面,如果是初学者对相关的使用方式不熟悉,就可以通过该菜单去查看一些组件地使用用例,点击View source就可以查看相应的源码:

总结

本文主要讲解了内部模式中几个比较实用的工具,希望能给大家提供一些帮助,如果你发现了一些插件开发中的小技巧,也欢迎一起交流讨论~~~

题外话

从下篇文章开始会逐步介绍 PSI、自定义语言以及一些常用插件的开发思路和实现方式,敬请期待,同时也祝各位新年快乐,在新的一年里,事业有成,身体健康,家庭幸福,万事如意!

相关推荐
AntDreamer36 分钟前
在实际开发中,如何根据项目需求调整 RecyclerView 的缓存策略?
android·java·缓存·面试·性能优化·kotlin
cliffordl3 小时前
vscode 环境搭建
ide·vscode·编辑器
JANGHIGH3 小时前
VSCode引用Eigen库无法识别问题解决
ide·vscode·编辑器
我就是全世界5 小时前
开源集成开发环境搭建之VSCode启动Jupyter Notebook
ide·vscode·jupyter
极客先躯18 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
蜜桃小阿雯19 小时前
JAVA开源项目 校园美食分享平台 计算机毕业设计
java·jvm·spring boot·spring cloud·intellij-idea·美食
程序猿进阶1 天前
如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?
java·ide·vscode·算法·面试·职场和发展·架构
猿饵块1 天前
vscode
ide·vscode·编辑器
大数据界Olu1 天前
bug | pycharm社区版无sciview解决办法
ide·python·pycharm
千寻简1 天前
Cursor免费 GPT-4 IDE 工具的保姆级使用教程
java·运维·ide·ai