背景
写一个IDE插件的目的永远都是提高工作效率。当有以下几种场景的时候,那么你就可以尝试去写一个插件了。
- 一个页面或功能有比较多的模板代码。如GsonFormat能快捷生成数据类型。
- 在一个团队中遇到协作性的问题,可以用插件来解决的。如 git 的可视化操作。
环境准备
MVP插件
环境搭建按照教程走一遍就好,要开发一个插件,还是要自己亲手撸一个之后才有感觉。
首先创建一个名为 MvpPluginDemo 的项目, 第一步就是在plugin.xml把信息填写好:
<idea-plugin>
// 填写唯一id
<id>com.test.mvp</id>
// 插件名
<name>MvpPluginDemo</name>
// 版本号
<version>1.0</version>
// 链接信息
<vendor email="my@gmail.com" url="http://www.yoursite.com">我/公司</vendor>
//描述
<description><![CDATA[
这是一个插件的描述,用户搜索下载时会显示描述。这个描述尽量满足50字,巴拉巴拉巴拉。。
]]></description>
//迭代信息
<change-notes><![CDATA[
这是版本更新时,更新内容的描述,也是尽量满足50字,巴拉拉拉拉拉拉拉拉拉拉拉。。
]]>
</change-notes>
<!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="173.0"/>
<!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
<depends>com.intellij.modules.platform</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>
一般情况下填写注释的那些信息即可。
创建Action
接着创建一个 Action,我们不需要手动填写 actions 信息,可以直接可视化构造:
Groups是指定创建的入口,这比较难以选择,根据描述很难判断具体的入口是哪个,只能靠自己去google或一点点试吧。如创建Mvp模板类代码与创建一个文件的操作类似,所以我们把它放在创建Kotlin文件的下方也算合理,after表示放在某个action后面。
开始编码
一个Action是长这样的:
public class MvpAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
}
}
编码阶段和写Java代码没太大差异,重点需要了解如何获取project的一些基本信息,即我们能从AnActionEvent里能获取什么,这也只能根据自己需要什么来研究调用对应的api。在这个例子我需要知道创建模板文件时的路径:
String dirPath = event.getData(PlatformDataKeys.VIRTUAL_FILE).getPath();
以上能获取当前创建mvp模板时的文件夹路径,然后执行生成文件的逻辑:
// 无论做什么,WriteCommandAction.runWriteCommandAction 是固定代码
WriteCommandAction.runWriteCommandAction(event.getProject(), () -> {
String dirPath = event.getData(PlatformDataKeys.VIRTUAL_FILE).getPath();
List<IGenerator> generatorList = new ArrayList<>();
// 分别生成model、presenter、component、view、vo
generatorList.add(new ModelGenerator());
generatorList.add(new PresenterGenerator());
generatorList.add(new ComponentGenerator());
generatorList.add(new ViewGenerator());
generatorList.add(new VoGenerator());
for(IGenerator generator : generatorList) {
generator.generateFile(dirPath);
}
// 以下代码就是为了刷新下项目,否则可能创建的文件可能不会时时生效
event.getProject().getBaseDir().refresh(false, true);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
event.getProject().getBaseDir().refresh(false, true);
}
}, 1000);
});
因为本例中的mvp是定制的架构,所以就不细节到每一个文件了,随便选一个文件来看下具体生成代码的逻辑。
public class PresenterGenerator implements IGenerator{
private static final String SUFFIX = "Presenter.kt";
private static final String SYMBOL = "/";
@Override
public void generateFile(String dirPath) {
// moduleName是当前要创建模板文件的空目录
String moduleName = GeneratorUtil.getModule(dirPath);
String fileName = dirPath + SYMBOL + moduleName + SUFFIX;
// 创建文件
File file = new File(fileName);
try {
// 文件输出流写入
FileOutputStream fileOutputStream = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream);
// 把模板代码写入,需要动态替换的地方用 replace 替换字符串。
writer.append("package " + GeneratorUtil.getPackage(dirPath) + "\n\n");
writer.append("import android.app.Activity\n" +
"import android.os.Bundle\n" +
"import com.alibaba.dinggov.ui.components.BaseComponentPresenter\n");
writer.append(GeneratorUtil.getComment());
writer.append("class $MODULEPresenter(activity: Activity) : BaseComponentPresenter<$MODULEView>() {\n\n".replace("$MODULE", moduleName));
writer.append(" private var model: $MODULEModel = $MODULEModel()\n\n".replace("$MODULE", moduleName));
writer.append(" override fun onStart(params: Bundle?) {\n");
writer.append(" loadInitData()\n");
writer.append(" }\n");
writer.append(" private fun loadInitData() {\n");
writer.append(" // TODO use model to load Data\n");
writer.append(" }\n");
writer.append("}\n");
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
不复杂的模板代码只需要用字符串一行行的拼接即可,逻辑也是相当简单的。最后需要生成jar:
如果是本地,直接添加jar就可以,需要放到仓库的看下其他上传的教程。
效果演示
最后看下效果演示: