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

相关推荐
qinzechen几秒前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#
hakesashou1 分钟前
python交互式命令时如何清除
java·前端·python
攒了一袋星辰2 分钟前
今日指数项目项目集成RabbitMQ与CaffienCatch
java·分布式·rabbitmq
wrx繁星点点8 分钟前
事务的四大特性(ACID)
java·开发语言·数据库
IT学长编程16 分钟前
计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·音乐系统·计算机毕业设计选题
IT学长编程33 分钟前
计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·协同过滤算法·计算机毕业设计选题·个性化音乐推荐系统
小小娥子38 分钟前
Redis的基础认识与在ubuntu上的安装教程
java·数据库·redis·缓存
几何心凉1 小时前
已解决:org.springframework.web.HttpMediaTypeNotAcceptableException
java
华农第一蒟蒻1 小时前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
两点王爷1 小时前
使用WebClient 快速发起请求(不使用WebClientUtils工具类)
java·网络