idea插件开发之一起来开发个map转对象的插件吧!

写在前面

源码

在实际工作中,经常有这样的场景,从map中获取值来赋值到某个对象上,这无疑是一个重复的劳动,本文来尝试通过编写一个这样的插件,让插件来帮我们写代码,不管是有1个属性,还是有30个属性,都能在瞬间完成,开始吧!

1:开发

idea已经提供了这样的功能,在generate中生成get,set,tostring等,如下图:

因为我们要做的和这些功能其实是类似,所以,也将菜单放在这里。首先需要创建一个Action:

xml 复制代码
<action id="map2obj" class="com.dahuyou.action.Map2ObjAction" text="map转对象" description="map转对象插件">
    <add-to-group group-id="GenerateGroup" anchor="first"/>
    <keyboard-shortcut keymap="$default" first-keystroke="ctrl alt K"/>
</action>
java 复制代码
public class Map2ObjAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        Messages.showInfoMessage("点击了", "提示");
    }
}

试下效果:

到这里,我们来看下最终要实现的插件希望达到一个什么效果,我们希望是这样的,比如我们有如下的代码:

Map map = fn();
MyObj myObj = new MyObj();

我们要将map中的值设置到myObj中,即最终生成这种代码:

Map map = fn();
MyObj myObj = new MyObj();
myObj.setProp1(map.get("prop1"));
myObj.setProp2(map.get("prop2"));
...

为了实现这个目标,思路是这样子的:

1:用户需要复制Map map,这样我们就可以获取到属性值的数据源信息
2:用户将光标放在MyObj myObj,这样我们就可以获取要设置属性值的目标对象信息
3:动态的生成myObj.setProp1(map.get("prop1"));这种代码到源文件中

首先,来定义接口,如下:

java 复制代码
/**
 * map转obj顶层规范接口,只提供过一个核心的生成代码的方法
 */
public interface IMap2ObjGenerator {
    /**
     * 唯一的核心方法,具体的操作步骤在抽象子类中以模板方法的方式提供,之后具体子类提供具体实现,完成业务逻辑,
     * 这样当我们有很多的子类时,重复的工作就不需要做了,而只需要实现特有的功能就行了
     * @param project
     * @param dataContext
     * @param psiFile
     */
    void doGenerate(Project project, DataContext dataContext, PsiFile psiFile);
}

可以看到在接口中我们只有一个核心的方法doGenerate,就是来生成代码的,通过如下的关键步骤来完成工作。

1: 获取用户所在的上下文信息,为后续获取相关信息做准备
2: 获取要设置属性值的目标对象,从中获取其属性信息
3:获取map源对象信息
4:织入set代码

抽象类如下:

java 复制代码
/**
 * 抽象类,提供模板方法
 */
public abstract class AbstractMap2ObjGenerator implements IMap2ObjGenerator {
    /**
     * 提取属性名称使用 ,如setXyz()则xyz就是属性名称了
     */
    protected final String setRegex = "set(\\w+)";

    /**
     * 模板方法
     * @param project
     * @param dataContext
     * @param psiFile
     */
    @Override
    public void doGenerate(Project project, DataContext dataContext, PsiFile psiFile) {
        // 1: 获取用户所在的上下文信息,为后续获取相关信息做准备
        GenerateContext generateContext = generateUserContext(project, dataContext, psiFile);
        // 2: 获取要设置属性值的目标对象,从中获取其属性信息
        TargetObjInfo targetObjInfo = generateTargetObjInfo(generateContext);
        // 3:获取map源对象信息
        SourceObjInfo sourceObjInfo = generateSourceObjInfo(generateContext);
        // 4:织入set代码
        weavingSetCode(targetObjInfo, sourceObjInfo, generateContext);
    }

    /**
     * 织入代码
     * @param targetObjInfo
     * @param sourceObjInfo
     * @param generateContext
     */
    protected abstract void weavingSetCode(TargetObjInfo targetObjInfo, SourceObjInfo sourceObjInfo, GenerateContext generateContext);

    /**
     *
     * @param generateContext
     * @return
     */
    protected abstract SourceObjInfo generateSourceObjInfo(GenerateContext generateContext);

    /**
     *
     * @param generateContext
     * @return
     */
    protected abstract TargetObjInfo generateTargetObjInfo(GenerateContext generateContext);

    /**
     *
     * @param project
     * @param dataContext
     * @param psiFile
     * @return
     */
    protected abstract GenerateContext generateUserContext(Project project, DataContext dataContext, PsiFile psiFile);

}

具体子类为Map2ObjGeneratorImpl,具体的代码就看源码吧,我觉得最重要的还是这个思路!!!

2:测试

首先创建如下测试类:

java 复制代码
public class Target {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

接着写测试代码:

java 复制代码
public class xx {
    public static void main(String[] args) {
        Map<String, String> sourceMap = new HashMap<>();
        sourceMap.put("name", "最激昂萨满");
        sourceMap.put("age", "99");

        Target target = new Target();




    }
}

按照如下步骤测试即可:

3:在idea中安装插件(用起来吧!)

因为我并没有发布到idea的插件市场,所以不能搜索到,但你可以从这里 下载安装包,通过离线安装的方式来使用,如下:

安装完成后,重启idea,如下就是安装成功了:

使用的话就和测试时一样了。

本来想上传到idea市场的,但每次提交直接给我来个服务报错,告诉我hiccup了:

我能咋办???

写在后面

参考文章列表

idea插件开发之系列

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7894 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
程序媛小果5 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot