apache / apache/maven-pmd-plugin

excludeFromFailureFile and maxAllowedViolations gate CPD by aggregate/file-pair, not by duplicate-block identity

Open
#724 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
66
Forks
55
Avg merge
8d 16h
Merged PRs (30d)
7

Description

### Affected version

3.28.1-SNAPSHOT (also present in released versions -- read from source, not yet reproduced live against Maven Central due to a network restriction in the environment I used, see note below)

### Bug description

Note: this is a source-code-only finding (AbstractPmdViolationCheckMojo.executeCheck/getViolations, ExcludeDuplicationsFromFile.isExcludedFromFailure), not yet reproduced against a live build -- repo.maven.apache.org was blocked in the sandbox I was working from. Filing anyway because the mechanism is unambiguous from the source; happy to attach a live repro if useful.

Two separate aggregate/no-identity gaps in how cpd-check consumes CPD's Match list:

Gap 1) pmd.maxAllowedViolations (default 0): the gate is failureCount > maxAllowedViolations, a raw count of duplications, no location. If a team tolerates 1 known duplication and later fixes it while a different, unrelated duplication appears elsewhere, failureCount is still 1 -- build stays green.

Gap 2) pmd.excludeFromFailureFile: isExcludedFromFailure(Match) only collects the SET OF FILE PATHS involved in a match, and excludes the duplication if both paths match a group already listed in the exclusion file -- it never looks at line ranges or block content/hash. Once a file pair (A, B) is in the exclusion list, ANY future duplication between A and B, anywhere in either file, with any content, is excluded forever.

Repro (conceptual, not yet run live): 1) create a real duplication between A.java and B.java, add "A,B" to excludeFromFailureFile (or set maxAllowedViolations=1); 2) mvn pmd:cpd pmd:cpd-check -> green; 3) remove that duplication, introduce a different, unrelated duplication within the same A/B pair (or, for maxAllowedViolations, anywhere in the project) of similar size; 4) run again with the same config -> still green, now masking a completely different duplicate.

Why it matters: this is the standard way most teams gate CPD in CI (via the Maven plugin, not the bare CPD CLI), so the aggregate/file-pair blind spot applies to the common case, not an edge case.

Suggest: for excludeFromFailureFile, match on block identity (line range and/or content hash) instead of just the file-pair; for maxAllowedViolations, consider tracking identity across runs the same way, so a same-size swap surfaces instead of netting to zero.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading AbstractPmdViolationCheckMojo.executeCheck/getViolations and ExcludeDuplicationsFromFile.isExcludedForFailure in the Maven plugin source. Trace how CPD Match objects become failureCount and how exclusion entries are compared, then investigate the conceptual A.java/B.java swap described in the issue. Done should distinguish duplicate-block identity from aggregate counts and file pairs, with behavior checked against the reported scenarios.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
build-system
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.