IntelliJ IDEA 翻译插件开发 - 从概念到实践
IntelliJ IDEA 翻译插件开发 - 从概念到实践
dong4j相对于 Hello World 版的插件, 我们可以学习一个 API 的用法.
在接下来的博文中将创建一个翻译插件, 相对于 Hello World 版的插件,
我们可以学习一个 API 的用法.
在写之前, 先补充一下上一篇博文中存在的问题.
使用 Gradle 开发 Intellij IDEA Plugin 的问题
当我们使用 Intellij 自带的 Intellij Platform Plugin 创建插件项目后, 我们可以通过 Intellij 以图形化界面创建 Action, Module Component 等,
就像这样:
OK 之后, 就会自动创建一个 GenerateActionByGui
继承 AnAction 的类, 并且在 plugin.xml 中自动写入插件的配置:
1 | <actions> |
简单快捷方便, 将程序猿偷懒的精神展现的淋漓尽致, 那么问题来了…….
当我们使用 Gradle 或者 Maven 这种项目管理软件创建 插件项目时, 你会发现这些功能没有了, 不信你看..
没有选择 Action 的按钮了, 而且还要一个问题
Use classpath of module 一直为 [none] , 这时候该怎么办呢?
解决方法
这里首先应该想到, 为什么创建 Intellij Platform Plugin 项目和创建 Gradle 项目存在区别? IDEA 应该会根据不同的项目类别显示不同的可用功能按钮.
对 Intellij IDEA 了解的朋友应该知道, 当创建或者打开一个 IDEA 工程时, 会自动创建 .idea 文件夹 和 .iml 文件, iml 是 Intellij IDEA
的工程配置文件,里面是当前 projec 的一些配置信息. 既然是工程配置文件, 应该会标识当前项目是属于哪种类型的工程, 顺着这种思路, 还真被我找到了.
使用 Gradle 创建的项目中, 在 .idea/moudle/ 下有 3 个 .iml 文件
我们需要改的就是 _main.iml
原来的文件内容:
1 |
|
改过之后的内容:
1 |
|
区别就是将 <module>
标签中的 type 属性由原来的 JAVA_MODULE 改为 PLUGIN_MODULE. 修改之后整个项目其实已经是一个 Plugin 项目了
图标都变成 Plugin 特有的了, 看到这个我就放心了…..
如果现在通过 GUI 创建一个 Action, 到最后你会发现会报一个找不到 plugin.xml 的错误, 所以还需要添加一个行
1 | <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/../../src/main/resources/META-INF/plugin.xml" /> |
让 IDEA 找到 plugin.xml, 并在我们创建好 Action 后, 向 plugin.xml 中写入 Action 配置.
还有一个问题没有解决, 虽然我们已经能配置
但是当运行的时候, 却会报错, 因为我们的依赖是通过 Gradle 管理的, 这样直接运行虽然能打开容器, 但却不能调试我们的插件, 我们还是通过 Gradle 运行
1 | gradle runI |
如果从 GitHub 上 clone 下来一个优秀的插件学习的话, clone 下来的包中可能没有 .idea 这个文件夹, 当导入到 IDEA 中时,
只有
这 3 个选择, 如果不是上述项目, 我选择直接打开项目, 等 IDEA 自动创建好 .idea 后, 通过修改 .iml 文件, 将项目改为 plugin 项目, 然后就可以创建
Plugin 的运行环境了. 这种方法适合没有通过 Gradle 或者 Maven 项目管理的 Plugin 项目.
问题解决, 接下来是一个翻译插件的开发过程
翻译插件开发
愉快的用 GUI 创建一个 Action
有道 API
有道翻译 API HTTP 地址:
有道翻译 API HTTPS 地址:
接口调用参数
调用 API 需要向接口发送以下字段来访问服务。
字段名 | 类型 | 含义 | 必填 | 备注 |
---|---|---|---|---|
q | text | 要翻译的文本 | True | 必须是 UTF-8 编码 |
from | text | 源语言 | True | 语言列表 (可设置为 auto) |
to | text | 目标语言 | True | 语言列表 (可设置为 auto) |
appKey | text | 应用 ID | True | 可在 应用管理 查看 |
salt | text | 随机数 | True | |
sign | text | 签名,通过 md5(appKey+q+salt + 密钥) 生成 | True | appKey+q+salt + 密钥的 MD5 值 |
签名生成方法如下:
1、将请求参数中的 appKey,翻译文本 query(q, 注意为 UTF-8 编码),随机数 (salt) 和密钥 (可在 应用管理 查看), 按照
appid+q+salt + 密钥 的顺序拼接得到字符串 str。
2、对字符串 str 做 md5,得到 32 位小写的 sign(参考 Java 生成 MD5 示例)
注意:
1、请先将需要翻译的文本转换为 UTF-8 编码
2、在发送 HTTP 请求之前需要对各字段做 URL encode。
3、在生成签名拼接 appKey+q+salt 字符串时,q 不需要做 URL encode,在生成签名之后,发送 HTTP 请求之前才需要对要发送的待翻译文本字段 q 做 URL
encode。
输出结果
返回的结果是 json 格式,包含字段与 FROM 和 TO 的值有关,具体说明如下:
字段名 | 类型 | 含义 | 备注 |
---|---|---|---|
errorCode | text | 错误返回码 | 一定存在 |
query | text | 源语言 | 查询正确时,一定存在 |
speakUrl | text | 输入发音地址 | 输入发音地址,一定存在 |
tSpeakUrl | text | 翻译发音地址 | 翻译发音地址,一定存在 |
translation | text | 翻译结果 | 查询正确时一定存在 |
basic | text | 词义 | 基本词典, 查词时才有 |
web | text | 词义 | 网络释义,该结果不一定存在 |
总结
- 怎么获取选择的对象?
Action ID : 代表当前 Action 的唯一 id
Class Name : 类名
Name : 插件按钮显示在菜单上的名称
Description : 鼠标悬浮在按钮上时, 界面底部显得的描述
Add to Group : 功能按钮添加的位置
Groups : 所属的分组
Action : 设置在组中的位置
Keyboard shortcuts : 功能按钮的快捷键
插件开发一些 API
获取当前编辑的文件PsiFile psiFile = event.getData(LangDataKeys.PSI_FILE);
可以通过下面两种方式对文件的进行操作:
1 | new WriteCommandAction.Simple(event.getProject(), psiFile) { |
1 | WriteCommandAction.runWriteCommandAction(event.getProject(), new Runnable() { |
获取当前编辑的 class 对象
1 | PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset()); |
获取类名
1 | String className = psiClass.getNameIdentifier().getText(); |
获得 PsiElementFactory 对象 可以通过这个工厂类创建成员变量 方法 类等等
1 | PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); |
添加一个方法
1 | String methodText = buildMethodText(className); |
1 | private String buildMethodText (String className){ |
添加一个构造方法
1 | PsiMethod constructor = elementFactory.createConstructor(); |
添加一个成员变量,PsiType 表示变量的类型,PsiModifierList 代表变量的修饰符,可以通过 setInitializer 设置变量初始化方式
1 | PsiType psiType = PsiType.getTypeByName(className, project |
添加一个内部类
1 | PsiClass innerClass = elementFactory.createClass(innerClassName); |
其他
1 | // 创建枚举 |
格式化代码
1 | CodeStyleManager.getInstance(project).reformat(psiClass); |
插件的 UI 都是使用 java Swing 来实现,比如创建一个 Dialog:src>new>Dialog; 然后会生成一个 JDialog 的 java 类和一个 Dialog 的 from 文件。然后在
Action 中使用:
1 | TestDialog dialog = new TestDialog(); |