Replace sebastian/diff with own strict unified-diff parser - #83
Draft
janedbal wants to merge 1 commit into
Draft
Conversation
The sebastian/diff parser classifies each patch line with regexes.
Its header-skip regex '[+-]{3} [ab]' also matches content lines such
as '+-- alternative ...' (an added SQL comment line). The parser
drops such lines silently. All later line numbers in the hunk then
shift by one. This causes false "patch mismatch" errors, or silently
wrong coverage attribution when the shifted content happens to match.
Upstream does not accept fixes for this class of bugs
(see sebastianbergmann/diff#132).
The new UnifiedDiffParser consumes each hunk body by the line counts
that the '@@' header declares. A content line inside a hunk can never
be mistaken for a header. Any structural inconsistency causes a hard
error instead of a silent skip.
The hand-made test fixtures declared wrong hunk counts and
sebastian/diff never validated them. The strict parser does, so the
fixtures now carry correct counts.
Co-Authored-By: Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
SebastianBergmann\Diff\Parserclassifies each patch line with regexes. Its header-skip regex[+-]{3} [ab]also matches ordinary content lines such as+-- alternative ...(an added SQL comment). The parser drops such lines silently. All later line numbers in the hunk then shift by one.For coverage-guard this has two outcomes:
Patch file ... has added line #N that does not match actual contenterror, orWe hit the first outcome in a real CI run: a patch added a SQL migration with a comment line starting
-- alternative ..., and the check failed on an up-to-date patch. Upstream does not accept fixes for this class of parser bugs (sebastianbergmann/diff#132), so the parser is replaced instead.How
The new
UnifiedDiffParserconsumes each hunk body by the line counts that the@@header declares. While inside a hunk body, the parser never inspects a line for header-likeness, so content lines cannot be misclassified — no matter what text they start with. Any structural inconsistency (counts that do not match the body, an unexpected line, a truncated hunk, a quoted path, a binary patch) causes a hardErrorExceptioninstead of a silent skip.Supported input stays the same:
git diffoutput with the standardb/prefix, plus plaindiff -ustyle---/+++sections. Handled explicitly: new/deleted files, renames, mode-only changes,Binary files ... differ,\ No newline at end of file, zero-context (-U0) hunks, CRLF patches, and empty context lines whose single space was stripped by some tool.sebastian/diffis no longer needed and is removed fromrequire-dev, the dependency-analyser config, and the README optional-dependencies list.Note on fixtures
The hand-made fixtures (
sample.patchand friends) declared hunk counts that did not match their bodies (@@ -10,4 +10,10 @@for a body with 5 old / 9 new lines). sebastian/diff never validated counts, so this went unnoticed. The strict parser validates them, so the fixtures now carry correct counts.Validation
+-- a...case and for diff-of-a-diff content.composer checkpasses.The same fix will be ported to
shipmonk-rnd/copy-paste-detector, which copied thisPatchParser.Co-Authored-By: Claude Code