fix(lsp): section-range termination is level-aware (caption audit follow-up)
CI / cargo fmt --check (push) Successful in 20s
CI / cargo clippy (push) Successful in 37s
CI / cargo test (push) Successful in 27s
CI / editor keymaps (push) Successful in 1m38s

The post-captions audit found find_section_range terminated a generated
section only at the next *level-1* heading. With a custom non-1
*_header_level (e.g. a level-2 Generated Tags index) a following same-level
section could be absorbed into the replaced span. Terminate at the next
heading of level <= the matched section's level instead, which keeps the
deeper `level+1` sub-groups inside while stopping at a sibling/parent.

Test: find_section_range_stops_at_same_level_sibling. 0 failures, clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 18:49:00 +00:00
parent 545367c3f6
commit 3fd04b0efa
2 changed files with 27 additions and 7 deletions
+17
View File
@@ -305,6 +305,23 @@ fn build_toc_text_with_no_headings_is_just_the_heading() {
assert_eq!(out, "= Contents =\n");
}
#[test]
fn find_section_range_stops_at_same_level_sibling() {
// A non-level-1 generated section (e.g. a level-2 tags index) must not
// swallow the following same-level section when regenerated.
let src = "== Foo ==\n- a\n== Bar ==\n- b\n";
let ast = parse(src);
let (start, end) = ops::find_section_range(&ast, "Foo").expect("section found");
let bar_off = src.find("== Bar ==").unwrap();
assert_eq!(start.offset, 0);
assert!(
end.offset <= bar_off,
"section absorbed the sibling: end={} bar={}",
end.offset,
bar_off
);
}
#[test]
fn captions_honour_custom_header_and_level() {
// toc_header="Table of Contents", level 2 → `== Table of Contents ==`.