zoukankan      html  css  js  c++  java
  • 添加PMD插件扫描潜在的bug

    上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等。这次继续代码健康工具类PMD。

    什么是PMD

    PMD真的不像checkstyle这样的东西所见即所得啊,去官网找了半天也没有找到解释。官网都直接说是PMD。

    We've been trying to find the meaning of the letters PMD - because frankly, we don't really know. We just think the letters sound good together.

    简单来说,PMD是一个代号,是一个静态代码检测工具。它可以用来检查

    • 潜在的bug:空的try/catch/finally/switch语句
    • 未使用的代码:未使用的局部变量、参数、私有方法等
    • 可选的代码:String/StringBuffer的滥用
    • 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
    • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs

    总之,这是一个辅助我们检测潜在bug的工具,大大减少了人工审查成本,提高编码效率。

    在gradle中使用

    gradle还是一贯的简单,新建pmd.gradle

    /**
     * The PMD Plugin
     *
     * Gradle plugin that performs quality checks on your project’s Java source files using PMD
     * and generates reports from these checks.
     *
     * Tasks:
     * Run PMD against {rootDir}/src/main/java: ./gradlew pmdMain
     * Run PMD against {rootDir}/src/test/java: ./gradlew pmdTest
     *
     * Reports:
     * PMD reports can be found in {project.buildDir}/build/reports/pmd
     *
     * Configuration:
     * PMD is very configurable. The configuration file is located at {rootDir}/config/pmd/pmd-ruleset.xml
     *
     * Additional Documentation:
     * https://docs.gradle.org/current/userguide/pmd_plugin.html
     */
    
    apply plugin: 'pmd'
    
    pmd {
        // The version of the code quality tool to be used.
        // The most recent version of PMD can be found at https://pmd.github.io
        toolVersion = "5.8.1"
    
        // The source sets to be analyzed as part of the check and build tasks.
        // Use 'sourceSets = []' to remove PMD from the check and build tasks.
        sourceSets = [project.sourceSets.main]
    
        // The directory where reports will be generated.
        reportsDir = file("$project.buildDir/reports/pmd")
    
        // Whether to allow the build to continue if there are warnings.
        ignoreFailures = false
    
        // Whether or not rule violations are to be displayed on the console.
        consoleOutput = true
    
        // The custom rule set files to be used.
        ruleSetConfig = resources.text.fromFile("$rootProject.projectDir/config/pmd/pmd-ruleset.xml")
    }
    

    添加我们的pmd-ruleset.xml配置文件, 这个ruleset有很多种,我们可以先把所有的加上,然后在开发中调整,直到找到最合适的配置方案。因为全部的规则太多,会导致你花费大量的时间解决PMD问题。

    ruleset内容可以在https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html 这里找到

    然后在build.gradle中添加

    apply from: 'pmd.gradle'
    

    执行

    ./gradlew check  或者 ./gradlew build
    

    报告位置:

    build/reports/pmd/main.html
    

    在maven中使用

    maven需要把ruleset放到resources下读取,如果是单moudle项目,直接就可以。如果是多模块项目,需要额外做一些工作。

    我们来新建一个项目来单独存储配置文件,build-tools. 在resources下放置ruleset。名字叫做pmd-ruleset.xml, 内容见https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

    然后maven install把这个子模块给安装到本地仓库。

    接着修改parent pom

    <build>
    
        <pluginManagement>
          <plugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-pmd-plugin</artifactId>
              <version>3.10.0</version>
              <dependencies>
                <dependency>
                  <groupId>com.shuwei</groupId>
                  <artifactId>build-tools</artifactId>
                  <version>0.0.1</version>
                </dependency>
              </dependencies>
              <configuration>
                <sourceEncoding>utf-8</sourceEncoding>
                <minimumTokens>100</minimumTokens>
                <targetJdk>${java.version}</targetJdk>
                <excludes>
                  <exclude>**/message/*.java</exclude>
                  <exclude>**/generated/*.java</exclude>
                </excludes>
                <excludeRoots>
                  <excludeRoot>target/generated-sources</excludeRoot>
                </excludeRoots>
                <rulesets>
                  <ruleset>pmd-ruleset.xml</ruleset>
                </rulesets>
                <printFailingErrors>true</printFailingErrors>
              </configuration>
              <executions>
                <execution>
                  <id>install</id>
                  <phase>install</phase>
                  <goals>
                    <goal>pmd</goal>
                  </goals>
                </execution>
              </executions>
            </plugin>
          </plugins>
        </pluginManagement>
    
    
        <!--所有子模块都要执行的plugin-->
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-pmd-plugin</artifactId>
          </plugin>
        </plugins>
    
      </build>
    
    
      <reporting>
        <!--所有子模块都要执行的报告-->
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-pmd-plugin</artifactId>
          </plugin>
        </plugins>
      </reporting>
    

    和上一节checkstyle不同的时候,这里的plugin下新增了dependency节点。这个节点负责加载一些资源过来,比如我们的配置文件ruleset。所以,这个dependency要先于项目存在,所以才要先单独install一下。当然,也可以把这个项目放到maven私服上,这样更简单了。

    依旧把pmd的运行绑定到install命令上,这样,我们运行maven install的时候就可以进行pmd检查了。

    检查报告在

    j-context/target/site/pmd.html
    

    也可以单独运行pmd

    mvn pmd:pmd
    

    idea插件

    搜索安装idea pmd插件,导入我们的ruleset, 然后在项目上右键,run pmd即可。

    Ruleset default内容

    可以在maven官网看到: https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

    PMD 包含 16 个规则集,涵盖了 Java 的各种常见问题,其中一些规则要比其他规则更有争议:

    基本(rulesets/basic.xml)—— 规则的一个基本合集,可能大多数开发人员都不认同它: catch 块不该为空,无论何时重写 equals(),都要重写 hashCode(),等等。

    命名(rulesets/naming.xml)—— 对标准 Java 命令规范的测试:变量名称不应太短;方法名称不应过长;类名称应当以小写字母开头;方法和字段名应当以小写字母开头,等等。

    未使用的代码(rulesets/unusedcode.xml)—— 查找从未使用的私有字段和本地变量、执行不到的语句、从未调用的私有方法,等等。

    设计(rulesets/design.xml)—— 检查各种设计良好的原则,例如: switch 语句应当有 default 块,应当避免深度嵌套的 if 块,不应当给参数重新赋值,不应该对 double 值进行相等比较。

    导入语句(rulesets/imports.xml)—— 检查 import 语句的问题,比如同一个类被导入两次或者被导入 java.lang 的类中。

    JUnit 测试(rulesets/junit.xml)—— 查找测试用例和测试方法的特定问题,例如方法名称的正确拼写,以及 suite() 方法是不是 static 和 public。

    字符串(rulesets/string.xml)—— 找出处理字符串时遇到的常见问题,例如重复的字符串标量,调用 String 构造函数,对 String 变量调用 toString() 方法。

    括号(rulesets/braces.xml)—— 检查 for、 if、 while 和 else 语句是否使用了括号。

    代码尺寸(rulesets/codesize.xml)—— 测试过长的方法、有太多方法的类以及重构方面的类似问题。

    Javabean(rulesets/javabeans.xml)—— 查看 JavaBean 组件是否违反 JavaBean 编码规范,比如没有序列化的 bean 类。

    终结函数(finalizer)—— 因为在 Java 语言中, finalize() 方法不是那么普遍(我上次编写这个代码也经是好多年前的事了),所以它们的使用规则虽然很详细,但是人们对它们相对不是很熟悉。这类检查查找 finalize() 方法的各种问题,例如空的终结函数,调用其他方法的 finalize() 方法,对 finalize() 的显式调用,等等。

    克隆(rulesets/clone.xml)—— 用于 clone() 方法的新规则。凡是重写 clone() 方法的类都必须实现 Cloneable, clone() 方法应该调用 super.clone(),而 clone() 方法应该声明抛出 CloneNotSupportedException 异常,即使实际上没有抛出异常,也要如此。

    耦合(rulesets/coupling.xml)—— 查找类之间过度耦合的迹象,比如导入内容太多;在超类型或接口就已经够用的时候使用子类的类型;类中的字段、变量和返回类型过多等。

    严格的异常(rulesets/strictexception.xml)—— 针对异常的测试:不应该声明该方法而抛出 java.lang.Exception 异常,不应当将异常用于流控制,不应该捕获 Throwable,等等。

    有争议的(rulesets/controversial.xml)—— PMD 的有些规则是有能力的 Java 程序员可以接受的。但还是有一些争议。这个规则集包含一些更有问题的检验,其中包括把 null 赋值给变量、方法中有多个返回点,以及从 sun 包导入等。

    日志(rulesets/logging-java.xml)—— 查找 java.util.logging.Logger 的不当使用,包括非终状态(nonfinal)、非静态的记录器,以及在一个类中有多个记录器。

    参考

  • 相关阅读:
    ADF中遍历VO中的行数据(Iterator)
    程序中实现两个DataTable的Left Join效果(修改了,网上第二个DataTable为空,所处的异常)
    ArcGIS api for javascript——鼠标悬停时显示信息窗口
    ArcGIS api for javascript——查询,然后单击显示信息窗口
    ArcGIS api for javascript——查询,立刻打开信息窗口
    ArcGIS api for javascript——显示多个查询结果
    ArcGIS api for javascript——用图表显示查询结果
    ArcGIS api for javascript——查询没有地图的数据
    ArcGIS api for javascript——用第二个服务的范围设置地图范围
    ArcGIS api for javascript——显示地图属性
  • 原文地址:https://www.cnblogs.com/woshimrf/p/using-pmd.html
Copyright © 2011-2022 走看看