小伙伴想写个 IDEA 插件么?这些 API 了解一下!

用户头像
liuzhihang
关注
发布于: 2020 年 08 月 01 日
小伙伴想写个 IDEA 插件么?这些 API 了解一下!

前言



在看完 IDEA 插件开发简易教程后,小伙伴们是否迫不及待的想自己上手整一个插件了?心里规划好了一二三,但是却不知道从哪里开始下手。下面我分享下自己整理的一些常用的 API。



公众号:liuzhihangs,记录工作学习中的技术、开发及源码笔记;时不时分享一些生活中的见闻感悟。欢迎大佬来指导!



AnAction操作



  1. 创建Action集成AnAction并实现其actionPerformed方法. 在方法中可以获取到AnActionEvent对象. 代码如下:



public class JsonFormatAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent event) {
// 获取当前project对象
Project project = event.getData(PlatformDataKeys.PROJECT);
// 获取当前编辑的文件, 可以进而获取 PsiClass, PsiField 对象
PsiFile psiFile = event.getData(CommonDataKeys.PSI_FILE);
Editor editor = event.getData(CommonDataKeys.EDITOR);
// 获取Java类或者接口
PsiClass psiClass = getTargetClass(editor, psiFile);
// 创建并调起 DialogWrapper
DialogWrapper dialog = new JsonFormat(project, psiFile, editor, psiClass);
dialog.show();
}



  1. 其他方式



// 获取project. 内部调用 getData(CommonDataKeys.PROJECT) = getDataContext().getData(CommonDataKeys.PROJECT)
Project project = e.getProject();
// 获取数据上下文
DataContext dataContext = e.getDataContext();
// context可以也获取到其他信息, 入参为 PlatformDataKeys 定义的字段
Project project1 = dataContext.getData(PlatformDataKeys.PROJECT);
Editor editor = dataContext.getData(PlatformDataKeys.EDITOR);
PsiFile psiFile = dataContext.getData(PlatformDataKeys.PSI_FILE);
PsiElement psiElement = dataContext.getData(PlatformDataKeys.PSI_ELEMENT);
// 虚拟文件
VirtualFile virtualFile = dataContext.getData(PlatformDataKeys.VIRTUAL_FILE);



获取PsiClass



PsiClass为java类或者接口



@Nullable
protected PsiClass getTargetClass(Editor editor, PsiFile file) {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null) {
return null;
} else {
PsiClass target = PsiTreeUtil.getParentOfType(element, PsiClass.class);
return target instanceof SyntheticElement ? null : target;
}
}

Psixxx操作

PsiClass操作API



源码有注释且比较清楚, 此处仅记录我用到的一部分



// 获取全类名
String qualifiedName = aClass.getQualifiedName();
// 获取所有字段
PsiField[] fields = aClass.getFields();



PsiField操作



// 获取字段名
String name = psiField.getName()

PsiElement操作



PsiClass和PsiField都实现了PsiElement



// 删除
element.delete()
// 添加元素, 向一个类中添加方法, 字段等, 也可以调用 addBefore, addAfter
add(PsiElement element)



PsiType操作



PsiType支持常用基本类型, 但是当创建对象时则不支持.需要自己创建

PsiElementFactory psiElementFactory = JavaPsiFacade.getElementFactory(project);
// String 类型
PsiType stringPsiType = psiElementFactory.createTypeFromText("java.lang.String", null)
// list
PsiType listPsiType = psiElementFactory.createTypeFromText("java.util.List<String>", null);
// 自定义list
PsiType typeFromText = psiElementFactory.createTypeFromText("java.util.List<" + className + ">", null);



其他API



XML 文件操作



参考地址:https://jetbrains.org/intellij/sdk/docs/referenceguide/frameworksand_external_apis/xmldomapi.html



以 Mapper.xml 举例声明接口,继承 DomElement,并配合 @Attribute、@SubTag 、@SubTagsList 注解定义一个 xml model,其中需要注意 @SubTagsList 方法要使用复数形式。



public interface Mapper extends DomElement {
/**
* namespace
*
* @return
*/
@Attribute("namespace")
GenericAttributeValue<String> getNamespace();
/**
*
* 增删改查对应的节点
*
* @return
*/
@SubTagsList({"select", "insert", "update", "delete"})
List<Statement> getStatements();
@SubTagList("select")
List<Select> getSelects();
@SubTagList("insert")
List<Insert> getInserts();
@SubTagList("update")
List<Update> getUpdates();
@SubTagList("delete")
List<Delete> getDeletes();
}



搜索文件



比如想搜索项目中的所有 xml 文件,上面使用 Mapper 接口定义了 Mapper.xml 的结构,就可以利用 DomService 搜索所有的 Mapper.xml:



// 当前项目的所有元素 mapper, 分别填入类型, 作用域 GlobalSearchScope
List<DomFileElement<Mapper>> fileElements = DomService.getInstance().getFileElements(Mapper.class, project, GlobalSearchScope.allScope(project));



写入文件



需要调用WriteCommandAction进行异步写入.



WriteCommandAction.runWriteCommandAction(project, () -> {
doGenerate(psiClass, jsonObject);
});



通知



在操作成功之后,在 IDEA 右下角通知用户,使用 NotificationGroup 类即可。



// 静态属性
private static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup("Java2Json.NotificationGroup", NotificationDisplayType.BALLOON, true);
public void actionPerformed(@NotNull AnActionEvent e) {
// 在方法中调用
Notification success = NOTIFICATION_GROUP.createNotification(message, NotificationType.INFORMATION);
Notifications.Bus.notify(success, project);
}

也可以定义为工具类,如下



/**
*
* 进行消息通知工具类
*
* @author liuzhihang
* @date 2020/2/28 18:52
*/
public class NotificationUtils {
private static NotificationGroup notificationGroup = new NotificationGroup("ApiDoc.NotificationGroup", NotificationDisplayType.BALLOON, true);
public static void warnNotify(String message, Project project) {
Notifications.Bus.notify(notificationGroup.createNotification(message, NotificationType.WARNING), project);
}
public static void infoNotify(String message, Project project) {
Notifications.Bus.notify(notificationGroup.createNotification(message, NotificationType.INFORMATION), project);
}
public static void errorNotify(String message, Project project) {
Notifications.Bus.notify(notificationGroup.createNotification(message, NotificationType.ERROR), project);
}
}



总结



基本上常用的就是这些了,也可以查找官方文档,官方文档现在还是比较全面的,地址在相关资料中。也可以 Clone Toolkit 这个插件源码,源码中有一些注释。在其他优秀的插件中,同样可有相关使用方法。

相关资料





发布于: 2020 年 08 月 01 日 阅读数: 265
用户头像

liuzhihang

关注

学,而知不足;教,然后知困。 2020.07.30 加入

公众号:「 刘志航 」

评论

发布
暂无评论
小伙伴想写个 IDEA 插件么?这些 API 了解一下!