zoukankan      html  css  js  c++  java
  • sonar自定义规则

    Sonar并不是简单地把不同的代码检查工具结果(例如 FindBugs,PMD 等)直接显示在 Web 页面上,而是通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。

    sonarqubue默认的对java的检测规则不一定适合我们,可以自己去自定义rules。

    禁用rules

    Rules-Quality Profile- Sonar way Java
    查看激活的规则,可以禁用,或者更改严重级别(Severity)
    图片描述

    自定义rules

    sonar提供XPath或Java方式的扩展,有的语言支持XPath,有的只能支持Java,比如Java语言只支持Java方式的扩展。具体详见Support of Custom Rules by Language

    步骤如下:

    • 创建一个SonarQube插件

    • 增加相关依赖

    • 创建自定义rules

    • 生成插件的jar包

    • 将该jar包放在SONARQUBE_HOME/extensions/plugins目录下

    • 重启SonarQube

    添加maven依赖

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
    
            <sonar-plugin-api.version>5.6</sonar-plugin-api.version>
            <sonar-java-plugin.version>4.2</sonar-java-plugin.version>
            <sonar-packaging-maven-plugin.version>1.17</sonar-packaging-maven-plugin.version>
    
            <sslr-testing-harness.version>1.20</sslr-testing-harness.version>
            <junit.version>4.12</junit.version>
            <fest-assert.version>1.4</fest-assert.version>
            <logback-classic.version>1.1.3</logback-classic.version>
    
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.sonarsource.sonarqube</groupId>
                <artifactId>sonar-plugin-api</artifactId>
                <version>${sonar-plugin-api.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.sonarsource.java</groupId>
                <artifactId>sonar-java-plugin</artifactId>
                <version>${sonar-java-plugin.version}</version>
                <type>sonar-plugin</type>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.sonarsource.java</groupId>
                <artifactId>java-checks-testkit</artifactId>
                <version>${sonar-java-plugin.version}</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>org.codehaus.sonar.sslr</groupId>
                <artifactId>sslr-testing-harness</artifactId>
                <version>${sslr-testing-harness.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.easytesting</groupId>
                <artifactId>fest-assert</artifactId>
                <version>${fest-assert.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback-classic.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!--http://stackoverflow.com/questions/35369058/custom-plugin-for-sonarqube-5-2-produces-noclassdeffounderror-->
            <!-- https://mvnrepository.com/artifact/org.codehaus.sonar.sslr-squid-bridge/sslr-squid-bridge -->
            <dependency>
                <groupId>org.codehaus.sonar.sslr-squid-bridge</groupId>
                <artifactId>sslr-squid-bridge</artifactId>
                <version>2.6</version>
                <!--记得exclude掉sonar-plugin-api,才可以加载其他相关依赖-->
                <exclusions>
                    <exclusion>
                        <groupId>org.codehaus.sonar</groupId>
                        <artifactId>sonar-plugin-api</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.6.2</version>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>19.0</version>
            </dependency>
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.10</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.4</version>
            </dependency>
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>2.6</version>
            </dependency>
    
    
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
                    <artifactId>sonar-packaging-maven-plugin</artifactId>
                    <version>${sonar-packaging-maven-plugin.version}</version>
                    <extensions>true</extensions>
                    <configuration>
                        <pluginKey>java-custom</pluginKey>
                        <pluginName>Java Custom Rules</pluginName>
                        <!-- your plugin class -->
                        <pluginClass>com.xixicat.sonar.MySonarPlugin</pluginClass>
                        <sonarLintSupported>true</sonarLintSupported>
                        <sonarQubeMinVersion>5.6</sonarQubeMinVersion> <!-- allow to depend on API 6.x but run on LTS -->
                    </configuration>
                </plugin>
            </plugins>
        </build>

    这里的依赖要小心配置,记得exclude掉sonar-plugin-api,才可以加载其他相关依赖,然后显示依赖用到的jar,否则容易报class not found

    编写plugin

    创建plugin入口

    public class MySonarPlugin implements Plugin {
        public void define(Context context) {
    // server extensions -> objects are instantiated during server startup
            context.addExtension(MyJavaRulesDefinition.class);
    
            // batch extensions -> objects are instantiated during code analysis
            context.addExtension(MyJavaFileCheckRegistrar.class);
        }
    }

    这个类实现了org.sonar.api.Plugin接口,主要添加两类扩展:

    • server extensions
      在sonarqube server启动时实例化,实现org.sonar.api.server.rule.RulesDefinition接口

    public class MyJavaRulesDefinition implements RulesDefinition {
    
        public static final String REPOSITORY_KEY = "myRepo";
    
        public void define(Context context) {
            NewRepository repository = context.createRepository(REPOSITORY_KEY, Java.KEY);
            repository.setName("my sonar repo");
            AnnotationBasedRulesDefinition.load(repository, "java", RulesList.getChecks());
            repository.done();
        }
    }
    
    public class RulesList {
    
        private RulesList() {
        }
    
        public static List<Class> getChecks() {
            return ImmutableList.<Class>builder().addAll(getJavaChecks()).addAll(getJavaTestChecks()).build();
        }
    
        public static List<Class<? extends JavaCheck>> getJavaChecks() {
            return ImmutableList.<Class<? extends JavaCheck>>builder()
                    .add(AvoidSmallerLengthVariableNameRule.class)
                    .build();
        }
    
        public static List<Class<? extends JavaCheck>> getJavaTestChecks() {
            return ImmutableList.<Class<? extends JavaCheck>>builder()
                    .build();
        }
    }
    
    • batch extensions
      在分析代码的时候实例化,实现org.sonar.plugins.java.api.CheckRegistrar接口

    public class MyJavaFileCheckRegistrar implements CheckRegistrar {
        public void register(RegistrarContext registrarContext) {
            // Call to registerClassesForRepository to associate the classes with the correct repository key
            registrarContext.registerClassesForRepository(MyJavaRulesDefinition.REPOSITORY_KEY,
                    Arrays.asList(checkClasses()), Arrays.asList(testCheckClasses()));
        }
    
        /**
         * Lists all the checks provided by the plugin
         */
        public static Class<? extends JavaCheck>[] checkClasses() {
            return new Class[] { // List of rules to be included here
                    AvoidSmallerLengthVariableNameRule.class
            };
        }
    
        /**
         * Lists all the test checks provided by the plugin
         */
        public static Class<? extends JavaCheck>[] testCheckClasses() {
            return new Class[] {};
        }
    }

    创建规则

    import org.sonar.api.server.rule.RulesDefinition;
    import org.sonar.check.Priority;
    import org.sonar.check.Rule;
    import org.sonar.check.RuleProperty;
    import org.sonar.plugins.java.api.JavaFileScanner;
    import org.sonar.plugins.java.api.JavaFileScannerContext;
    import org.sonar.plugins.java.api.tree.BaseTreeVisitor;
    import org.sonar.plugins.java.api.tree.VariableTree;
    import org.sonar.squidbridge.annotations.SqaleConstantRemediation;
    import org.sonar.squidbridge.annotations.SqaleSubCharacteristic;
    
    @Rule(key = "AvoidSmallerLengthLocalVariableName",
            name = "Avoid usage of the smaller length in local variable name",
            description = "This rule detects usage of smaller length local variable name. Variable name should not be smaller than 4 characters.",
            tags = {"coding-guideline"},
            priority = Priority.MINOR)
    @SqaleSubCharacteristic(RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY)
    //SQALE全称是Software Quality Assessment based on Lifecycle Expectations,是一套评估代码质量的方法。
    @SqaleConstantRemediation("10min") //纠正所需时间
    public class AvoidSmallerLengthVariableNameRule extends BaseTreeVisitor implements JavaFileScanner {
    
        private static final String DEFAULT_VALUE = "SmallerLengthLocalVariable";
    
        private JavaFileScannerContext context;
    
        /**
         * Avoid usage of the smaller length in local variable name in Quality profiles.
         * The key
         */
        @RuleProperty(
                defaultValue = DEFAULT_VALUE,
                description = "Avoid usage of the smaller length in local variable name")
        protected String name;
    
        public void scanFile(JavaFileScannerContext context) {
            this.context = context;
            scan(context.getTree());
        }
    
    
        @Override
        public void visitVariable(VariableTree tree) {
            String variableName = tree.simpleName().name();
            System.out.println("Scanning the variable : " + variableName);
            if(variableName.length() < 4) {
                context.reportIssue(this,tree, "Variable length is less than 4 characters");
            }
            super.visitVariable(tree);
        }
    }

    打包plugin

    mvn clean package sonar-packaging:sonar-plugin

    拷贝到plugins

    cp target/sonar-rule-demo-0.0.1-SNAPSHOT.jar ~/sonar/extensions/plugins

    run

    docker run --rm  
     -e JAVA_OPTS='-Xmx1g' 
      -v /Users/xixicat/sonar/data:/opt/sonarqube/data 
      -v /Users/xixicat/sonar/extensions:/opt/sonarqube/extensions 
      -p 9000:9000 -p 9092:9092 
      -e SONARQUBE_JDBC_USERNAME=sonar 
      -e SONARQUBE_JDBC_PASSWORD=sonar 
      sonarqube:lts-alpine

    查看自定义的规则

    图片描述

    doc

  • 相关阅读:
    Could A New Linux Base For Tablets/Smartphones Succeed In 2017?
    使用libhybris,glibc和bionic共存时的TLS冲突的问题
    6 Open Source Mobile OS Alternatives To Android in 2018
    Using MultiROM
    GPU drivers are written by the GPU IP vendors and they only provide Android drivers
    Jolla Brings Wayland Atop Android GPU Drivers
    How to Use Libhybris and Android GPU Libraries with Mer (Linux) on the Cubieboard
    闲聊Libhybris
    【ARM-Linux开发】wayland和weston的介绍
    Wayland and X.org problem : Why not following the Android Solution ?
  • 原文地址:https://www.cnblogs.com/xiang--liu/p/9710101.html
Copyright © 2011-2022 走看看