☰
PMD 7.x 版本演进全览:从 7.0.0 大重构到 7.28 的规则、语言与工程能力盘点
2026/10/12 15:46:40 网站建设 项目流程
  • 静态分析
  • 代码质量

【免费下载链接】pmd

An extensible multilanguage static code analyzer.

项目地址:https://gitcode.com/gh_mirrors/pm/pmd
点击查看免费下载

PMD 是业界广泛使用的可扩展多语言静态代码分析器,其 7.x 系列从 2023 年的首个 RC 一路演进到 2026 年的 7.28.0,完整经历了「大版本重构 → 逐版本打磨」的整个过程。本文以仓库内的 历史发布说明 为骨架,系统梳理 PMD 7.x 的版本时间线、7.0.0 的架构级变革、Java 语言版本支持策略、规则体系演进、Kotlin 类型感知分析、CPD 能力扩展以及安全与发布工程实践,帮助读者快速建立对 PMD 7 全貌的认知,并为升级、选型与自定义规则开发提供依据。

PMD 7 新 CLI 演示动画

一、PMD 7.x 版本时间线总览

7.x 系列采用固定节奏的 minor release 模式(通常每 27~35 天一个版本),每个版本以「新特性(New and noteworthy)→ 规则变更 → 修复 → API 变更 → 合并的 PR → 依赖升级 → 统计」的标准结构发布。从发布说明统计看,各版本发布节奏稳定,例如 7.0.0 距上一大版本(6.55.0)相隔 390 天,而此后的小版本间隔大多在一个月以内。

版本发布日期核心主题
7.0.02024-03-22大版本重构:Java 21/22、Kotlin/Swift、Apex 新解析器、CPD 新语言、统一 CLI、XPath 3.1
7.1.02024-04-26更稳健的 CPD 报告;UnnecessaryVarargsArrayCreation等新规则
7.2.02024-05-31集合以 XPath 序列属性形式暴露
7.3.02024-06-28移除 pmd-compat6;CPD XML 报告 schema 化;新增退出码 5
7.4.02024-07-26AvoidNonRestrictiveQueries(Apex 性能)
7.5.02024-08-30Java 23 支持;AvoidSynchronizedStatement
7.6.02024-09-27Git 默认分支切换为 main
7.7.02024-10-25C++ CPD 支持忽略字面量与标识符;JUnit/switch 规则批量重命名
7.8.02024-11-29QueueableWithoutFinalizer(Apex)
7.9.02024-12-27CPD 支持 Rust
7.10.02025-01-31Java 24 支持;ExhaustiveSwitchHasDefault;更换 GPG 签名密钥
7.11.02025-02-28AvoidStatefulDatabaseResult;发布二进制签名
7.12.02025-03-28ImplicitFunctionalInterface
7.13.02025-04-25官方 Docker 镜像;语言方言(Dialect)实验性支持
7.14.02025-05-30CLI 默认多线程(-t 1C);UnnecessaryWarningSuppression
7.15.02025-06-27AvoidBooleanMethodParameters(Apex)
7.16.02025-07-25Java 25 支持;CPD 支持 CSS;ReplaceJavaUtilCalendar/Date
7.17.02025-09-12命名规范、ModifierOrder、CollectionTypeMismatch等 9 个 Java 新规则;CPD Markdown 报告
7.18.02025-10-31构建要求提升至 Java 17;IdenticalConditionalBranches等新规则
7.19.02025-11-28EnumComparison、AvoidFutureAnnotation;Apex/PLSQLNcssCount合并
7.20.02025-12-30OnlyOneReturn新增ignoredMethodNames
7.21.02026-01-30Java 26 支持;构建要求提升至 Java 21;枚举属性值统一为小驼峰
7.22.02026-02-27修复 VBHTML/YAHTML 报告存储型 XSS;UnnecessaryInterfaceDeclaration
7.23.02026-03-27修复类版本
7.24.02026-04-24AvoidInterfaceAsMapKey、OverridingThreadRun
7.25.02026-05-29ANTLR 升级至 4.13.2;违规报告位置精确化(单行警告)
7.26.02026-06-29Swift 语法错误按处理错误上报;WrongTestAnnotation、AssertEqualsArgumentOrder
7.27.02026-08-28Java 27 支持;Apex 67.0;Kotlin 类型感知分析(auxClasspath)
7.28.02026-09-25Kotlin XPath 函数与类型属性;OnDemandImport、InternalApiUsage等 6 个新规则

