Goland(Jetbrains Idea平台)插件开发教程(三)

前言

在上一篇教程中,简单介绍了如何编写intellij平台的live template并集成到插件中。这次介绍一下如何编写live template的macro与注册,以及从上下文中取到PsiElement,与marco接受参数。

查看自带的marco与源码

首先看一下Goland自带的macro,这几个go开头的就是Goland特有的了。

marco是继承于com.intellij.codeInsight.template.macro.MacroBase,我们根据这个继承关系就可以找到这几个marco的对应实现。



那我们就从GoFunctionParametersMacro看起吧

构造函数声明了marco的name与description,这并没有啥特别的。主要的是calculateResult这个abstract method的实现。

可以看到从context中获取到了PsiElement,objectUtils.doIfNotNull只是封装的判空,如果参数1为null就不执行函数。可以看到从GoSignature对象中获取到的GoParameters就是我们要的参数内容了,getResult只是将参数转为了List。

自行编写

小试牛刀

可以先写个template将参数和范围值作为variable输出看看。

可以看到ListResult输出的效果如下

生成sql where条件

由于平时的业务操作数据库对象基本上是主键查询,所有业务逻辑都在代码里,所以我在组内做了套根据函数参数与返回类型生成find get操作的live template。不过这玩意因业务、框架而异了。go没有像mybatis、jpa这样的框架,即使用了xorm gorm也要取到对应的对象去操作数据库,对于不同项目来说肯定不同,所以也很难出现像mybatis有专门的idea插件。我的情况也比较特殊,大多数都是主键查询,没有连表,所以才想了这样的操作。或许大家还可以发掘其他的用途吧,下面举个例子。
自定义的Macro继承MacroBase,前半部分是复制GoFunctionParametersMacro的实现,后面实现了自己对where语句的拼接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class GoSqlWhereMacro extends MacroBase {
    public GoSqlWhereMacro() {
        super("goSqlWhere", "goSqlWhere()");
    }


    @Nullable
    protected Result calculateResult(@NotNull Expression[] params, ExpressionContext context, boolean quick) {
        if (params == null) {
            return null;
        }


        PsiElement element = context.getPsiElementAtStartOffset();
        GoSignatureOwner method = (GoSignatureOwner) PsiTreeUtil.getParentOfType(element, GoSignatureOwner.class);
        GoSignature signature = (GoSignature) ObjectUtils.doIfNotNull(method, GoSignatureOwner::getSignature);
        GoParameters parameters = (GoParameters) ObjectUtils.doIfNotNull(signature, GoSignature::getParameters);
        List<GoParamDefinition> definitionList = (List<GoParamDefinition>) ObjectUtils.doIfNotNull(parameters, GoParameters::getDefinitionList);


        StringBuilder result = new StringBuilder();
        if (definitionList != null) {
            for (GoParamDefinition def :
                    definitionList) {
                result.append(def.getName()).append(" = ? ");
            }
        }
        return new TextResult(result.toString());
    }
}

注册自定义的Macro
在plugin.xml标签内添加

1
2
3
4
<extensions defaultExtensionNs="com.intellij">

    <liveTemplateMacro implementation="cn.huihongcloud.golandplugin.livetemplate.macro.GoSqlWhereMacro"/>
</extensions>

在设置中配置

效果

接受参数

还记得自带的函数参数获取输出的是带中括号的参数list,现在我们写个macro去掉中括号。还记得calculateResult的第一个参数是个数组吧,这就是嵌套的表达式。
下面的就是去掉中括号的实现。这只是介绍一下如何将一个Macro作为另一个Macro的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


public class DeBraceMarco extends MacroBase {
    public DeBraceMarco() {
        super("deBrace", "deBrace(String)");
    }


    @Override
    protected @Nullable Result calculateResult(@NotNull Expression[] expressions, ExpressionContext expressionContext, boolean b) {
        if (expressions == null) {
            return null;
        }
        if (expressions.length == 1) {
            Result result = expressions[0].calculateResult(expressionContext);
            if (result != null) {
                String s = result.toString();
                s = StringUtils.stripStart(s, "[");
                s = StringUtils.stripEnd(s, "]");
                return new TextResult(s);
            }
        }
        return null;
    }
}

省略掉在plugin.xml中注册的操作
下面是针对变量的配置,goFunctionParameters作为deBrace的参数

看看效果

小结

这篇文章介绍了live template的marco是如何编写与注册的,以及一些基础的用法。希望大家可以脑洞大开,做出一些提升开发效率的模板吧。
不过这个也因项目而异了,并不是所有项目都适合我说的这些东西施展拳脚,这里的两个例子是非常简化的版本,把可以一次性完成的东西拆成了两个模板,可能也很难看出有啥便利之处。在实际应用中,可以在同个模板中使用多个macro,我自己的情况则是利用live template把数据库get find操作各做了套模板,一次性直接生成查询与返回结果的代码,个人使用起来还是挺舒服的。

作者

ZhongHuihong

发布于

2021-09-12

更新于

2021-10-02

许可协议