Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Build a Smaller rust-analyzer

Build a language service with lossless parsing, revisioned inputs, dependency-tracked queries, snapshot workers, and cancellation of stale work.

1. Parse incomplete expressions

Create tokens and a tiny immutable syntax tree. Return (tree, errors) and add error nodes rather than failing. Make every typed child accessor optional.

2. Add ground inputs

Store FileId → Arc<str> and a small crate graph. Keep paths in a separate VFS map. All semantic functions accept IDs, never read files.

3. Build a memoized query engine

Implement parse, definitions, name resolution, and type-of-expression queries. Record query dependencies and input revisions. Reuse a result only if its transitive inputs remain unchanged.

4. Separate host and snapshot

AnalysisHost owns mutable inputs. analysis() returns a cloneable read snapshot. Applying a change advances the revision and invalidates outstanding snapshots.

5. Add main-loop dispatch

Use channels for client, VFS, and worker events. Apply all mutations in one loop. Route typed read requests with a snapshot to a fixed thread pool and send responses back as tasks.

6. Make stale work cancel

Have long queries periodically compare their captured revision with the host’s current revision and unwind or return Cancelled. Map cancellation to retry for idempotent requests and content-modified otherwise.

7. Add latency classes

Keep trivial typing operations synchronous, semantic work on a worker pool, and one blocking formatter on a separate lane. Saturate the semantic pool and prove the typing and formatting paths still respond.

8. Isolate an extension

Run a fake macro expander as a subprocess over framed messages. Crash it on one request; preserve syntax features, report degradation, and restart it.

9. Compare with production

Map your design to VFS, GlobalState, AnalysisHost, Analysis, Salsa inputs and tracked functions, RequestDispatcher, TaskPool, HIR/IDE façades, Cargo, flycheck, and proc-macro server. The real repository adds the Rust language, macro hygiene, rich inference, project models, thousands of features, and careful memory tuning. Preserve its center: immutable derived worlds that can be abandoned the moment ground truth changes.