Skip to content

Commit 12f34e3

Browse files
committed
fix(md077): correct nested list tight continuation false positive
When scanning a parent item's range, continuation lines belonging to a nested child item were incorrectly checked against the parent's content column. This caused false positives (correct indent flagged as over- indented) and wrong fix output (reducing to parent's indent instead of child's). Track nested item scope and skip lines that belong to child items — those are handled by the child's own iteration.
1 parent a1e100d commit 12f34e3

1 file changed

Lines changed: 38 additions & 2 deletions

File tree

src/rules/md077_list_continuation_indent.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ impl Rule for MD077ListContinuationIndent {
120120
.unwrap_or(total_lines);
121121

122122
let mut saw_blank = false;
123+
// Track nested child items so we don't check their continuation
124+
// lines against the parent's content column.
125+
let mut nested_content_col: Option<usize> = None;
123126

124127
for line_num in (item_line + 1)..=range_end {
125128
let Some(line_info) = ctx.line_info(line_num) else {
@@ -138,7 +141,12 @@ impl Rule for MD077ListContinuationIndent {
138141
}
139142

140143
// Nested list items are not continuation content
141-
if line_info.list_item.is_some() {
144+
if let Some(ref li) = line_info.list_item {
145+
if li.marker_column > marker_col {
146+
nested_content_col = Some(li.content_column);
147+
} else {
148+
nested_content_col = None;
149+
}
142150
saw_blank = false;
143151
continue;
144152
}
@@ -161,6 +169,15 @@ impl Rule for MD077ListContinuationIndent {
161169

162170
let actual = line_info.visual_indent;
163171

172+
// Lines belonging to a nested item's scope are handled by
173+
// that item's own iteration — skip them here.
174+
if let Some(ncc) = nested_content_col {
175+
if actual >= ncc {
176+
continue;
177+
}
178+
nested_content_col = None;
179+
}
180+
164181
// Tight continuation (no blank line): flag over-indented lines
165182
if !saw_blank {
166183
if actual > required && flagged_lines.insert(line_num) {
@@ -359,11 +376,30 @@ mod tests {
359376

360377
#[test]
361378
fn tight_continuation_nested_over_indented() {
362-
// L2 "- " at column 2, content_column = 4. Continuation at 5 is over-indented.
379+
// L2 "- " at column 2, content_column = 4. Continuation at 5 is over-indented for L2.
363380
let content = "- L1\n - L2\n over-indented continuation of L2\n";
364381
let warnings = check(content);
365382
assert_eq!(warnings.len(), 1);
366383
assert_eq!(warnings[0].line, 3);
384+
// Must report expected=4 (L2's content_col), not expected=2 (L1's)
385+
assert!(warnings[0].message.contains("expected 4"));
386+
assert!(warnings[0].message.contains("found 5"));
387+
}
388+
389+
#[test]
390+
fn tight_continuation_nested_correct_indent_not_flagged() {
391+
// Continuation at 4 spaces is correct for L2 (content_col=4). Must NOT be
392+
// flagged as over-indented relative to L1 (content_col=2).
393+
let content = "- L1\n - L2\n correctly indented continuation of L2\n";
394+
assert!(check(content).is_empty());
395+
}
396+
397+
#[test]
398+
fn fix_tight_continuation_nested_over_indented() {
399+
// Fix should reduce to 4 spaces (L2's content_col), not 2 (L1's)
400+
let content = "- L1\n - L2\n over-indented continuation of L2\n";
401+
let fixed = fix(content);
402+
assert_eq!(fixed, "- L1\n - L2\n over-indented continuation of L2\n");
367403
}
368404

369405
#[test]

0 commit comments

Comments
 (0)