需求
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便可