静态分析代码质量【免费下载链接】pmdAn extensible multilanguage static code analyzer.项目地址https://gitcode.com/gh_mirrors/pm/pmd点击查看免费下载本文围绕 PMD 官方架构决策记录ADR 2 - Policy on the use of Kotlin for development位于 docs/pages/pmd/projectdocs/decisions/adr-2.md展开系统解读 PMD 团队在引入 Kotlin 时制定的边界与规则并结合当前仓库中的源码、Maven 配置与测试代码验证这些决策的实际落地情况。读完本文你将理解PMD 为什么对 Kotlin开放但设限、六条具体决策规则各自的动机、pmd-core保持纯 Java 的兼容性含义以及语言模块在混合语言与纯 Kotlin 两种路径之间如何取舍。背景PMD 用 ADR 记录架构决策PMD 是一个有着二十多年历史的多语言静态代码分析工具详见 README.md长期以来大量架构决策仅存在于开发者脑中。为此项目引入了架构决策记录Architecture Decision RecordsADR机制——即 ADR 1所有重大决策以统一模板Context / Decision / Status / Consequences写入仓库随文档站点发布并通过 Pull Request 讨论、将状态从 Proposed 提升到 Accepted。所有已接受的 ADR 会汇总在 docs/pages/pmd/projectdocs/decisions.md 的索引页中。ADR 2 正是在这一机制下于 2022 年 7 月提出、同年 9 月被接受见其 Change History 章节它专门回答一个问题Kotlin 应该在 PMD 代码库中用到什么程度Context为什么此前对 Kotlin 保持谨慎ADR 2 的 Context 部分记录了决策时的三个现实约束现状是仅测试用 Kotlin当时 Kotlin 只出现在部分单元测试中例如pmd-lang-test模块提供了一批基于 Kotlin 的测试基类这点在 pmd-lang-test/pom.xml 的模块描述 This module uses Kotlin 中可得到印证。JetBrains IntelliJ IDEA 之外的开发支持不足Eclipse 的 Kotlin 插件按用户评价不能正常工作VS Code 虽有 Kotlin 插件但仅具备基础功能而 gitpod.io、GitHub Codespaces 等在线 IDE 大多基于 VS Code。这意味着在 PMD 中引入 Kotlin就等于接受PMD 只能靠 IntelliJ IDEA 开发这是一种事实上的供应商锁定vendor lock-in。多语言混合的维护成本在 Java 之外混入第二种语言会让维护与新人贡献门槛变高。不过文档也坦承PMD 本身就是一个处理数十种语言的工具这个理由的说服力有限。与此同时扩展 Kotlin 使用也有明确收益可以吸引更多贡献者Kotlin 开发者生态庞大也有利于在项目中开发小型 DSL。这些利弊权衡直接塑造了后面的决策内容。Decision六条规则界定 Kotlin 的边界ADR 2 的核心决策是总体上对在 PMD 中增加 Kotlin 的使用持开放态度但为了把扩展限制在可维护范围内制定了六条规则。规则一pmd-core必须保持纯 JavaThe modulepmd-coreshould stay in plain Java.pmd-core是所有语言模块共享的核心 API解析、规则、报告等基础设施。保持纯 Java 的首要目的是保持二进制兼容性——当源码变更时纯 Java 的核心可以最大程度避免兼容性破坏。文档同时解释了当时的背景PMD 目前所有模块是同步发布的所以兼容性压力暂时不大但未来各语言模块变更频率差异大若模块间能保持兼容就没有必要每次都整体发布——届时pmd-core的纯 Java 属性将更有价值。仓库实证在根 pom.xml 中Kotlin 编译插件kotlin-maven-plugin与 Kotlin 标准库依赖只在需要使用 Kotlin 的模块中生效而 pmd-core/pom.xml 的插件与依赖清单里没有任何 Kotlin 相关条目。从当前源码树看pmd-core的src/main与src/test下也确实不存在任何.kt文件——纯 Java并非口号而是被构建配置与源码现状共同维持的硬约束。规则二测试代码可以使用 KotlinFor (unit) testing, Kotlin can be used inpmd-coreand in the language modules.单元测试被明确列为可自由使用 Kotlin 的领域覆盖pmd-core与各语言模块。测试框架层面则给出了现状与目标pmd-test目前还未使用 Kotlin而pmd-lang-test已经使用。仓库实证pmd-lang-test正是 ADR 落地最典型的模块。其 src/main/kotlin 目录下提供了大量 Kotlin 测试基座例如BaseTextComparisonTest.kt把源码文件 dump 结果与基准文件比较的通用测试基类其子类包括CpdTextComparisonTest与BaseTreeDumpTestBaseParsingHelper.kt语言无关的解析器工具基类封装了parse、parseResource、executeRule等测试常用入口BaseTreeDumpTest.ktAST 结构 dump 对比测试基类。此外 pmd-lang-test/pom.xml 以compile作用域引入Kotestkotest-assertions-core-jvm、kotest-property-jvm、kotest-runner-junit5-jvm让这些 Kotlin 测试基类连同断言库一起自动对使用者可用。规则三语言模块可以按需选择实现语言from now on, we allow to have the individual language modules be implemented in different languages when it makes sense.各语言模块获得自主权可以继续用纯 Java像pmd-java现在这样也可以引入 Kotlin。这一条与 ADR 2 开头引入 Kotlin 可以增加贡献、便于开发 DSL的判断直接呼应——对于某些语法树构建、模式匹配密集的模块Kotlin 的表达力能显著降低实现成本。仓库实证pmd-apex模块是存量模块混入 Kotlin的现行案例。其生产代码 ApexTreeBuilder.kt约 830 行位于src/main/java目录下但以.kt为扩展名承担将 Apex 解析器产出转换为 PMD AST 的核心构建逻辑并由 ApexParser.java 以new ApexTreeBuilder(task, ...)直接调用。与此同时pmd-apex/pom.xml 也配置了kotlin-maven-plugin与 Kotlin 标准库依赖。也就是说Java 与 Kotlin 在同一个模块、同一份生产代码中混合协作是 ADR 规则三允许并已经发生的现实。规则四混合语言不得破坏纯 Java 使用方式When mixing languages (e.g. Java Kotlin), we need to care that the modules can still be used with plain Java.这是对下游用户的保护条款。以pmd-java为例它向自定义规则作者提供了符号表symbol table、类型解析type resolution等 API即便模块内部混入 Kotlin也不能强迫用户必须用 Kotlin 才能写自定义规则——至少对已经存在、且用户可能已用 Java 写过规则的语言模块如此。换言之Kotlin 是内部实现选项不是外部使用门槛。规则五全新语言模块允许纯 Kotlin实现It is also possible to write the entire language module in Kotlin only.对于全新的语言模块允许整模块用 Kotlin 实现此时规则四中混合语言的兼容性难题自然消失不存在历史 Java 规则。这条规则为未来以 Kotlin 优先Kotlin-first方式接入新语言留出了空间。仓库实证虽然目前各存量语言模块仍以 Java 为主但 PMD 已经拥有一个名为pmd-kotlin的模块——它负责分析 Kotlin 语言本身基于 ANTLR4 语法 KotlinParser.g4根节点KotlinFile、节点前缀Kt参见 pmd-kotlin/pom.xml说明 PMD 对 Kotlin 生态的重视而用 Kotlin 写新语言模块的通道则留给未来的新语言接入。规则六重构存量模块必须保持兼容否则就是主版本变更When refactoring an existing language module from Java only to introduce Kotlin, care needs to be taken to not make incompatible changes. If compatibility (binary or source) cant be maintained, then that would be a major version change.如果要把一个纯 Java 的存量语言模块重构为引入 Kotlin必须保证不产生不兼容变更一旦二进制或源码兼容性无法维持则该变更只能随主版本号MAJOR升级发布。这条规则与 ADR 3 确立的 API 演进原则Semantic VersioningMAJOR 用于不兼容变更internal/impl包与InternalApi、Experimental注解界定非公开 API形成呼应——Kotlin 引入的兼容性成本最终由版本策略来兜底。构建基础设施根 pom.xml 中的 Kotlin 管线上述规则能否落地取决于构建系统是否配套。根 pom.xml 集中定义了 Kotlin 相关的统一配置配置项值含义kotlin.version2.2.10Kotlin 编译器版本见 pom.xmlkotlin.compiler.apiVersion/languageVersion1.9语言特性 API 与语言版本兼容目标kotlin.compiler.jvmTarget${maven.compiler.test.target}与测试目标 JVM 字节码版本对齐kotest.version5.9.1Kotest 测试框架版本dokka.version2.0.0Kotlin 文档生成插件版本在插件管理段pom.xmlkotlin-maven-plugin通过add-test-source目标把src/test/kotlin注册为测试源码目录再依次执行kotlin-compile同时编译src/main/kotlin与src/main/java和kotlin-test-compile编译src/test/kotlin与src/test/javamaven-compiler-plugin的默认 compile/testCompile 被禁用改由 Java 编译执行点接管从而保证 Kotlin 与 Java 在同一模块中协同编译。pmd-lang-test还通过 dokka-maven-plugin 生成 Kotlin 文档。Consequences收益与代价并存ADR 2 明确承认这一决策是双刃剑收益面更多 Kotlin 开发者可以参与贡献内部开发小型 DSL领域专用语言变得更容易打开了通向更多语言的可能性——文档明确提到未来不限于 Kotlin例如pmd-scala模块使用 Scala 也是合理方向当前仓库确实存在 pmd-scala-modules/pmd-scala-common 模块其部分测试已用 Kotlin 编写如 ScalaParserTests.kt。代价面除 IntelliJ IDEA 之外的 IDE 在阅读 PMD 源码时会遇到困难Eclipse 实际上将无法继续实用维护一个多语言polyglot代码库的复杂度更高。测试侧的大规模实践pmd-java 的 Kotlin 测试生态规则二测试可用 Kotlin在pmd-java中得到了最大规模的实践。该模块在 src/test/kotlin 下积累了上百个 Kotlin 测试文件覆盖 AST 节点测试、符号解析symbols包、类型系统types包含internal/infer下的类型推断测试等领域。其中 KotlinTestingDsl.kt 是一个典型的DSL 开发成果它基于 Kotest 与tree-matchers/tree-printers库com.github.oowekyala.treeutils构建了一套节点匹配 DSL——例如JavaVersion枚举支持J9..J11这种区间运算符、shouldMatchNode让断言以声明式写出并统一约定不变量断言javaImplicitAssertions如isParenthesized必须与parenthesisDepth 0一致。这与 ADR 2 中Kotlin 便于开发小型 DSL的动机完全吻合。需要再次强调边界这些 Kotlin 测试全部位于测试源码树pmd-java的生产代码仍是纯 Java且 pmd-java/pom.xml 只为测试引入kotlin-maven-plugin与kotlin-stdlib、kotlin-test-junit——这正是规则四混合语言不影响用户以纯 Java 使用模块的典型体现。小结ADR 2 的实践价值从 ADR 2 出发结合仓库现状可以提炼出 PMD 的 Kotlin 落地路径核心保持纯 Java 以守护兼容性底线测试代码放开使用 Kotlinpmd-lang-test、pmd-java 测试均以此构建测试 DSL语言模块生产代码按需引入pmd-apex 的 ApexTreeBuilder.kt 已是 Java/Kotlin 混编实例未来新语言模块可走纯 Kotlin 路线任何不兼容变更都必须以主版本升级为代价。这条路径既利用了 Kotlin 的表达力与生态吸引力又通过版本策略与 API 原则ADR 3把兼容性风险控制在明确边界内是大型多语言静态分析项目引入第二语言的参考范本。状态与变更历史状态Accepted已接受最近更新2024 年 2 月对应 7.0.02022-09-30状态由 Proposed 改为 Accepted2022-07-28提出初始版本赞分享静态分析代码质量【免费下载链接】pmdAn extensible multilanguage static code analyzer.项目地址https://gitcode.com/gh_mirrors/pm/pmd点击查看免费下载相关推荐使用 ADR 模板记录架构决策Atlantis 项目的架构决策记录实践指南使用 ADR 模板记录架构决策Atlantis 项目的架构决策记录实践指南 导读 本文围绕 Atlantis 仓库中的 docs/adr/template.mDevOpsCI/CD基础设施Volcano 与 Kubernetes 版本兼容矩阵从 v1.6 到 HEAD 的完整版本适配指南Volcano 与 Kubernetes 版本兼容矩阵从 v1.6 到 HEAD 的完整版本适配指南 Volcano 作为运行在 Kubernetes 之上的5分钟上手万能模组管理器 Reloaded-II一篇文章讲透跨游戏装模组的全流程5分钟上手万能模组管理器 Reloaded II一篇文章讲透跨游戏装模组的全流程 你同时玩着《索尼克英雄》《索尼克滑板》和《血源诅咒》每个游戏都想装高清纹理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考