Expand description
Incremental reparse: turn a single text edit plus the previous parse tree into a new tree without re-lexing and re-parsing the whole file.
Modelled on rust-analyzer’s reparsing.rs: try the cheapest strategy first
and fall back to progressively more work.
- [
reparse_token] — the edit lands inside one leaf token (identifier, string, comment, whitespace) and re-lexing that token’s text yields the same single token kind. Splice a fresh leaf in place. - [
reparse_block] — the edit lands strictly inside a{ … }block. Re-lex and re-parse just that block (it is self-contained — braces delimit it, so its subtree never depends on the surrounding context) and splice the new block subtree in place. - [
reparse_toplevel] — the edit lands inside a single top-level statement (a direct child of theROOTnode) that isn’t inside any{ … }. Unlike a block, a bare statement has no delimiter tokens, so its boundary is pinned by two guards: a consume-all check (the reparse must consume every token of the statement text — this rules out the statement shrinking and releasing trailing tokens) and a forward-merge guard (re-parsing the statement with the next sibling appended must still end at the statement’s original length — this rules out the statement growing to absorb what follows, e.g. a trailing binary operator). The backward direction is inherently safe: R only continues a statement across a newline via a trailing operator, never a leading one, and the previous sibling’s tokens are untouched by the edit. - Otherwise return
None; the caller does a fullcrate::parser::parse.
Correctness invariant (Tenet 4): a successful reparse must yield a green
tree and diagnostics byte-identical to a full parse of the edited text.
Splicing relies on rowan green nodes being position-independent. The invariant
is enforced by tests/incremental_reparse.rs (an oracle property test over the
corpus) and a debug_assert! here.
Structs§
- Edit
- A single contiguous text edit: replace
range(a byte range in the old text) withinsert. - Reparsed
- The result of a successful incremental reparse: the new whole-file green tree and its parse diagnostics (absolute offsets in the new text).
Enums§
- Reparse
Kind - Which strategy produced a
Reparsed. Surfaced for tests and benchmarks.
Functions§
- apply_
edits - Apply
editstooldleft-to-right, each expressed against the text its predecessors produced — the inverse operation tomap_range_through_edits. - diff_
edit - Recover a single contiguous
Edit(deleted range inold+ inserted text) from a pair of full texts by stripping the common prefix and suffix. Multiple disjoint edits collapse into one spanning edit — still a correct transform, just coarser. Boundaries are clamped to char boundaries. - edits_
produce - Whether applying
editstooldleft-to-right yields exactlytarget:apply_edits(old, edits) == targetwithout the final rebuild, and without the panic on a slice that does not fit. - map_
range_ through_ edit - Map a
TextRangetaken against the text beforeeditto its position in the text afteredit. - map_
range_ through_ edits - Map a range through a sequence of edits applied left-to-right (the order
Edit::applywould run them — each edit is expressed against the text produced by its predecessors). Any single invalidating edit collapses the whole result toNone. - reparse
- Attempt an incremental reparse of
old_root(parsed fromold_text, withold_diags) underedit. ReturnsNonewhen no incremental strategy applies — the caller must then do a full parse. Aneditwhose rangeold_textcannot take is one such case, not a panic. - reparse_
edits - Chain the single-edit
reparseover a sequence ofedits(each expressed against the text its predecessors produced, in the orderEdit::applywould run them). Each step reparses off the previous step’s whole-file tree, so N disjoint edits each reparse their own tight region instead of collapsing into one widediff_editspan (the whole point of feeding precise LSP edits through — multi-cursor and find-replace). - reparse_
edits_ with_ options reparse_editswith theParseOptionsthe old tree was parsed under (seereparse_with_options).- reparse_
with_ options reparsewith theParseOptionsthe old tree was parsed under. A tree parsed viaparse_with_optionsmust be reparsed with the same options, or the correctness invariant (reparse output ≡ full parse of the edited text) breaks for roxygen blocks resolving their markdown mode from the default.