Skip to main content

Module reparse

Module reparse 

Source
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.

  1. [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.
  2. [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.
  3. [reparse_toplevel] — the edit lands inside a single top-level statement (a direct child of the ROOT node) 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.
  4. Otherwise return None; the caller does a full crate::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) with insert.
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§

ReparseKind
Which strategy produced a Reparsed. Surfaced for tests and benchmarks.

Functions§

apply_edits
Apply edits to old left-to-right, each expressed against the text its predecessors produced — the inverse operation to map_range_through_edits.
diff_edit
Recover a single contiguous Edit (deleted range in old + 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 edits to old left-to-right yields exactly target: apply_edits(old, edits) == target without the final rebuild, and without the panic on a slice that does not fit.
map_range_through_edit
Map a TextRange taken against the text before edit to its position in the text after edit.
map_range_through_edits
Map a range through a sequence of edits applied left-to-right (the order Edit::apply would run them — each edit is expressed against the text produced by its predecessors). Any single invalidating edit collapses the whole result to None.
reparse
Attempt an incremental reparse of old_root (parsed from old_text, with old_diags) under edit. Returns None when no incremental strategy applies — the caller must then do a full parse. An edit whose range old_text cannot take is one such case, not a panic.
reparse_edits
Chain the single-edit reparse over a sequence of edits (each expressed against the text its predecessors produced, in the order Edit::apply would 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 wide diff_edit span (the whole point of feeding precise LSP edits through — multi-cursor and find-replace).
reparse_edits_with_options
reparse_edits with the ParseOptions the old tree was parsed under (see reparse_with_options).
reparse_with_options
reparse with the ParseOptions the old tree was parsed under. A tree parsed via parse_with_options must 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.