feat(cargo_heather): allow descriptive trailing comments + safer --fix + diff-style mismatch output#16
feat(cargo_heather): allow descriptive trailing comments + safer --fix + diff-style mismatch output#16
Conversation
…x + diff-style mismatch output Three improvements driven by real-world friction migrating ox-sdk to cargo_heather: 1. Header check is now a prefix-match instead of exact equality. A file passes if the leading comment block STARTS WITH the configured header — additional descriptive comment paragraphs after the header are allowed. This means projects no longer have to choose between shipping a license header and documenting the file at the top. 2. `cargo heather --fix` is now paragraph-aware. When replacing a wrong header it strips only the first comment paragraph (and an optional blank-comment-line separator), preserving any descriptive comment paragraphs that follow. Previously --fix would nuke every leading comment, including human-written documentation. 3. MISMATCH output now shows the expected and actual headers with a diff-style +/- marker, so it is obvious from the log alone what needs to change instead of having to open every flagged file. Adds 17 new unit tests (header_matches direct tests, prefix-match cases for Rust/TOML/script files, paragraph-aware strip + fix tests, and format_mismatch_details tests). All 231 tests pass. Self-check on the ox-tools workspace remains green (51/51 files OK). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #16 +/- ##
=======================================
- Coverage 99.6% 99.4% -0.2%
=======================================
Files 11 14 +3
Lines 1847 2050 +203
=======================================
+ Hits 1840 2039 +199
- Misses 7 11 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR updates cargo_heather’s header checking and fixing behavior to reduce friction when files include descriptive top-of-file comments, and improves mismatch logging by showing expected vs actual headers in a diff-like format.
Changes:
- Switch header validation to a prefix match so files can include descriptive trailing comments after the configured header.
- Make
--fixparagraph-aware to preserve descriptive comment paragraphs after the header. - Enhance mismatch output to print expected/actual headers with
+/-diff-style markers.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/cargo_heather/src/lib.rs | Logs mismatch details and adds a helper to format expected vs actual header output. |
| crates/cargo_heather/src/checker.rs | Implements prefix-based matching and updates --fix to strip only the leading “header paragraph”, preserving trailing descriptive comments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ling Six new edge-case unit tests targeting the mutation-testing misses on the paragraph-aware logic in fix_script_content / strip_existing_header: boundary cases where idx == start, idx == lines.len(), header-only content, and explicit blank-comment-separator / blank-line consume checks. Brings cargo_heather test count to 237. Also adds 'whitespace' to .spelling so the new doc comments pass cargo-spellcheck. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address review feedback on PR #16: the prior paragraph-aware strip stopped at the first blank-comment line, which left paragraphs 2+ of an existing wrong multi-paragraph header in place. Combined with prefix-match validation a file could pass while still containing leftover license text from the old header. Now both fix_script_content and strip_existing_header strip exactly N = expected_header.lines().count() consecutive header-comment lines (blank-comment lines like `//` and `#` count as header-comment lines). After the N-line strip an optional trailing blank-comment paragraph separator and one blank line are still consumed so descriptive trailing comments stay clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CI mutation-testing flagged 8 surviving mutants in fix_script_content and strip_existing_header after the strip-N rewrite. Added 5 targeted tests covering: leading-blank-skip (< vs >, += vs -=/*=), strip-N off-by-one (< vs <=) for both functions, idx==len boundary in optional consumes (< vs <=), and idx==start else-branch reset (> vs >=). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The `while idx < lines.len() && lines[idx].trim().is_empty() { idx += 1; }`
loop in both `fix_script_content` and `strip_existing_header` was vulnerable`nto a cargo-mutants TIMEOUT mutation: replacing `+= 1` with `*= 1` keeps`n`idx` at 0 forever when the first line is blank, hanging the test.`n`nReplaced both loops with`n` let n = lines.iter().take_while(|l| l.trim().is_empty()).count();`n`nwhich uses an immutable counter that cargo-mutants cannot mutate into an`ninfinite loop. Behavior is identical; existing tests cover this path.`n`nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The previous implementation joined per-line trimmed strings with "\n", then called .trim().lines() to strip outer blank lines. This was a pointless round-trip and also subtly wrong: str::trim() strips all leading/trailing whitespace, including the indentation of the first non-blank line, not just blank lines. Replace with a direct approach: trim_end each line, then pop blank lines from the front and back of the Vec. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rip helper Break the 1142-line monolithic checker.rs into a checker/ module with clear separation of concerns: - matcher.rs: line-by-line header prefix matching - extract.rs: pull the first comment block from file content (regular + script frontmatter), deduplicated via collect_comment_block - strip.rs: remove existing headers via shared find_header_end helper; the previously parallel strip_existing_header / fix_script_content now share one algorithm with thin wrappers - mod.rs: public API (check_files, check_file, fix_file, prepend_header, check_content) and dispatch helpers The shared find_header_end uses take_while().count() instead of a mutable += counter, so the mutation-test workaround comments are no longer needed. All 212 lib tests pass; clippy and rustdoc are clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace "frontmatters" with "frontmatter blocks" and "iff" with "if and only if" so the workflow's cargo spellcheck (Hunspell) job passes. No behavior change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three improvements driven by real-world friction migrating ox-sdk to cargo_heather:
Header check is now a prefix-match instead of exact equality. A file passes if the leading comment block STARTS WITH the configured header — additional descriptive comment paragraphs after the header are allowed. This means projects no longer have to choose between shipping a license header and documenting the file at the top.
cargo heather --fixis now paragraph-aware. When replacing a wrong header it strips only the first comment paragraph (and an optional blank-comment-line separator), preserving any descriptive comment paragraphs that follow. Previously --fix would nuke every leading comment, including human-written documentation.MISMATCH output now shows the expected and actual headers with a diff-style +/- marker, so it is obvious from the log alone what needs to change instead of having to open every flagged file.
Adds 17 new unit tests (header_matches direct tests, prefix-match cases for Rust/TOML/script files, paragraph-aware strip + fix tests, and format_mismatch_details tests). All 231 tests pass. Self-check on the ox-tools workspace remains green (51/51 files OK).