1、maven依赖 本开发教程适用于sonarqube5.x、6.x。
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > wxtx</groupId > <artifactId > TestSonar</artifactId > <version > 0.0.1-SNAPSHOT</version > <packaging > sonar-plugin</packaging > <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <sonar.version > 6.3</sonar.version > <java.plugin.version > 4.7.1.9272</java.plugin.version > <sslr.version > 1.21</sslr.version > <gson.version > 2.6.2</gson.version > </properties > <dependencies > <dependency > <groupId > org.sonarsource.sonarqube</groupId > <artifactId > sonar-plugin-api</artifactId > <version > ${sonar.version}</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.sonarsource.java</groupId > <artifactId > sonar-java-plugin</artifactId > <type > sonar-plugin</type > <version > ${java.plugin.version}</version > </dependency > <dependency > <groupId > org.sonarsource.java</groupId > <artifactId > java-frontend</artifactId > <version > ${java.plugin.version}</version > </dependency > <dependency > <groupId > org.sonarsource.sslr-squid-bridge</groupId > <artifactId > sslr-squid-bridge</artifactId > <version > 2.6.1</version > <exclusions > <exclusion > <groupId > org.codehaus.sonar.sslr</groupId > <artifactId > sslr-core</artifactId > </exclusion > <exclusion > <groupId > org.codehaus.sonar</groupId > <artifactId > sonar-plugin-api</artifactId > </exclusion > <exclusion > <groupId > org.codehaus.sonar.sslr</groupId > <artifactId > sslr-xpath</artifactId > </exclusion > <exclusion > <groupId > org.slf4j</groupId > <artifactId > jcl-over-slf4j</artifactId > </exclusion > <exclusion > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.sonarsource.java</groupId > <artifactId > java-checks-testkit</artifactId > <version > ${java.plugin.version}</version > </dependency > <dependency > <groupId > com.google.code.gson</groupId > <artifactId > gson</artifactId > <version > ${gson.version}</version > </dependency > <dependency > <groupId > org.sonarsource.sslr</groupId > <artifactId > sslr-testing-harness</artifactId > <version > ${sslr.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > 1.6.2</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > </dependency > <dependency > <groupId > org.assertj</groupId > <artifactId > assertj-core</artifactId > <version > 3.6.1</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > 0.9.30</version > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.sonarsource.sonar-packaging-maven-plugin</groupId > <artifactId > sonar-packaging-maven-plugin</artifactId > <version > 1.17</version > <extensions > true</extensions > <configuration > <pluginDescription > test</pluginDescription > <pluginKey > java-custom</pluginKey > <pluginName > Java Custom Rules</pluginName > <pluginClass > wxtx.com.MySonarPlugin</pluginClass > <sonarLintSupported > true</sonarLintSupported > <sonarQubeMinVersion > 5.6</sonarQubeMinVersion > </configuration > </plugin > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > 3.6.0</version > <configuration > <source > 1.8</source > <target > 1.8</target > </configuration > </plugin > </plugins > </build > </project >
2、制定规则 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Rule ( key = "TXAbstractClassNameCheck" , name = "抽象类命名使用TXAbstract或TXBase开头" , description = "抽象类命名使用TXAbstract或TXBase开头" , tags = {"wxtx-java" }, priority = Priority.MINOR) @SqaleSubCharacteristic (RulesDefinition.SubCharacteristics.ARCHITECTURE_CHANGEABILITY)@SqaleConstantRemediation ("10min" )public class TXAbstractClassNameCheck extends BaseTreeVisitor implements JavaFileScanner { private JavaFileScannerContext context; public void scanFile (JavaFileScannerContext context) { this .context = context; scan(context.getTree()); } @Override public void visitClass (ClassTree tree) { if (tree == null || tree.simpleName() == null ){ super .visitClass(tree); return ; } String className = tree.simpleName().name(); boolean isAbstract = tree.symbol().isAbstract(); if (isAbstract && isNameIll(className)){ context.reportIssue(this , tree, "抽象类命名使用TXAbstract或TXBase开头" ); } super .visitClass(tree); } private boolean isNameIll (String className) { return !className.startsWith("TXAbstract" ) && !className.startsWith("TXBase" ); } }
3、注册规则 3.1、自定义插件入口
1 2 3 4 5 6 public class TXSonarPlugin implements Plugin { public void define (Context context) { context.addExtension(TXJavaRulesDefinition.class); context.addExtension(TXJavaFileCheckRegistrar.class); } }
3.2、server extensions 在sonarqube server启动时实例化,实现org.sonar.api.server.rule.RulesDefinition接口
1 2 3 4 5 6 7 8 9 public class TXJavaRulesDefinition implements RulesDefinition { public static final String REPOSITORY_KEY = "TXRepo" ; public void define (Context context) { NewRepository repository = context.createRepository(REPOSITORY_KEY,Java.KEY); repository.setName("Java编码规范" ); AnnotationBasedRulesDefinition.load(repository, "java" ,TXRulesList.getChecks()); repository.done(); } }
3.3、batch extensions 在分析代码的时候实例化,实现org.sonar.plugins.java.api.CheckRegistrar接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class TXJavaFileCheckRegistrar implements CheckRegistrar { public void register (RegistrarContext registrarContext) { registrarContext.registerClassesForRepository(TXJavaRulesDefinition.REPOSITORY_KEY, Arrays.asList(checkClasses()), Arrays.asList(testCheckClasses())); } public static Class<? extends JavaCheck>[] checkClasses() { new Class[] {TXAbstractClassNameCheck.class}; } @SuppressWarnings ("unchecked" ) public static Class<? extends JavaCheck>[] testCheckClasses() { return new Class[] {}; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class TXRulesList { private TXRulesList () { } 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(TXAbstractClassNameCheck.class).build(); } public static List<Class<? extends JavaCheck>> getJavaTestChecks() { return ImmutableList.<Class<? extends JavaCheck>>builder().build(); } }
4、输出 maven执行命令mvn clean install输出jar包,其中修改MANIFEST.MF的Plugin-Dependencies,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Manifest-Version: 1.0 Plugin-Dependencies: META-INF/lib/* Plugin-Description: test Plugin-BuildDate: 2017-11-08T12:12:27+0800 Archiver-Version: Plexus Archiver SonarLint-Supported: true Built-By: Administrator Plugin-License: Plugin-Version: 0.0.1-SNAPSHOT Sonar-Version: 5.6 Plugin-Developers: Plugin-ChildFirstClassLoader: false Plugin-Key: javacustom Plugin-Class: wxtx.com.MySonarPlugin Created-By: Apache Maven 3.3.9 Build-Jdk: 1.8.0_144 Plugin-Name: Java Custom Rules
并将依赖的jar包复制进META-INF/lib/目录下(例如guava、sonar-plugin-api)
5、测试 5.1、将自定义插件jar放到sonar下的extensions/plugins路径下 5.2、启动SonarQube 5.3、激活规则:登录admin账号后,点击activate按钮激活规则
6、参考 [1]sonar-custom-rules-examples