Skip to content

feat(work-e55f69ed): add # Errors sections to core public APIs#145

Closed
EffortlessSteven wants to merge 6 commits intomainfrom
feat/work-e55f69ed/core-public-apis-missing---errors-sectio
Closed

feat(work-e55f69ed): add # Errors sections to core public APIs#145
EffortlessSteven wants to merge 6 commits intomainfrom
feat/work-e55f69ed/core-public-apis-missing---errors-sectio

Conversation

@EffortlessSteven
Copy link
Copy Markdown
Member

Summary

Added # Errors sections to 4 core public APIs for better error documentation.

Changes

  • Added # Errors section to 4 public API functions

Issue Reference

Fixes #129

Extract the escape_xml function to a shared xml_utils.rs module as
per ADR decision. The function now properly handles illegal XML
control characters (0x00-0x1F except tab/LF/CR) by escaping them as
&#xNN; entities.

Changes:
- Create crates/diffguard-core/src/xml_utils.rs with shared escape_xml
- Update lib.rs to pub mod xml_utils
- Update junit.rs to use super::xml_utils::escape_xml
- Update checkstyle.rs to use super::xml_utils::escape_xml
- Remove duplicate escape_xml functions and tests from junit.rs/checkstyle.rs

Fix: c if c <= '\u{001F}' && c != '\t' && c != '\n' && c != '\r' => {
    out.push_str(&format!(
- check.rs::run_check - documents DiffParseError, PathFilterError, RuleCompileError, OverrideCompileError
- unified.rs::parse_unified_diff - documents DiffParseError
- overrides.rs::RuleOverrideMatcher::compile - documents OverrideCompileError
- rules.rs::compile_rules - documents RuleCompileError variants
Added '# Errors' sections to documentation for core public APIs per
Rust API Guidelines C409:

- parse_unified_diff
- compile_rules
- RuleOverrideMatcher::compile
- run_check
@gemini-code-assist
Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Summary by CodeRabbit

Release Notes

  • Documentation

    • Enhanced API documentation with comprehensive error descriptions for core public functions (parse, compile, and execution).
  • Refactor

    • Consolidated XML handling utilities into a shared module for improved code maintainability and reduced duplication.
  • Tests

    • Added extensive property-based tests for XML escaping functionality.

Walkthrough

PR consolidates duplicated XML escaping logic from two modules into a shared utility, adds comprehensive property-based tests, documents error conditions in four core public APIs per Rust guidelines, and introduces design/specification documents for refactoring parse_blame_porcelain.

Changes

Cohort / File(s) Summary
Documentation: Public API error conditions
CHANGELOG.md, crates/diffguard-core/src/check.rs, crates/diffguard-diff/src/unified.rs, crates/diffguard-domain/src/overrides.rs, crates/diffguard-domain/src/rules.rs
Added # Errors sections to four core public functions documenting failure conditions and error types returned by parse_unified_diff, compile_rules, RuleOverrideMatcher::compile, and run_check. Updated changelog accordingly.
XML utility consolidation
crates/diffguard-core/src/checkstyle.rs, crates/diffguard-core/src/junit.rs, crates/diffguard-core/src/lib.rs, crates/diffguard-core/src/xml_utils.rs
Extracted duplicated escape_xml helper from checkstyle.rs and junit.rs into new shared xml_utils module; both callers now import and use the centralized implementation. Module exposed as public in lib.rs.
Property-based tests
crates/diffguard-core/tests/property_tests_escape_xml.rs
Added comprehensive property and example-based tests (296 lines) validating escape_xml behavior across special characters, control characters, boundary conditions, and Unicode handling using proptest framework.
Design & specification documents
adr-011-parse-blame-porcelain-result.md, specs-011-parse-blame-porcelain-result.md
Introduced ADR and spec documents detailing refactor of parse_blame_porcelain function signature to return bare BTreeMap instead of Result, eliminating unnecessary error wrapper for a never-failing operation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 We hops and we cheers, the docs now shine bright,\
XML utils consolidated, everything tight!\
Properties tested with care, edge cases embraced,\
Error conditions documented—no corner left traced! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes substantial out-of-scope changes beyond issue #129: extraction of escape_xml into xml_utils.rs module, ADR-011 documentation, specs-011 documentation, and related refactoring affecting checkstyle.rs, junit.rs, lib.rs, and new test files. Consider separating the escape_xml refactoring and documentation changes into a distinct PR to keep this focused on issue #129's # Errors documentation objectives.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary focus: adding # Errors sections to core public APIs, which is the main documented objective.
Description check ✅ Passed The description is relevant to the changeset, mentioning the addition of # Errors sections to public APIs and referencing issue #129.
Linked Issues check ✅ Passed The PR adds # Errors sections to all four required public APIs: parse_unified_diff [unified.rs], compile_rules [rules.rs], RuleOverrideMatcher::compile [overrides.rs], and run_check [check.rs], fully addressing issue #129 requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/work-e55f69ed/core-public-apis-missing---errors-sectio

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1fb07bf89

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

/// Additional Property: Original implementation for testing
fn escape_xml(s: &str) -> String {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Test the exported escape_xml instead of a local clone

This integration test file defines its own escape_xml implementation and all properties call that local function, so the new shared production function (diffguard_core::xml_utils::escape_xml) is never exercised here. That means regressions in the real implementation (for example the new control-character branch) can ship while this suite still passes, which weakens the safety net for XML output correctness.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@adr-011-parse-blame-porcelain-result.md`:
- Line 15: Update the ADR text to use the correct Clippy lint name: replace the
incorrect `unnecessary_result_bool` mention with `unnecessary_wraps` so the
document accurately states that the lint detecting private functions that
unnecessarily return Result/Option is `unnecessary_wraps`; ensure the change is
applied to the sentence that currently references `unnecessary_result_bool` (the
one describing Clippy detecting functions whose return values are unnecessarily
wrapped).

In `@crates/diffguard-core/src/xml_utils.rs`:
- Around line 24-26: The match arm that currently encodes control chars (the
branch matching c if c <= '\u{001F}' && c != '\t' && c != '\n' && c != '\r')
must stop emitting numeric character references and instead drop those forbidden
XML 1.0 control characters; update the logic in that branch (the code that
manipulates out using out.push_str(&format!("&#x{:X};", c as u32))) to simply
skip/ignore the character so nothing is appended to out. Keep all other escaping
behavior unchanged.

In `@crates/diffguard-core/tests/property_tests_escape_xml.rs`:
- Around line 45-104: The current property tests (e.g.,
ampersand_only_appears_as_amp_in_output, less_than_only_appears_as_lt_in_output,
greater_than_only_appears_as_gt_in_output,
double_quote_only_appears_as_quot_in_output,
single_quote_only_appears_as_apos_in_output) only assert the presence of escaped
entities; change them to assert full normalization by also asserting that no raw
unescaped characters remain in the output (e.g., assert output does not contain
'<', '>', '"' or '\'' respectively) and for ampersands assert that every '&' in
output is part of a valid entity (limit to &amp;, &lt;, &gt;, &quot;, &apos;)
rather than any stray '&'); implement this by replacing the contains(...)
assertions with checks that the raw character is absent and, for ampersands,
iterating occurrences (or using a simple pattern check) to ensure each '&' is
followed by one of the allowed entity strings.
- Around line 283-296: The tests in property_tests_escape_xml.rs define a local
escape_xml which masks the real implementation; remove the local fn escape_xml
and import the production function with use
diffguard_core::xml_utils::escape_xml; so the property tests call
diffguard_core::xml_utils::escape_xml (or alternatively move these property
tests into src/xml_utils.rs under #[cfg(test)] to exercise the production
function directly).

In `@crates/diffguard-diff/src/unified.rs`:
- Around line 131-134: The doc comment for parse_unified_diff claiming malformed
hunk headers return DiffParseError is inconsistent with the implementation that
swallows hunk-header parse failures; update the implementation so
parse_unified_diff actually propagates header parse errors instead of
continuing. Locate the parse_unified_diff function and where hunk header parsing
currently catches/ignores failures (the block that swallows parse errors) and
change it to return Err(DiffParseError::...) or propagate the parse result with
? so malformed headers produce the DiffParseError the docs promise.

In `@crates/diffguard-domain/src/rules.rs`:
- Around line 92-98: The doc comment for compile_rules omits the
RuleCompileError::UnknownDependency variant; update the comment block above pub
fn compile_rules to list this variant (e.g., add “-
[`RuleCompileError::UnknownDependency`] — a rule refers to a dependency that
does not exist”) so the public error contract includes UnknownDependency
alongside MissingPatterns, InvalidRegex, InvalidGlob, and
InvalidMultilineWindow.

In `@specs-011-parse-blame-porcelain-result.md`:
- Around line 23-27: The spec currently anchors changes to exact line numbers in
crates/diffguard/src/main.rs which will drift; update the document to reference
symbols instead — e.g., refer to the function signature change for
parse_blame_porcelain (fn parse_blame_porcelain(blame_text: &str) ->
BTreeMap<u32, BlameLineMeta>), the return-site change (returning out instead of
Ok(out)), the caller change that removes the .with_context(...)? call (reference
the calling function by name where that removal occurs), and the test change
that removes the .expect("parse") call (reference the test by its test function
name); replace all hardcoded line-number mentions with these symbol-based
references throughout the spec.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b0fbd532-8b5e-4f87-8041-8640be351bd6

📥 Commits

Reviewing files that changed from the base of the PR and between 586450b and f1fb07b.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • adr-011-parse-blame-porcelain-result.md
  • crates/diffguard-core/src/check.rs
  • crates/diffguard-core/src/checkstyle.rs
  • crates/diffguard-core/src/junit.rs
  • crates/diffguard-core/src/lib.rs
  • crates/diffguard-core/src/xml_utils.rs
  • crates/diffguard-core/tests/property_tests_escape_xml.rs
  • crates/diffguard-diff/src/unified.rs
  • crates/diffguard-domain/src/overrides.rs
  • crates/diffguard-domain/src/rules.rs
  • specs-011-parse-blame-porcelain-result.md


Issue #141 reports that `parse_blame_porcelain` in `crates/diffguard/src/main.rs` (line 1768) is typed to return `Result<BTreeMap<u32, BlameLineMeta>>` but never actually returns `Err`. This is dead code — the function silently skips invalid entries via `continue` rather than propagating errors, and always reaches `Ok(out)` at line 1818.

Clippy detects this pattern with the `unnecessary_result_bool` lint (or equivalent): *"this function's return value is unnecessarily wrapped by `Result`"*.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

What is the exact Clippy lint name for functions that unnecessarily return Result (i.e., can never return Err)?

💡 Result:

The exact Clippy lint name is unnecessary_wraps. It detects private functions that only return Ok or Some, meaning they unnecessarily wrap values in Result or Option when no Err or None is ever returned.

Citations:


Update Clippy lint name in ADR.

The ADR references unnecessary_result_bool, which is not a Clippy lint. The correct lint name is unnecessary_wraps—it detects private functions that unnecessarily return Result or Option when they never return Err or None. Update line 15 to use the accurate lint name.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adr-011-parse-blame-porcelain-result.md` at line 15, Update the ADR text to
use the correct Clippy lint name: replace the incorrect
`unnecessary_result_bool` mention with `unnecessary_wraps` so the document
accurately states that the lint detecting private functions that unnecessarily
return Result/Option is `unnecessary_wraps`; ensure the change is applied to the
sentence that currently references `unnecessary_result_bool` (the one describing
Clippy detecting functions whose return values are unnecessarily wrapped).

Comment on lines +24 to +26
c if c <= '\u{001F}' && c != '\t' && c != '\n' && c != '\r' => {
out.push_str(&format!("&#x{:X};", c as u32));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In XML 1.0, are numeric character references like &#x0; or &#x1B; valid for forbidden control characters U+0000-U+001F (except tab, LF, CR)?

💡 Result:

No, in XML 1.0, numeric character references like � (U+0000) or � (U+001B) are not valid for forbidden control characters in the range U+0000-U+001F (except U+0009 tab, U+000A LF, U+000D CR). The XML 1.0 specification defines valid characters in production [2] Char as #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]. This excludes all other control characters in U+0000-U+001F except the three exceptions. Section 4.1 specifies a well-formedness constraint [WFC: Legal Character]: "Characters referred to using character references must match the production for Char." Therefore, references to non-Char codepoints, including � and �, are invalid and must be rejected by conforming processors. U+0000 is always invalid. For the other forbidden controls (e.g., U+001B), they are not legal Chars, so their NCRs are forbidden in XML 1.0. XML 1.1 introduced support for NCRs to these controls (except U+0000), but the question specifies XML 1.0. This is confirmed by multiple sources quoting the spec, including Wikipedia, Stack Overflow discussions citing the XML 1.1 rationale (which explicitly states these are "forbidden in XML 1.0"), and W3C pages on control characters.

Citations:


Numeric character references for forbidden XML 1.0 control characters are invalid and will break XML parsers.

The code at lines 24–25 encodes forbidden control characters (U+0000–U+001F except tab, LF, CR) as numeric character references like &#xNN;. However, in XML 1.0, these numeric references are not valid even though they reference valid Unicode codepoints. Section 4.1 of the XML 1.0 specification requires that "Characters referred to using character references must match the production for Char," which explicitly excludes these control characters. Conforming XML parsers will reject output containing such references.

Replace the encoding with dropping the forbidden characters:

Proposed fix
-            c if c <= '\u{001F}' && c != '\t' && c != '\n' && c != '\r' => {
-                out.push_str(&format!("&#x{:X};", c as u32));
-            }
+            // Forbidden XML 1.0 control characters—drop them
+            '\u{0000}'..='\u{0008}'
+            | '\u{000B}'
+            | '\u{000C}'
+            | '\u{000E}'..='\u{001F}' => {}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
c if c <= '\u{001F}' && c != '\t' && c != '\n' && c != '\r' => {
out.push_str(&format!("&#x{:X};", c as u32));
}
// Forbidden XML 1.0 control characters—drop them
'\u{0000}'..='\u{0008}'
| '\u{000B}'
| '\u{000C}'
| '\u{000E}'..='\u{001F}' => {}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/diffguard-core/src/xml_utils.rs` around lines 24 - 26, The match arm
that currently encodes control chars (the branch matching c if c <= '\u{001F}'
&& c != '\t' && c != '\n' && c != '\r') must stop emitting numeric character
references and instead drop those forbidden XML 1.0 control characters; update
the logic in that branch (the code that manipulates out using
out.push_str(&format!("&#x{:X};", c as u32))) to simply skip/ignore the
character so nothing is appended to out. Keep all other escaping behavior
unchanged.

Comment on lines +45 to +104
fn ampersand_only_appears_as_amp_in_output(input: String) {
let output = escape_xml(&input);
// If input contains &, it should be escaped to &amp;
// So & should never appear unescaped (i.e., not followed by amp;)
if input.contains('&') {
prop_assert!(
output.contains("&amp;"),
"& was not properly escaped to &amp; in output: {:?}",
output
);
}
}

#[test]
fn less_than_only_appears_as_lt_in_output(input: String) {
let output = escape_xml(&input);
if input.contains('<') {
prop_assert!(
output.contains("&lt;"),
"< was not properly escaped to &lt; in output: {:?}",
output
);
}
}

#[test]
fn greater_than_only_appears_as_gt_in_output(input: String) {
let output = escape_xml(&input);
if input.contains('>') {
prop_assert!(
output.contains("&gt;"),
"> was not properly escaped to &gt; in output: {:?}",
output
);
}
}

#[test]
fn double_quote_only_appears_as_quot_in_output(input: String) {
let output = escape_xml(&input);
if input.contains('"') {
prop_assert!(
output.contains("&quot;"),
"\" was not properly escaped to &quot; in output: {:?}",
output
);
}
}

#[test]
fn single_quote_only_appears_as_apos_in_output(input: String) {
let output = escape_xml(&input);
if input.contains('\'') {
prop_assert!(
output.contains("&apos;"),
"' was not properly escaped to &apos; in output: {:?}",
output
);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Strengthen special-char properties to assert full correctness, not just presence.

These checks currently only verify that escaped entities exist, but they don’t guarantee unescaped special characters are absent. Consider asserting full normalization constraints (e.g., no raw <, >, ", ', and & only as valid entities) to avoid false positives.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/diffguard-core/tests/property_tests_escape_xml.rs` around lines 45 -
104, The current property tests (e.g., ampersand_only_appears_as_amp_in_output,
less_than_only_appears_as_lt_in_output,
greater_than_only_appears_as_gt_in_output,
double_quote_only_appears_as_quot_in_output,
single_quote_only_appears_as_apos_in_output) only assert the presence of escaped
entities; change them to assert full normalization by also asserting that no raw
unescaped characters remain in the output (e.g., assert output does not contain
'<', '>', '"' or '\'' respectively) and for ampersands assert that every '&' in
output is part of a valid entity (limit to &amp;, &lt;, &gt;, &quot;, &apos;)
rather than any stray '&'); implement this by replacing the contains(...)
assertions with checks that the raw character is absent and, for ampersands,
iterating occurrences (or using a simple pattern check) to ensure each '&' is
followed by one of the allowed entity strings.

Comment on lines +283 to +296
fn escape_xml(s: &str) -> String {
let mut out = String::with_capacity(s.len());
for c in s.chars() {
match c {
'&' => out.push_str("&amp;"),
'<' => out.push_str("&lt;"),
'>' => out.push_str("&gt;"),
'"' => out.push_str("&quot;"),
'\'' => out.push_str("&apos;"),
_ => out.push(c),
}
}
out
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that integration test defines a local escape_xml and whether production escape_xml is publicly exposed.
rg -n --type=rust '^\s*fn\s+escape_xml\s*\(' crates/diffguard-core/tests/property_tests_escape_xml.rs
rg -n --type=rust '^\s*use\s+.*escape_xml' crates/diffguard-core/tests/property_tests_escape_xml.rs
rg -n --type=rust '^\s*pub(?:\([^)]*\))?\s+fn\s+escape_xml\s*\(' crates/diffguard-core/src/xml_utils.rs crates/diffguard-core/src/lib.rs

Repository: EffortlessMetrics/diffguard

Length of output: 190


🏁 Script executed:

#!/bin/bash
# Check if escape_xml is re-exported from lib.rs and verify module structure
echo "=== Checking lib.rs exports ==="
grep -n "escape_xml" crates/diffguard-core/src/lib.rs

echo -e "\n=== Checking xml_utils.rs module declaration in lib.rs ==="
grep -n "mod xml_utils\|pub.*xml_utils" crates/diffguard-core/src/lib.rs

echo -e "\n=== Checking full test file imports ==="
head -30 crates/diffguard-core/tests/property_tests_escape_xml.rs

Repository: EffortlessMetrics/diffguard

Length of output: 1272


🏁 Script executed:

#!/bin/bash
# Verify the crate name from Cargo.toml
cat crates/diffguard-core/Cargo.toml | grep -A 2 '^\[package\]'

Repository: EffortlessMetrics/diffguard

Length of output: 129


Property tests are not testing the production escape_xml implementation.

Line 283 introduces a local escape_xml, so all assertions validate duplicated test code instead of the actual production function at crates/diffguard-core/src/xml_utils.rs:14. Real regressions in the production implementation can go undetected. Import the production function using use diffguard_core::xml_utils::escape_xml; or move these properties into src/xml_utils.rs under #[cfg(test)].

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/diffguard-core/tests/property_tests_escape_xml.rs` around lines 283 -
296, The tests in property_tests_escape_xml.rs define a local escape_xml which
masks the real implementation; remove the local fn escape_xml and import the
production function with use diffguard_core::xml_utils::escape_xml; so the
property tests call diffguard_core::xml_utils::escape_xml (or alternatively move
these property tests into src/xml_utils.rs under #[cfg(test)] to exercise the
production function directly).

Comment on lines +131 to +134
/// # Errors
///
/// Returns [`DiffParseError`] if the diff text contains a malformed hunk header.
/// See that type's documentation for all possible variants.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

# Errors contract is inconsistent with current implementation.

Line 133 says malformed hunk headers return DiffParseError, but Line 223–235 explicitly swallows parse failures and continues, so parse_unified_diff currently does not return that error in this case. Please align docs and behavior (either propagate Err or document best-effort parsing without returning malformed-header errors).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/diffguard-diff/src/unified.rs` around lines 131 - 134, The doc comment
for parse_unified_diff claiming malformed hunk headers return DiffParseError is
inconsistent with the implementation that swallows hunk-header parse failures;
update the implementation so parse_unified_diff actually propagates header parse
errors instead of continuing. Locate the parse_unified_diff function and where
hunk header parsing currently catches/ignores failures (the block that swallows
parse errors) and change it to return Err(DiffParseError::...) or propagate the
parse result with ? so malformed headers produce the DiffParseError the docs
promise.

Comment on lines +92 to 98
/// Returns [`RuleCompileError`] if any rule configuration is invalid.
/// Variants include:
/// - [`RuleCompileError::MissingPatterns`] — rule has no patterns defined
/// - [`RuleCompileError::InvalidRegex`] — pattern is not a valid regex
/// - [`RuleCompileError::InvalidGlob`] — path glob is malformed
/// - [`RuleCompileError::InvalidMultilineWindow`] — `multiline_window` is less than 2
pub fn compile_rules(configs: &[RuleConfig]) -> Result<Vec<CompiledRule>, RuleCompileError> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

compile_rules error docs omit one emitted variant.

Line 93 says “Variants include,” but compile_rules can also return RuleCompileError::UnknownDependency (see Line 135–141). Please add it to avoid an incomplete public error contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/diffguard-domain/src/rules.rs` around lines 92 - 98, The doc comment
for compile_rules omits the RuleCompileError::UnknownDependency variant; update
the comment block above pub fn compile_rules to list this variant (e.g., add “-
[`RuleCompileError::UnknownDependency`] — a rule refers to a dependency that
does not exist”) so the public error contract includes UnknownDependency
alongside MissingPatterns, InvalidRegex, InvalidGlob, and
InvalidMultilineWindow.

Comment on lines +23 to +27
| Line 1768 (function signature) | `fn parse_blame_porcelain(blame_text: &str) -> Result<BTreeMap<u32, BlameLineMeta>>` | `fn parse_blame_porcelain(blame_text: &str) -> BTreeMap<u32, BlameLineMeta>` |
| Line 1818 (return) | `Ok(out)` | `out` |
| Lines 1861-1862 (caller) | `.with_context(...)?` | Remove `.with_context()` and `?` |
| Line 4068 (test) | `.expect("parse")` | Remove `.expect()` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Prefer symbol-based references over hardcoded line numbers.

The spec ties requirements to exact line numbers in crates/diffguard/src/main.rs, which will quickly drift. Refer to symbols/sections (function name, caller name, test name) instead to keep this document durable.

Proposed doc edit
-| Line 1768 (function signature) | `fn parse_blame_porcelain(blame_text: &str) -> Result<BTreeMap<u32, BlameLineMeta>>` | `fn parse_blame_porcelain(blame_text: &str) -> BTreeMap<u32, BlameLineMeta>` |
-| Line 1818 (return) | `Ok(out)` | `out` |
-| Lines 1861-1862 (caller) | `.with_context(...)?` | Remove `.with_context()` and `?` |
-| Line 4068 (test) | `.expect("parse")` | Remove `.expect()` |
+| `parse_blame_porcelain` signature | `fn parse_blame_porcelain(blame_text: &str) -> Result<BTreeMap<u32, BlameLineMeta>>` | `fn parse_blame_porcelain(blame_text: &str) -> BTreeMap<u32, BlameLineMeta>` |
+| `parse_blame_porcelain` return expression | `Ok(out)` | `out` |
+| Caller in `collect_blame_allowed_lines` | `.with_context(...)?` | Remove `.with_context()` and `?` |
+| Test `parse_blame_porcelain_extracts_line_metadata` | `.expect("parse")` | Remove `.expect()` |

Also applies to: 48-48

🧰 Tools
🪛 LanguageTool

[style] ~25-~25: Consider using the typographical ellipsis character here instead.
Context: ... | out | | Lines 1861-1862 (caller) | .with_context(...)? | Remove .with_context() and ? |...

(ELLIPSIS)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@specs-011-parse-blame-porcelain-result.md` around lines 23 - 27, The spec
currently anchors changes to exact line numbers in crates/diffguard/src/main.rs
which will drift; update the document to reference symbols instead — e.g., refer
to the function signature change for parse_blame_porcelain (fn
parse_blame_porcelain(blame_text: &str) -> BTreeMap<u32, BlameLineMeta>), the
return-site change (returning out instead of Ok(out)), the caller change that
removes the .with_context(...)? call (reference the calling function by name
where that removal occurs), and the test change that removes the
.expect("parse") call (reference the test by its test function name); replace
all hardcoded line-number mentions with these symbol-based references throughout
the spec.

@EffortlessSteven
Copy link
Copy Markdown
Member Author

✅ doc-writer agent complete — work-b7815019

Changes

Added docstrings to 9 public structs/enums in crates/diffguard-types/src/lib.rs:

Symbol Summary
ToolMeta Metadata describing the tool that produced a check receipt
DiffMeta Metadata describing the git diff that was scanned
Finding A single rule match within a scoped file
VerdictStatus The overall disposition of a check run
VerdictCounts Severity counts for a check run
Verdict The overall result of a check run
CheckReceipt The complete output of a single check run
Defaults Default values for omitted config fields
RuleConfig A single rule definition within a ConfigFile

Added WHY comments to 2 helper predicates:

  • is_false — explains it avoids emitting false for default-flag fields
  • is_match_mode_any — explains it keeps configs minimal by skipping defaults

Tests

All 37 tests pass.

Commit

6a195addocs(lib.rs): add docstrings to public structs/enums and WHY comments

@EffortlessSteven
Copy link
Copy Markdown
Member Author

This PR has been closed and replaced with docs/add-errors-sections. The new branch contains ONLY the # Errors documentation additions to 4 core public APIs. All unrelated changes removed. Please close PR #145 and review/merge docs/add-errors-sections.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core public APIs missing # Errors section in doc comments

1 participant