Sonar Java 规则插件开发 (基于阿里开发手册) - Go语言中文社区

Sonar Java 规则插件开发 (基于阿里开发手册)


引言

最近在做Sonar静态代码扫描管理,以此顺手接了Sonar的插件开发,基于阿里开发手册进行开发,在整体开发过程中,其中还是遇到不少坑位,也以此给大家做相应借鉴

官网Demo演示插件开发地址:
https://docs.sonarqube.org/display/PLUG/Writing+Custom+Java+Rules+101
基于官网的我暂时不多说,基础框架按照官网的范例进行搭建即可

开源地址:

https://github.com/tigerge000/sonar-java-custom-rules.git

sonar常用方法说明

范例

需求:【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类 命名以它要测试的类的名称开始,以 Test 结尾。
实现:
AbstractClassNameCheck

package org.finger.java.rule.checks.namerules;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.tree.*;

/**
 * 抽象类命名检查
 * 抽象类命名使用 Abstract 或 Base 开头
 * Created by 古月随笔 on 2017/3/17.
 */
@Rule(key = "AbstractClassNameCheck")
public class AbstractClassNameCheck extends BaseTreeVisitor implements JavaFileScanner{

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractClassNameCheck.class);

    private JavaFileScannerContext context;

    @Override
    public void scanFile(JavaFileScannerContext context) {
        this.context = context;
        scan(context.getTree());
    }

    @Override
    public void visitClass(ClassTree tree) {
        String className = tree.simpleName().name();

        LOGGER.info(className + "<<>>" + tree.symbol().isAbstract());


        if(tree.symbol().isAbstract()){
            //判断名称是否以Abstract 或 Base 开头

            String abName = "Abstract";
            String bsName = "Base";
            //判断类名如果小于Abstract 或 Base
            if (className.length() < abName.length() || className.length() < bsName.length()) {
                context.reportIssue(this, tree, "The Name Of Abstract Class should use Abstract or Base first");
            } else {
                //判断是否存在 Abstract 或 Base
                if (!className.contains(abName)) {
                    if (!className.contains(bsName)) {
                        context.reportIssue(this, tree, "The Name Of Abstract Class should use Abstract or Base first");
                    } else {
                        if (className.indexOf(bsName) != 0) {
                            context.reportIssue(this, tree, "The Name Of Abstract Class should use Abstract or Base first");
                        }
                    }
                } else {
                    if (className.indexOf(abName) != 0) {
                        context.reportIssue(this, tree, "The Name Of Abstract Class should use Abstract or Base first");
                    }
                }
            }
        }
        super.visitClass(tree);
    }

}

resources目录下添加目录:org.sonar.l10n.java.rules.squid(这命名主要是由于sonar源码中固定写死的)
AbstractClassNameCheck.html

<p>AbstractClassNameCheck Check</p>
<h2>Noncompliant Code Example</h2>
<pre>
    public abstract class HiClass {// Noncompliant
    }

    public abstract class MyNameIsAbstract {// Noncompliant
    }
</pre>
<h2>Compliant Solution</h2>
<pre>
    public abstract class AbstractMysql {
    }

    public abstract class BaseMysql {
    }
</pre>

AbstractClassNameCheck.json

{
  "title": "The Name Of Abstract Class should use Abstract or Base first",
  "status": "ready",
  "remediation": {
    "func": "Constant/Issue",
    "constantCost": "5min"
  },
  "tags": [
    "bug",
    "pitfall"
  ],
  "defaultSeverity": "CRITICAL"
}

AbstractClassNameCheck_java.json(为什么有这个文件,主要是由于进行单测的时候,sonar源码内容写死是xxxx_java.json命名)

{
  "title": "The Name Of Abstract Class should use Abstract or Base first",
  "status": "ready",
  "remediation": {
    "func": "Constant/Issue",
    "constantCost": "5min"
  },
  "tags": [
    "bug",
    "pitfall"
  ],
  "defaultSeverity": "CRITICAL"
}

单测:
AbstractClassNameCheckTest

package org.finger.java.rule.checks.namerules;

import org.junit.Test;
import org.sonar.java.checks.verifier.JavaCheckVerifier;

/**
 * Created by huqingen on 2017/3/17.
 */
public class AbstractClassNameCheckTest {
    @Test
    public void test() {
        JavaCheckVerifier.verify("src/test/files/HiClass.java", new AbstractClassNameCheck());
    }

    @Test
    public void test1() {
        JavaCheckVerifier.verify("src/test/files/MyNameIsAbstract.java", new AbstractClassNameCheck());
    }

    @Test
    public void test2() {
        JavaCheckVerifier.verify("src/test/files/BaseMysql.java", new AbstractClassNameCheck());
    }
    @Test
    public void test3() {
        JavaCheckVerifier.verify("src/test/files/AbstractMysql.java", new AbstractClassNameCheck());
    }
}

开发目录结构:

PS:
1.由于编辑的时候经常出现crash问题,暂时先写到这,��,真不是故意
2.编写sonar规则的时候,给个建议,采用Debug方式调试整个tree里面的内容,针对性的编写自己想要的规则,sonar在这块扫描基础方法做的还是很棒的

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/tigereg000/article/details/79312022
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 10:58:18
  • 阅读 ( 1897 )
  • 分类:职场

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