@codacy/tools-pmd-7

中文文档
0.28.0发布于 2026/11/09MITTypeScriptCommonJS近 30 天下载 1.2万

PMD 7 adapter — CLI-mode multi-language static analyzer

原始使用文档
文档目录6 节
  1. Table of Contents
  2. Overview
  3. Updating patterns
  4. Updating the PMD version
  5. Development
  6. Notes for maintainers

@codacy/tools-pmd-7

Table of Contents


Overview

Multi-language static analysis tool using the PMD CLI. Uses the CLI execution strategy -- spawns the PMD shell script via spawnTool() and parses its JSON output.

PropertyValue
Tool IDPMD7
Codacy UUIDed7e8287-707d-485a-a0cb-e211004432c2
StrategyCLI
LanguagesJava, Javascript, Kotlin, Swift, PLSQL, XML, Apex, Velocity, VisualForce, JSP
Binarypmd (shell script from PMD distribution zip)
File patterns**/*.java, **/*.js, **/*.jsx, **/*.kt, **/*.kts, **/*.swift, **/*.sql, **/*.pls, **/*.plb, **/*.pkb, **/*.pks, **/*.xml, **/*.pom, **/*.wsdl, **/*.xsl, **/*.cls, **/*.trigger, **/*.vm, **/*.page, **/*.component, **/*.jsp

Updating patterns

# Re-fetch pattern metadata from the Codacy API
pnpm prefetch

# Commit the result
git add src/patterns.json

Pattern IDs follow the format PMD7_category_{lang}_{categoryDir}_{RuleName}, e.g. PMD7_category_java_errorprone_EmptyCatchBlock.

Updating the PMD version

  1. Update PMD_VERSION in src/adapter.ts
  2. Update PMD_DOWNLOAD_URL and PMD_EXTRACTED_DIR constants accordingly
  3. Run pnpm prefetch to check for new/removed rules
  4. Run pnpm test to verify compatibility
  5. If the major version changes, create a new adapter package (pmd-8/)

Development

pnpm build    # Build with tsup
pnpm test     # Run tests (requires Java + PMD in PATH or installed)

To install PMD locally for testing, download from https://github.com/pmd/pmd/releases and add bin/ to your PATH. Java 8+ is required.

Notes for maintainers

  • Preset mappings (src/pattern-mappings.json): same shape as PMD 6, with one upstream difference that matters. PMD 7 renamed the JUnit* best-practice rules to UnitTest* to make them test-framework-agnostic, so those are claimed by junit, junit-5 and testng, while the rules that are still JUnit-version-specific go to one key each. jakarta-ee covers the EJB rules, and the two Apache Commons rules use their own tags (lib:apache-commons-logging, lib:apache-commons-fileupload). That rename is exactly the drift packages/runner/test/mapping-drift.test.ts exists to catch — a prefix copied from PMD 6 would match nothing here and fail silently.

    The test-framework keys gate on lib:junit / lib:junit-5 / lib:testng tags, not on prefixes, and that is deliberate: PMD renames this family more often than any other, so a prefix list is a standing drift liability. It has already happened twice. The first time was the JUnit* → UnitTest* rename above. The second was JUnit5TestShouldBePackagePrivate → JUnitJupiterTestShouldBePackagePrivate, which silently killed the PMD7_category_java_bestpractices_JUnit5 prefix and with it the whole junit-5 gate for that rule. The tags name the framework rather than the rule, so they survive both renames. Prefixes are still right for jakarta-ee, whose EJB rules carry no tag.

    Detection had to learn spring-boot-starter-test (which pulls JUnit 5 transitively and is the only test declaration most Spring projects have), the junit-jupiter-/junit-platform- per-role artifacts, and Gradle's testRuntimeOnly verb — without those, gating these default-on rules would have lost them for every Spring Boot repo.

  • PMD requires Java 8+ as a runtime. The adapter uses ensureJre() from @codacy/tooling to download Adoptium Temurin JDK 21 if no suitable Java is found on the system.

  • The PMD distribution is downloaded as a zip from GitHub releases and extracted to toolInstallDir/pmd-bin-{version}/.

  • The JAVA_HOME environment variable is set when invoking PMD if using a non-system Java binary.

  • PMD's JSON output format provides beginline/begincolumn/endline/endcolumn, all 1-based. No offset conversion needed.

  • PMD priority (1-5, 1=highest) maps to numeric confidence: 1-2 -> 3 (high), 3 -> 2 (medium), 4-5 -> 1 (low).

  • Pattern ID to rule reference mapping: PMD7_category_java_errorprone_EmptyCatchBlock -> category/java/errorprone.xml/EmptyCatchBlock.

  • Config file detection supports ruleset.xml and apex-ruleset.xml in the repository root.

  • When patterns are specified, a generated ruleset XML is written to the generated config dir and passed via -R.

  • When no patterns or local config is specified, PMD runs with the built-in rulesets/java/quickstart.xml.

  • The --no-fail-on-violation flag ensures PMD exits 0 even when violations are found.

  • The --file-list option is used to pass target files via a temp file rather than command-line arguments, avoiding argument length limits.

  • Velocity forces main-thread execution. PMD defaults to one thread per core, but its Velocity module (pmd-velocity / VtlParser) shares Apache Velocity runtime state between parses, so two .vm files analyzed concurrently corrupt each other's ASTs. The common outcome is a quietly wrong report — violations mis-attributed to other files, phantom file entries, IndexOutOfBoundsException per file, most findings dropped (measured: 0/0/6 violations across three multi-threaded runs of 12 .vm files, against a stable 84 single-threaded). Sometimes it also hangs: reporting on a corrupted node throws AssertionError: Root of the tree should implement RootNode, an Error that RuleApplicator does not recover from, which kills main inside MultiThreadProcessor.close(). close() does shut its own pool down — the leak is that PMD builds one pool per language and the enclosing code never closes the others, so their non-daemon PmdThread workers stay parked and block DestroyJavaVM forever while a complete report sits unread on stdout.

  • The flag is --threads 0, not 1. Only zero selects PMD's MonoThreadProcessor and creates no worker pool at all (its log line becomes Using main thread for analysis). --threads 1 still spawns one non-daemon worker — enough to avoid the Velocity corruption, but the hang stays reachable via any other rule that throws an Error. Both emit byte-identical reports, so zero is free. requiresSingleThread() adds it whenever a routed file's extension is in THREAD_UNSAFE_EXTENSIONS (today just .vm); repos without Velocity keep multi-threaded PMD, and PMD 6 does not have this bug. Upstream context is in docs/tech-debt.md.

  • The extension check must match the runner's router. requiresSingleThread() deliberately does not use path.extname, which returns "" for a file whose basename is exactly .vm — the runner would still route that file to PMD as Velocity, so the guard has to see it too.

  • The runner's per-tool timeout is only an AbortSignal (plus a ~2s hard-reject grace); ctx.signal is passed to spawnTool so a hung PMD is actually killed rather than left behind as an orphan JVM. Because analyze() resolves rather than rejects, an abort is reported here as kind: "Timeout" — the runner's own classification only fires when the adapter rejects.

  • Processing errors (unparseable files) are mapped to AnalysisError with level "warning".

  • Configuration errors (invalid rules) are mapped to AnalysisError with level "warning".

版本与发布记录

@codacy/tools-pmd-7 共发布 36 个版本,首次发布于 2026/03/24;过去 12 个月发布了 36 个版本。

版本发布日期距今
0.28.0latest2026/11/09今天
0.27.12026/11/054 天前
0.27.02026/11/036 天前
0.26.02026/10/3010 天前
0.25.02026/10/1921 天前
0.24.02026/09/251 个月前

关于 @codacy/tools-pmd-7 的常见问题

@codacy/tools-pmd-7 是什么?

PMD 7 adapter — CLI-mode multi-language static analyzer

如何安装 @codacy/tools-pmd-7?

在项目目录运行 npm install @codacy/tools-pmd-7,或使用 pnpm add / yarn add / bun add。

@codacy/tools-pmd-7 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@codacy/tools-pmd-7 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@codacy/tools-pmd-7 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@codacy/tools-pmd-7 可以商用吗?

@codacy/tools-pmd-7 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@codacy/tools-pmd-7 的下载量有多少?

根据 npm 官方下载统计,@codacy/tools-pmd-7 在 2026/10/10 – 2026/11/08 这 30 天内被下载 11,736 次,日均约 391 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@codacy/tools-pmd-7 还在维护吗?

最新版本 0.28.0 发布于 2026/11/09(今天);至今共发布 36 个版本,其中过去 12 个月发布了 36 个;首次发布于 2026/03/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。