【持续集成】如何用sonar-pmd插件集成pmd-xml的规则

摘要:
Iterables.isEmpty(files)&&!

需求
sonar-pmd插件只有添加了pmd的java规则,现在需要添加pmd的xml规则,更准确是添加自定义的xml规则.

步骤:
为了更好集成和示范,选择前人已集成p3c的sonar-pmd插件.
url: https://github.com/mrprince/sonar-p3c-pmd
git clone 到本地
集成分为两个环节:
1.规则配置
2.源码修改

规则配置
该插件首先依赖PmdRulesDefinition对仓库repository进行定义,从

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.propertiesrule.pmd-xml.MistypedCDATASection.name中,rule.pmd-xml代表repository名字,需要一致.

源码修改
PmdRulesDefinition类的define(Context context)里可以看到extractRulesData是读取配置信息,如果想分别管理不同类型的规则,例如pmd原生和p3c规则,就可以分别配置,另外读取.
NewRepository类是和sonar的规则语言绑定的,所以另外增加一个新的repository对象,添加Xml.Key
pom.xml 新增依赖:

<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值.

入口:PmdSensor
真正的入口是PmdSensor,重写父类Sensoranalyse方法,定位到这个方法,继续开始修改.
因为添加了一个新的仓库,而且从源码得知,一开始代码只是支持java的规则,全部都是写死的,现在需要新增xml. 修改该类的shouldExecuteOnProjecthasFilesToCheck,这里显然也是和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方法一步步进去,遇到有硬编码和判断语言类型的地方就着手修改.

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方法初始化PMDConfigurationSourceCodeProcessor两个对象.SourceCodeProcessor是传入InputStreamrulesets来分析每个文件的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}extensionsplugins 
restart sonar即可

免责声明:文章转载自《【持续集成】如何用sonar-pmd插件集成pmd-xml的规则》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇(appium+python)UI自动化_02_appium启动手机appSpring-SpringMVC父子容器&amp;amp;AOP使用总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android 4.0 SDK的离线方式安装(转)

转自:http://networking.ctocio.com.cn/110/12195610.shtml  作 为一个IT技术人员,迫不及待地就奔向了http://developer.android.com去看看有没有新的SDK公布出来,当时是上午,没见到 有更新,心想一定是若干天后才会发布。没想到同事下午告诉我,新版的SDK已经发布了。当时是临下班,...

【转好文】c程序员学习perl

给C程序员的提示 Perl结合了多种编程语言的特性,C语言也在其中。Perl和C有以下相同之处: ·1.分号是每个简单语句必需的,换行不能表示语句结束。 ·2.数组下标也是从0开始,Perl中像substr这样的字符串函数也是从0开始计算位置的。 ·3.逗号操作符的作用一样。 ·4.&&和||操作符作用一样。然而,Perl和C毕竟是两...

Tomcat学习总结(2)——Tomcat使用详解

一、Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件。 如果想修改Tomcat服务器的启动端口,则可以在server.xml配置文件中的Connector节点进行的端口修改 例如:将Tomcat服务器的启动端口由默认的8080改成8081端口 Tomcat服务器启动端口默认配置 1...

Gradle里配置jetty实现静态资源的热部署

通过Gradle我们可以很方便的使用内置jetty启动我们的web程序,在本地进行调试。但是在使用的过程中,我发现了几个问题,导致本地调试的效率大受影响。 如果使用gradle jettyRun启动jetty服务器后,项目里的静态资源(jsp,html,JavaScript文件)都被锁定了,导致无法实时修改这些静态资源。 既然无法实时修改这些静态资源,...

JAXB的介绍(转载)

< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 一、前言。最近正在做一个项目,根据需求计划需要一种Object <--> XML的工具,而JAXB就非常符合需求,于是以下是近天来的研究心得。 二、JAXB技术介绍 1.什么是JAX...

android 项目中设置背景图片

xml文件设置背景图片中:任意一个控件,button imageView 或layout,在其的xml属性设置中,添加 [XML] view plaincopy android:background="@drawable/bg"     即可实现设置其背景图片为bg. 图片存放在drawable目录下。 drawable目录下存放大小图标...