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插件开发之系列

相关推荐
花开富贵ii42 分钟前
代码随想录算法训练营四十三天|图论part01
java·数据结构·算法·深度优先·图论
布朗克1682 小时前
Java 10 新特性及具体应用
java·开发语言·新特性·java10
ZZHow10245 小时前
JavaWeb开发_Day05
java·笔记·web
CHEN5_025 小时前
【Java虚拟机】垃圾回收机制
java·开发语言·jvm
Warren985 小时前
Lua 脚本在 Redis 中的应用
java·前端·网络·vue.js·redis·junit·lua
艾伦~耶格尔9 小时前
【数据结构进阶】
java·开发语言·数据结构·学习·面试
爪洼传承人9 小时前
18- 网络编程
java·网络编程
smileNicky9 小时前
SpringBoot系列之从繁琐配置到一键启动之旅
java·spring boot·后端
祈祷苍天赐我java之术10 小时前
Java 迭代器(Iterator)详解
java·开发语言
David爱编程10 小时前
为什么必须学并发编程?一文带你看懂从单线程到多线程的演进史
java·后端