pub fn compute_damage_range(
old: &[String],
new: &[String],
cursor_row: usize,
) -> Option<Range<usize>>Expand description
Compute the row range that differs between old and new, with a
cursor-row hint to accelerate the common single-character-edit case.
Contract: cursor_row must be the row that was actually edited
(the editor’s cursor position after the keystroke), and it must be the
only edited row outside the hint window. The fast path trusts this —
given a cursor_row that does not identify the sole edit point, the
function under-reports the damaged range and rows outside it keep a stale
ParsedLine.
Callers performing an edit that does not satisfy this must not call it:
super::view::MarkdownEditorView::note_bulk_edit forces the slow path
for the next update, and every bulk-edit site is expected to use it.
This used to say distant simultaneous edits “can only happen via
programmatic buffer replacement, which goes through set_text”. That is
false. A replace all rewrites rows across the whole buffer, deliberately
preserves the line count, does not go through set_text, and restores the
cursor to a row it may itself have edited — satisfying every precondition of
the fast path while violating its meaning. Concretely, rewriting rows 0 and
6 of a seven-row buffer with cursor_row = 6 returns 6..7.
No mis-render was reproducible from that, because the incremental parser’s later guards (kind, opener-shape, lazy-depth, the widening cap) happen to catch a distant edit — but none of them is aimed at this, so the safety was incidental. Hence the explicit signal rather than a reliance on them.
Returns None when the buffers are byte-identical (defensive
guard — callers should already have gated on text_revision).
Fast path: same line count, the row at cursor_row differs, and
no other line in ±CURSOR_HINT_WINDOW differs. Returns
Some(cursor_row..cursor_row + 1). O(CURSOR_HINT_WINDOW).
Slow path: longest common prefix (LCP) and longest common suffix (LCS); damaged range is the middle slice. O(min(buffer_size, damage_size)).