如何使用 gradle-pmd-plugin 添加自定义 java pmd 规则到 gradle 项目?

How to add custom java pmd rules to gradle project using gradle-pmd-plugin?

在项目 arch4u-pmd 的工作期间,我们制定了几个基于 java 的 pmd 规则,将它们配置在基于 XML 的规则集 our-rules.xml 中,并将其作为普通文件发布java lib/artifact (io.github.abc:my-pmd-rules:0.1.0) 到我们的工件存储库。 工件结构如下所示:

> unzip -l my-pmd-rules-0.1.0.jar   
Archive:  my-pmd-rules-0.1.0.jar   
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  02-15-2022 00:24   META-INF/
      139  02-15-2022 00:24   META-INF/MANIFEST.MF
        0  02-15-2022 00:24   io/
        0  02-15-2022 00:24   io/github/
        0  02-15-2022 00:24   io/github/rules/
        ...
     4781  02-15-2022 00:24   io/github/rules/MissingMandatoryAnnotation.class
     ...
     1138  02-15-2022 00:24   io/github/rules/our-rules.xml
     ...

我们如何使用 pmd plugin 将它们添加到 Gradle 项目?

我们必须处理以下 materials/questions/answers:

  1. https://whosebug.com/search?page=2&tab=Relevance&q=pmd%20classpath
  2. Gradle's PMD plugin: what are acceptable arguments?
  3. Adding a ruleset to PMD?
  4. https://discuss.gradle.org/t/pmd-ruleset-not-available-in-classpath/7201
  5. https://discuss.gradle.org/t/custom-rules-with-pmd-plugin/5859/4
  6. How to configure PMD Auxiliary classpath in Sonar
  7. https://docs.gradle.org/current/userguide/pmd_plugin.html
  8. https://github.com/gradle/gradle/blob/master/subprojects/code-quality/src/main/groovy/org/gradle/api/plugins/quality/PmdPlugin.java
  9. Custom PMD rule with Gradle也不行
    tasks.withType(Pmd) {
       pmdClasspath += file("path/to/rules.jar")
    }
    

在 Gradle pmd 插件的官方文档中,有一个依赖部分解释了 high-level 这方面的内容,但没有实际示例:

  1. pmd - 要使用的 PMD 库
  2. pmdAux - 在分析期间可用于类型解析的附加库。如果 PMD 抱怨缺少 类.
  3. ,这可能会有用

为了将自定义 java 规则添加到您的项目

  1. 使用Gradle插件

    apply plugin: 'pmd'
    
    repositories {
       mavenCentral() // if your rules in Maven Central
       mavenLocal()   // if your rules is in .m2 folder 
       maven {
          // if your rules are in some custom/self-hosted artifacts repository like Nexus
       }
    }
    
    dependencies {
       ...
       pmd "io.github.abc:my-pmd-rules:0.1.0" 
       pmd "commons-io:commons-io:2.11.0"     // required dependency by pmd engine
       ...
    }
    
    pmd {
       consoleOutput = true
       ruleSetFiles = files("io/github/rules/our-rules.xml")    // exactly path as in your lib classpath
       ruleSets = []                                            // Keep it as is, workaround for pmd
    }
    
  2. 使用 Maven 插件

    ...
    <build>
     <plugins>
       ...
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-pmd-plugin</artifactId>
         <version>3.15.0</version>
         <executions>
           <execution>
             <phase>test</phase>
             <goals>
               <goal>check</goal>
             </goals>
           </execution>
         </executions>
         <configuration>
           <printFailingErrors>true</printFailingErrors>
           <rulesets>
             ...
             <ruleset>io/github/rules/our-rules.xml</ruleset> <!-- exactly path as in your lib classpath -->
             ...
           </rulesets>
           <excludeRoots>
             <excludeRoot>target/generated-sources/</excludeRoot>
           </excludeRoots>
         </configuration>
         <dependencies>
           <!-- your custom rules -->
           <dependency>
             <groupId>io.github.abc</groupId>
             <artifactId>my-pmd-rules</artifactId>
             <version>0.1.0</version>
           </dependency>
         </dependencies>
       </plugin>
       ...
     </plugins>
    </build>
     ...
    
  3. 如果您已经有一个规则集并且您只想包含自定义 Java 规则(来自库),您可以直接在您的规则集中定义它 xml原样:

      <!-- Define a rule -->
      <rule name="TheRuleName"
            language="java"
            externalInfoUrl="https://link.to.your.rule.official.docs.com"
            message="The violation message regarding your rule"
            class="io.github.rules.MissingMandatoryAnnotation">
        <priority>3</priority>
        <properties>
           ...
        </properties>
      </rule>