Skip to content

Baseline matching should not require the user to pick a strategy (line numbers vs. not) #662

Description

@fain182

Context

Today the user has to choose how baseline violations are matched against the current run, via the --ignore-baseline-linenumbers / -i flag (and the corresponding ignoreBaselineLinenumbers() in the config file). This drives two separate matching code paths in Violations::remove() and Violations::countUnmatchedIn():

  • with line numbers (default): a violation matches a baseline entry only if FQCN, line number, file path and the (stable part of the) error message match. Any change above the offending line shifts the line number and the check starts failing on an already-known violation.
  • without line numbers (-i): line numbers are dropped from the match, so unrelated edits don't reopen a baselined violation — but two violations of the same kind in the same class become indistinguishable.

Problem

The matching mechanism is an implementation detail, and it doesn't make sense that the user has to understand and choose it. It's not a decision about what to enforce (which is the user's job), it's a decision about how the baseline is compared (which is ours). The current situation:

  • forces users to learn the trade-off between the two modes;
  • makes baselines behave differently across projects/CI depending on a flag;
  • the default (line-number-sensitive) produces false failures on unrelated edits, which is a common source of confusion.

Proposal

There should be a single matching strategy that works well for everyone, with no user-facing knob. The line-number sensitivity in particular should not be something the user opts into.

Approaches to evaluate:

  • Hash of the line content instead of the line number. Anchoring a baseline entry to a hash of the offending line's source (optionally normalized for whitespace) makes matching stable against edits elsewhere in the file, while still distinguishing multiple violations of the same kind in the same class — which is exactly what the two current modes each fail at.
  • Fuzzy line matching (nearest line with the same content) as a lighter-weight alternative.
  • Keep FQCN + stable error key as the primary identity and use the line only as a tie-breaker.

Backwards compatibility

  • --ignore-baseline-linenumbers / ignoreBaselineLinenumbers() would be deprecated (kept as a no-op with a notice, then removed in a future major).
  • Existing baseline files may need a one-time regeneration; generate-baseline should produce the new format.

Related

Notes

Relevant code: src/Rules/Violations.php (remove(), countUnmatchedIn(), compareViolations(), extractViolationKey()), src/CLI/Baseline.php, and the option wiring in src/CLI/Command/CommonOptions.php.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions