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


    需求
    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即可
    
    转载请注明来源,谢谢
  • 相关阅读:
    边缘节点 如何判断CDN的预热任务是否执行完成刷新 路由追踪 近期最少使用算法
    查看恶意登录的尝试账号
    系统启动时发生了什么?
    JMS学习(五)--ActiveMQ中的消息的持久化和非持久化 以及 持久订阅者 和 非持久订阅者之间的区别与联系
    查找最近修改过的文件 并处理
    时间写入文件名 nohup 原理 Command In Background your shell may have its own version of nohup
    nohup COMMAND > FILE
    证明即程序、结论公式即程序类型
    C++学习注意
    C++标准库简介(转)
  • 原文地址:https://www.cnblogs.com/zhhiyp/p/9839132.html
Copyright © 2020-2023  润新知