需求
sonar-pmd插件只有添加了pmd的java規則,如今須要添加pmd的xml規則,更準確是添加自定義的xml規則.html
步驟:
爲了更好集成和示範,選擇前人已集成p3c的sonar-pmd插件.
url: https://github.com/mrprince/sonar-p3c-pmd
git clone
到本地
集成分爲兩個環節:
1.規則配置
2.源碼修改java
規則配置
該插件首先依賴PmdRulesDefinition
對倉庫repository
進行定義,從git
extractRulesData(repository, "/org/sonar/plugins/pmd/rules.xml", "/org/sonar/l10n/pmd/rules/pmd");
方法內部,能夠得知其是讀取外部配置來初始化pmd的rules.
一共有四處須要配置:
/org/sonar/plugins/pmd/rules.xml
/org/sonar/l10n/pmd/rules/pmd
/com/sonar/sqale/pmd-model.xml
/org/sonar/l10n/pmd.properties
對於配置,沒有什麼多說的,原則就是模仿!
l10n
下的html是須要和rule的key一致.做用是sonar的rule頁面展現.
pmd.properties
的rule.pmd-xml.MistypedCDATASection.name
中,rule.pmd-xml
表明repository名字,須要一致.github
源碼修改
在PmdRulesDefinition
類的define(Context context)
裏能夠看到extractRulesData
是讀取配置信息,若是想分別管理不一樣類型的規則,例如pmd原生和p3c規則,就能夠分別配置,另外讀取.
NewRepository
類是和sonar的規則語言綁定的,因此另外增長一個新的repository對象,添加Xml.Key
pom.xml
新增依賴:maven
<dependency> <groupId>org.sonarsource.sonar-xml-plugin</groupId> <artifactId>sonar-xml-plugin</artifactId> <version>1.3</version> <scope>provided</scope> </dependency>
NewRepository xmlRepository = context .createRepository(PmdConstants.XML_REPOSITORY_KEY, Xml.KEY) .setName(PmdConstants.XML_REPOSITORY_NAME);
模仿以前的repository設置,將一些常量寫在PmdConstants
類裏,後續還會常常用到這個string值.ide
入口:PmdSensor
真正的入口是PmdSensor
,重寫父類Sensor
的analyse
方法,定位到這個方法,繼續開始修改.
由於添加了一個新的倉庫,並且從源碼得知,一開始代碼只是支持java的規則,所有都是寫死的,如今須要新增xml. 修改該類的shouldExecuteOnProject
和hasFilesToCheck
,這裏顯然也是和sonar接口對接的方法,用於判斷是否執行的.編碼
@Override public boolean shouldExecuteOnProject(Project project) { return (hasFilesToCheck(Type.MAIN, PmdConstants.REPOSITORY_KEY)) || (hasFilesToCheck(Type.TEST, PmdConstants.TEST_REPOSITORY_KEY)) || (hasFilesToCheck(Type.MAIN, PmdConstants.XML_REPOSITORY_KEY)) ; } private boolean hasFilesToCheck(Type type, String repositoryKey) { FilePredicates predicates = fs.predicates(); Iterable<File> files = fs.files(predicates.or( predicates.and(predicates.hasLanguage(Xml.KEY),predicates.hasType(type)), predicates.and(predicates.hasLanguage(Java.KEY), predicates.hasType(type)))); return !Iterables.isEmpty(files) && !profile.getActiveRulesByRepository(repositoryKey).isEmpty(); }
新增了xml的判斷,Type.MAIN
是表明掃描的source是在src/main下,和src/test對應.FilePredicates
很像以前接觸的FileFilter
類,使用方式也很像,爲了有xml或java時都返回true,就在外面寫一個predicates.or
,這種類的設計感受除了寫着麻煩,實際上很好理解.
接下來從analyse
方法一步步進去,遇到有硬編碼和判斷語言類型的地方就着手修改.url
PmdExecutor
執行pmd的地方.插件
private Report executePmd(URLClassLoader classLoader) { ... PmdTemplate pmdFactory = createPmdTemplate(classLoader); executeRules(pmdFactory, context, javaFiles(Type.MAIN), PmdConstants.REPOSITORY_KEY); ... return report; }
能夠看到,是經過PmdTemplate來執行rules,模仿它新增一句:
executeRules(pmdFactory, context, xmlFiles(Type.MAIN), PmdConstants.XML_REPOSITORY_KEY);
而且提供本身的xmlFiles
方法,基於語言過濾.
爲了一探究竟,順便看看PmdTemplate
類
從代碼看是經過create
方法初始化PMDConfiguration
和SourceCodeProcessor
兩個對象.SourceCodeProcessor
是傳入InputStream
和rulesets
來分析每一個文件的PMD核心分析類.
經過languageVersions
來控制可以使用何種語言的rule.
原先是隻添加了java的LanguageModule,如今須要增長xml部分.對pmd源碼進行分析,便可知道new XmlLanguageModule().getVersion("")
可得到xml的languageVersion
.設計
PmdViolationRecorder
輸出
最後輸出的地方仍舊須要修改.
private Rule findRuleFor(RuleViolation violation) { String ruleKey = violation.getRule().getName(); Rule xmlRule = ruleFinder.findByKey(PmdConstants.XML_REPOSITORY_KEY, ruleKey); if (xmlRule != null) { return xmlRule; } Rule rule = ruleFinder.findByKey(PmdConstants.REPOSITORY_KEY, ruleKey); if (rule != null) { return rule; } return ruleFinder.findByKey(PmdConstants.TEST_REPOSITORY_KEY, ruleKey); }
這裏須要添加 xmlRule,不然是找一個普通javaRule,沒有則返回java的testRule
源碼改的差很少了.但test裏的類還須要修改,若是直接執行,會有部分類報錯,由於它test裏也是硬編碼了java的.固然也能夠選擇-Dmaven.test.skip=true
.
本文對應github地址:
https://github.com/phinehasz/sonar-pmd-xml-plugin
最快捷的辦法,下載個人代碼,在其基礎上新增配置.
git clone https://github.com/phinehasz/sonar-pmd-xml-plugin mvn package 放到sonar{version}\extensions\plugins restart sonar便可