注意:这是一篇草稿,但是因为 IntelliJ 插件开发参考资料实在太少,就放出来吧,不知道以后还有没有机会完善,怀念写 kotlin 的一周(哈哈)。
难点与应对方法:
- 语言基本陌生——问题不大
- IDE 完全陌生——看文档
- 插件运行原理一点都不知道——根据文档了解核心概念
- sdk一点都不知道,这对工时评估影响很大——这个就真的最花时间的了
先决条件:
- JVM 语言
- Gradle
- Swing
- 熟悉 IDE
Gradle
构建脚本 build.gradle
(Groovy/kotlin)
Gradle Wrapper 通过使用 gradle-wrapper.properties 配置文件来确保每个开发者和 CI 工具都使用相同的 Gradle 版本。
Swing
学 Swing 有感:终于知道后端学 CSS 有多难了。而且 Swing 不能实时调试,教程也不多。
IDE
窗口结构:https://www.jetbrains.com/help/idea/guided-tour-around-the-user-interface.html
IDE 开发体验确实好,自动改名,新建类,一键加参数
插件模板
https://github.com/JetBrains/intellij-platform-plugin-template
项目结构
.├── .github/ GitHub Actions├── .run/ Run/Debug 配置├── build/ 构建目录├── gradle│ ├── wrapper/ Gradle Wrapper│ └── libs.versions.toml Gradle version catalog├── src Plugin 代码│ ├── main│ │ ├── kotlin/ Kotlin 代码│ │ └── resources/ 资源文件夹 - plugin.xml <- 这是重点, icons, messages│ └── test│ ├── kotlin/ 测试代码│ └── testData/ 测试数据├── .gitignore├── build.gradle.kts Gradle build 配置├── CHANGELOG.md Full change history├── gradle.properties Gradle 配置├── gradlew *nix Gradle Wrapper script├── gradlew.bat Windows Gradle Wrapper script├── LICENSE├── qodana.yml├── README.md└── settings.gradle.kts Gradle project settings
plugin.xml
<idea-plugin> <id>org.jetbrains.plugins.template</id> <name>Template</name> <vendor>JetBrains</vendor>
<depends>com.intellij.modules.platform</depends>
<resource-bundle>messages.MyBundle</resource-bundle>
<extensions defaultExtensionNs="com.intellij"> <toolWindow factoryClass="..." id="..."/> </extensions>
<applicationListeners> <listener class="..." topic="..."/> </applicationListeners></idea-plugin>
开发资料
文档写得一般,没有系统教程,只能看开源插件学习
开启内部模式
这里还有个也没多大用的 samples 仓库
重要概念
Action
在IntelliJ插件开发中,“Action” 是一个核心概念。一般来说,一个 “Action” 就是用户可以执行的一个操作或命令,它可以被关联到菜单项、工具栏按钮或者快捷键。 例如:打开一个新的文件、剪切和粘贴文本、用某种语言运行代码等都是 “Actions”。
你可以通过创建和注册自定义 “Action” 来扩展 IntelliJ 的功能。每个 “Action” 都需要提供一个 “actionPerformed” 方法,当用户触发该操作时,这个方法会被调用。
在 IntelliJ 的插件开发中,使用 XML 文件(通常是 plugin.xml)来注册你的 “Action”,并指定其所在的位置,如 “File” 菜单或者右键弹出菜单等。
你可以选 action 插入的位置、触发快捷键,这些都是以用户触发为基础的。所以如果你的插件或程序不需要用户触发,只需要在后台或者特定条件下自动执行某些操作,你只需要编写普通的处理类就行了。
Service
https://plugins.jetbrains.com/docs/intellij/plugin-services.html
服务是一个全局或项目级别的单例,用于保存数据和状态,或者提供复杂的操作。
Listener & Message
监听和响应 Topic
Extension Point
EP:https://plugins.jetbrains.com/docs/intellij/intellij-platform-extension-point-list.html
没太看懂,ai是这么跟我解释的:在IntelliJ中,extension point不是一个class,而是一个特殊的接口,它为你的插件提供了扩展应用程序的能力。使用extension point,你可以将自己的代码插入到IDE的生命周期中的特定点,让你的代码在某些特定事件发生时被执行。这是IntelliJ插件开发的重要组成部分,用于实现插件的具体功能。
例子:
<extensions defaultExtensionNs="com.intellij"> <lang.parserDefinition implementation="your.package.YourParserDefinition"/></extensions>
public class YourParserDefinition implements ParserDefinition { public static final IFileElementType FILE = new IFileElementType(YourLanguage.INSTANCE);
@NotNull @Override public Lexer createLexer(Project project) { return new YourLexerAdapter(); }
@Override public PsiParser createParser(Project project) { return new YourPsiParser(); }
@Override public IFileElementType getFileNodeType() { return FILE; }
@NotNull @Override public TokenTypeRemapper getWhitespaceTokens() { return YourLanguageTokens.WHITESPACES; }
@NotNull @Override public TokenTypeRemapper getCommentTokens() { return YourLanguageTokens.COMMENTS; }
@NotNull @Override public TokenTypeRemapper getStringLiteralElements() { return YourLanguageTokens.STRING_LITERALS; }
@NotNull @Override public PsiElement createElement(ASTNode node) { return YourLanguageTypes.Factory.createElement(node); }
@Override public PsiFile createFile(FileViewProvider viewProvider) { return new YourFile(viewProvider); }
@NotNull @Override public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) { return SpaceRequirements.MAY; }
}
Execution
https://plugins.jetbrains.com/docs/intellij/execution.html
可以直接执行普通命令、从右上角执行可以配置运行配置。实际要编程实现时要理解的概念比较多。
PSI
PSI (Program Structure Interface):PSI是IntelliJ用于在内存中表示源代码的接口。例如,一个Java文件将被解析为一个PSI文件,包含了多个PSI类,PSI方法等。通过PSI,你可以很容易地分析和修改代码。
可以通过 View PSI Structure 熟悉 PSI
AI 开发
- 解释概念
- 根据 API 给出例子