二、7.0.0:一次架构级的全面重构

7.0.0 是自 PMD 6 之后近 390 天的首个大版本,官方明确声明「它不是 PMD 6.55.0 的直接替代品」,并配套发布了 迁移指南。其变革可以归纳为五个层面。

2.1 Java 模块彻底重写

  • 语法更贴近 JLS:Java 语法被大幅重构,与 Java 语言规范(JLS)的一致性显著提升,所有内置规则都针对新 AST 做了适配;
  • 类型解析与符号表重写:类型解析框架与符号表按 JLS 重新实现,AST 暴露了更多语义信息(方法调用、字段访问);
  • 报告位置收窄:此前方法或类级别的违规会报告整个方法/类的行区间,7.0.0 起只报告方法名或类名标识符所在行,这一行为由各节点对Node#getReportLocation()的重写控制,并影响CognitiveComplexity等多个规则。

2.2 语言版图扩张

  • Java 21/22:标准特性支持 JEP 456(Unnamed Variables & Patterns)、JEP 440(Record Patterns)、JEP 441(Pattern Matching for switch);预览特性通过PMD_JAVA_OPTS=--enable-preview配合--use-version java-22-preview启用;
  • Kotlin(稳定):支持 Kotlin 1.8 语法,首批内置 2 条规则(FunctionNameTooShort、OverrideBothEqualsAndHashcode),在 pmd-kotlin 模块中实现;
  • Swift(新增):有限支持 Swift 5.9(宏展开),首批 4 条内置规则(ForceCast、ForceTry、ProhibitedInterfaceBuilder、UnavailableFunction);
  • Apex 换芯:将闭源的 Jorje 解析器替换为完全开源的 apex-parser(ANTLR 语法)+ Google Summit-AST(ANTLR 解析树转 AST)组合,可解析 User Mode Database Operations 与??空值合并运算符,Apex 支持推进到 60.0(Spring '24);
  • CPD 新增语言:Coco、Julia、TypeScript、Apache Velocity(VTL),并改进 C++(--ignore-sequences)、Groovy(支持 Groovy 3/4 与CPD-ON/CPD-OFF抑制)与 JavaScript(ES6、注释保留)。

2.3 统一 CLI

7.0.0 将原来分散的工具整合为单一脚本pmd(Windows 下pmd.bat),通过子命令区分功能:

pmd check # 运行 PMD 规则分析项目 pmd cpd # 运行 CPD(复制粘贴检测器) pmd designer # 运行 PMD Rule Designer

同时为pmd check增加了进度条与 shell 补全支持。完整的参数说明可参考 CLI 参考文档。

2.4 XPath 3.1 与规则编写体系

  • XPath 规则引擎从 XPath 1.0 升级到 3.1(基于 Saxon,移除 Jaxen),所有规则的violationSuppressXPath属性默认按 XPath 3.1 求值;
  • 配套提供了 Node Stream API、Metrics 框架、测试框架、语言生命周期(Language Lifecycle)与语言属性(Language Properties)等新能力。

2.5 API 清理与兼容层

  • 旧的属性类(IntProperty、StringProperty等)被移除,统一改用PropertyFactory;多值属性分隔符从|改为逗号(,,可用反斜杠转义);数值属性的min/max变为可选;
  • 提供新的程序化 CPD 入口 CpdAnalysis(对应 pmd-core 中的net.sourceforge.pmd.cpd包);
  • 为 maven-pmd-plugin 提供pmd-compat6兼容模块(后续在 7.3.0 中正式移除);
  • 大量历史废弃规则与规则集(rulesets/java/basic.xml等 PMD 5 时代遗留)被清理。

三、Java 语言版本支持:21 → 27 的演进路线

PMD 7 对 Java 的支持采用「标准特性 + 预览特性」双轨机制:标准特性直接由对应语言版本(如java-21)解析,预览特性则需要两步操作:设置环境变量PMD_JAVA_OPTS=--enable-preview并选择NN-preview版本。

export PMD_JAVA_OPTS=--enable-preview pmd check --use-version java-25-preview ...

各版本演进要点:

  • 7.0.0(Java 21/22):Record Patterns、Pattern Matching for switch、Unnamed Variables & Patterns 正式支持;
  • 7.5.0(Java 23):四个预览特性(JEP 455/476/477/482);注意 String Templates 预览特性自 Java 23 起不再存在;
  • 7.10.0(Java 24):四个预览特性(JEP 488/492/494/495);同年 7.10.0 移除了为 String Templates 引入的实验性 AST 节点(ASTTemplate等);
  • 7.16.0(Java 25):JEP 511/512/513 三个新标准特性 + JEP 507 预览;ASTImportDeclaration#isModuleImport、ASTImplicitClassDeclaration等 API 转正为稳定;
  • 7.21.0(Java 26):JEP 530 预览;同版本构建要求提升到 Java 21(PMD 运行时仍保持 Java 8 兼容);
  • 7.27.0(Java 27):JEP 532 预览,java-27-preview版本可选。

每个新大版本都会移除更早的 preview 版本(例如 7.16.0 移除java-23-preview,7.21.0 移除java-24-preview,7.27.0 移除java-25-preview),使用方需跟随升级。

四、规则体系的持续演进

4.1 新规则:按语言与类别持续扩充

7.x 每个 minor release 几乎都会带来新规则,主要集中在 Java,其次是 Apex、Kotlin、Swift、PL/SQL 与 XML。按时间归纳的亮点规则包括:

  • Best Practices:UnnecessaryVarargsArrayCreation(7.1)、UseEnumCollections(7.3,报告以枚举为键的HashMap/HashSet,建议改用枚举专用集合)、UnusedLocalVariable大幅增强、ExhaustiveSwitchHasDefault(7.10)、ImplicitFunctionalInterface(7.12)、RelianceOnDefaultCharset/VariableCanBeInlined/CollectionTypeMismatch(7.17)、LabeledStatement/UnusedLabel(7.18)、EnumComparison(7.19)、OnDemandImport/TypeNameMismatch(7.28);
  • Codestyle:UseExplicitTypes(7.0,报告var用法)、UnnecessaryBoxing(7.0)、LambdaCanBeMethodReference(7.1)、ModifierOrder/TypeParameterNamingConventions(7.17,后者取代GenericsNaming)、UnnecessaryBlock(7.25);
  • Error Prone:ConfusingArgumentToVarargsMethod(7.1)、UselessPureMethodCall(7.17)、IdenticalConditionalBranches(7.18)、UnsupportedJdkApiUsage(7.21,覆盖sun.*与sun.misc.Unsafe等非便携 API,取代DontImportSun)、WrongTestAnnotation/AssertEqualsArgumentOrder(7.26)、UnusedReturnValue(7.27)、LongLiteralEndingWithLowercaseL/InternalApiUsage(7.28);
  • Design:ProtectedMemberInFinalClass(7.27,取代AvoidProtectedFieldInFinalClass与AvoidProtectedMethodInFinalClassNotExtending)、PublicMemberInNonPublicType(7.21);
  • Apex:AvoidNonRestrictiveQueries(7.4)、AvoidStatefulDatabaseResult(7.11)、TypeShadowsBuiltInNamespace(7.13)、AvoidFutureAnnotation(7.19)、InvocableClassNoArgConstructor(7.26)、ApexUnitTestClassShouldHaveRunRelevantTestsAnnotation(7.28,针对 SalesforceRunRelevantTests部署场景,标注为 Beta、要求 API 66.0+)。

4.2 规则重命名:更准确的命名与旧名兼容

7.x 进行了两轮大规模规则重命名,旧名仍然可用但被标记为 deprecated:

  • 7.7.0:一批以 JUnit 命名的规则改为UnitTest*前缀以反映其同时适用于 JUnit 5/TestNG 的真实范围(如JUnitTestsShouldIncludeAssert→UnitTestShouldIncludeAssert);一批 switch 相关规则改为同时覆盖语句与表达式(如SwitchStmtsShouldHaveDefault→NonExhaustiveSwitch、DefaultLabelNotLastInSwitchStmt→DefaultLabelNotLastInSwitch、TooFewBranchesForASwitchStatement→TooFewBranchesForSwitch);
  • 7.17.0:GenericsNaming→TypeParameterNamingConventions、UnnecessaryLocalBeforeReturn→VariableCanBeInlined、AvoidLosingExceptionInformation/UselessOperationOnImmutable→UselessPureMethodCall;
  • 7.27.0:UseUtilityClass→InstantiableUtilityClass。

4.3 关键规则属性的调整示例

  • NonThreadSafeSingleton(7.28):checkNonStaticMethods属性被废弃且不再生效,规则现在同时报告静态与非静态方法(此前默认只报告静态方法),可能导致违规增多。若需恢复抑制非静态方法,可配置 XPath 抑制属性:
<property name="violationSuppressXPath" value=".[ancestor-or-self::MethodDeclaration[1][@Static = false()]]" />
  • VariableCanBeInlined(7.28):statementOrderMatters属性被废弃,计划在 PMD 8.0.0 移除;
  • AvoidCatchingGenericException(7.18):新增typesThatShouldNotBeCaught属性,并整体从 Design 类别迁移至 Error Prone 类别,同时取代并废弃AvoidCatchingNPE与AvoidCatchingThrowable。从「Design」类别批量引入规则的自定义规则集需要显式补充引用:
<rule ref="category/java/errorprone.xml/AvoidCatchingGenericException" />
  • OnlyOneReturn(7.20/7.25):新增ignoredMethodNames(默认compareTo、equals)与allowGuardIfs属性;
  • 枚举属性值统一(7.21):AvoidUsingHardCodedIP的checkAddressTypes、ConfusingTernary的nullCheckBranch、ModifierOrder的typeAnnotations、CommentRequired的各属性值全部改为小驼峰形式(如ipv4、any、onType、required),旧值仍可用但会触发废弃警告。

4.4 违规报告位置的精确化(单行警告)

从 7.25.0 起,PMD 持续收敛违规报告位置,目标是从「整类/整块」缩小到「仅相关标识符行」。7.25.0 一次更新了 34 个 Java 规则(包括CyclomaticComplexity、TooManyFields、TooManyMethods、ExcessiveImports、ExcessivePublicCount等),例如CouplingBetweenObjects只报告类标识符、ExhaustiveSwitchHasDefault只报告 switch 关键字、TooManyStaticImports只报告第一个静态导入。这会影响 CI 脚本中的行号断言,升级时需注意。

五、Kotlin:从实验语言到类型感知分析

Kotlin 在 7.0.0 以实验特性引入、随即转正,此后一路获得重点投入:7.25.0 为 Kotlin 引入实验性的 AttributeView 自定义属性机制与PARSE_TIMEOUT_SECONDS语言属性;7.26.0 新增LocalVariableShadowsParameter规则;7.27.0 为 Kotlin 加入基于auxClasspath语言属性的类型感知分析(type-aware analysis);7.28.0 将类型信息接入 XPath 规则层。

5.1 类型属性(7.28,依赖类型解析)

以下属性暴露在声明节点(property、function、class、parameter、catch、for-loop、委托说明符、注解节点)上,仅在配置auxClasspath且 kotlin-type-mapper 完成类型解析后才可用:

  • @TypeName、@ReturnTypeName、@AnnotationFqNames(注解全限定名)

底层实现位于 KotlinNodeTypeData 及配套的 KotlinTypeName 与 InternalApiBridge,并有 KotlinAuxClasspathIntegrationTest 等测试覆盖。7.28.0 将getTypeName/getReturnTypeName重命名为getType/getReturnType,返回类型从String改为KotlinTypeName(实验性 API 的破坏性变更)。

5.2 通用属性(7.28,不依赖类型解析)

@Mutable、@Identifier、@Name暴露在声明与 import 相关节点上,无论是否配置auxClasspath都始终可用。

5.3 XPath 函数(7.28)

pmd-kotlin 命名空间下新增 7 个 XPath 函数:

函数语义
pmd-kotlin:typeIs(typeName)节点类型为typeName或其子类型时匹配
pmd-kotlin:typeIsExactly(typeName)仅精确匹配声明的类型(不含子类型)
pmd-kotlin:hasAnnotation(name)节点含指定简单名或全限定名注解时匹配
pmd-kotlin:modifiers()以序列返回声明的修饰符关键字
pmd-kotlin:isNullable()声明类型可空(带?)时返回true
pmd-kotlin:hasUnresolvedReference()节点含未解析引用时返回true
pmd-kotlin:matchesSig(signature)按方法签名模式(支持通配符)匹配调用点

同时新增的 AST 属性视图类(如KtPropertyDeclarationAttributes、KtFunctionValueParameterAttributes、KtCatchBlockAttributes等)均在net.sourceforge.pmd.lang.kotlin.ast包中,Java 规则可通过KotlinInnerNode#attributes访问,并自动暴露给 XPath。

六、CPD(复制粘贴检测)的持续增强

CPD 在 7.x 中同样持续进化:

  • 新语言支持:TypeScript、Julia、Coco、VTL(7.0)、Rust(7.9)、CSS(7.16,随pmd-css模块发布);
  • 报告格式:7.3.0 起 CPD 的 XML 报告基于 XSD schema(cpd-report_1_0_0.xsd),根元素pmd-cpd增加pmdVersion、timestamp、version属性,并将可恢复错误作为<error>元素写入;旧格式可通过 rendererxmlold使用(已废弃);7.17.0 新增 Markdown 报告格式,逐条输出重复代码块,详见 CPD 报告格式文档;
  • 命令行选项:C++ 支持--ignore-literal与--ignore-identifiers(7.7),--ignore-sequences(7.0);PMD 与 CPD 从 7.14.0 起共享文件收集参数(如--exclude-file-list、--report-file等);
  • 匹配质量:7.1.0 修复了重叠/部分重叠重复报告的缺陷,现在只报告最长且不重叠的重复;
  • 错误处理:7.3.0 引入退出码 5 表示发生可恢复错误(解析/词法/规则异常),并新增--no-fail-on-error参数恢复旧行为,--skip-lexical-errors相应废弃。

七、工程、安全与分发实践

  • Docker 镜像(7.13):官方镜像支持容器内直接分析,例如docker run --rm --tty -v $PWD:/src pmdcode/pmd:latest check -d . -R rulesets/java/quickstart.xml;
  • 签名发布(7.10/7.11):因旧 GPG 密钥口令泄露(CVE-2025-23215),7.10.0 起改用新密钥A0B5CA1A4E086838签名 Maven Central 制品;7.11.0 起二进制发行包也提供签名,验证方法见 签名发布文档;
  • 安全修复(7.22):修复 VBHTMLRenderer 与 YAHTMLRenderer 因未转义违规消息导致的存储型 XSS(默认html格式不受影响,但抑制标记存在类似问题);
  • 构建要求:7.18.0 起构建需要 Java 17,7.21.0 起需要 Java 21,但产物始终兼容 Java 8 运行时;
  • 内部现代化:ANTLR 从 4.9.3 升级到 4.13.2(7.25,ANTRL 语言模块需重新生成词法/语法分析器)、日志体系改用 slf4j、测试迁移到 JUnit 5、默认分支改为main(7.6)。

八、升级到 PMD 7 的注意事项

综合各版本发布说明,从 6.x 升级到 7.x(以及 7.x 内部跨版本升级)需要重点关注:

  1. 规则集路径与规则名:category/vf/*→category/visualforce/*、category/vm/*→category/velocity/*;被移除/重命名的规则需按 迁移指南 逐一核对;
  2. 属性框架:多值属性分隔符改为逗号;统计类规则的topscore/sigma属性被移除,minimum类型改为整数;Java 规则的方法/类违规位置收窄到标识符;
  3. XPath 版本:violationSuppressXPath及 XPath 规则默认使用 3.1,从 6.x 升级需重新校验表达式;
  4. CLI/退出码:统一为pmd check/cpd/designer子命令,注意 7.3.0 起的退出码 5 语义与--no-fail-on-error;
  5. Java preview 版本:跟随每个大版本迁移NN-preview参数,旧 preview 版本会被移除;
  6. 实验性 API:7.x 存在大量 Experimental API(如 Kotlin 属性视图、语言方言),升级时需关注 API 变更说明 与 japicmp 检查结果。

总结

PMD 7.x 用两年多时间完成了一次「从内核到体验」的全面现代化:Java 模块按 JLS 重写、Kotlin/Swift/CSS/Rust 等语言持续加入、CPD 报告与 CLI 走向统一规范、规则体系在命名、位置与准确性上不断收敛、供应链安全与发布工程逐步完善。对于正在使用或评估 PMD 的团队,本文梳理的版本演进脉络既是升级路线的参照,也是理解 PMD 7 设计取舍(如类型感知分析、单行警告、XPath 3.1)的入口。

  • 静态分析
  • 代码质量

【免费下载链接】pmd

An extensible multilanguage static code analyzer.

项目地址:https://gitcode.com/gh_mirrors/pm/pmd
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询