In “Zig Language Server and Cancellation”, Alex Kladov discusses approaches to the data model of a language server, in their case for Zig.
In the snapshot approach, the language server would have three snapshots: A fully analyzed ready snapshot with the source files, their ASTs, ZIRs, and AIRs (analyzed IR), and pre-computed cross-references. The working snapshot has essentially the same data, but with the AIR being constructed. It also holds the ASTs in pending for files currently being modified.
Edits are synchronously applied per-file to pending. When there are no syntax errors, for example, a batch of errors is collected from pending, sent to working for analysis in the background. Once working is fully processed, ready is atomically updated to that.
This approach always returns correct results for AST queries, while other queries may have some divergence.
In the Hacker News discussion, some commenters note this may be over-engineered. For example, the AST need not be completely re-parsed on every update, as it will most likely fail, and can instead map positions to edited positions by tracking deltas.