Skip to main content

Module edit

Module edit 

Source
Expand description

Tree-edit primitives for incremental reparse (cy-zv0, spec §11).

§Scope

This module exposes a TextEdit value type plus an incremental_reparse entry point shaped so downstream crates (cyrs-db) can route document edits through a single API. The name incremental_reparse is aspirational: the current implementation is a whole-file reparse fallback that reconstructs the full source from the old tree and calls crate::parse on the result. The API shape is designed so a future “smart” path can slot underneath without breaking callers.

§Why an API-first tranche

Rowan supports lossless green-tree splicing in principle (SyntaxNode::replace_with, GreenNode::replace_child), but a production-quality incremental reparse needs:

  1. A re-lex boundary sniff so edits inside trivia don’t trigger a parser re-entry.
  2. A minimal sub-tree identification that is safe across clause boundaries (an edit that deletes MATCH must invalidate the enclosing statement, not just the token).
  3. Error-recovery reconciliation so an edit that introduces or heals a syntax error produces a tree whose error set matches a full reparse.

Items 1–3 are a research-sized tranche. Landing the API + whole-file fallback lets downstream crates migrate onto Database::edit_file (see cyrs-db) today; the smart path can then land in a follow-up bead without touching any caller.

§Future smart path

When the incremental feature (defaulted-on) is enabled, a future implementation of incremental_reparse may short-circuit to a sub-tree reparse. Consumers must not rely on either the slow or fast path: the invariant is that the returned tree is byte-equal to parse(new_text).syntax() for some canonical new_text derived from old_tree + edit.

§Invariants

  • incremental_reparse(old_tree, edit) produces a Parse whose syntax().to_string() equals the new source text.
  • The call is infallible: malformed UTF-8 cannot enter because TextEdit::replace takes impl Into<String> and TextEdit::apply concatenates bytes at char boundaries.
  • edit.range must lie inside the old source; out-of-range offsets saturate to the source length (matching String::replace_range’s documented behaviour).

Structs§

TextEdit
A single-range text edit.

Functions§

incremental_reparse
Reparse after applying edit to old_tree’s source.