php_lsp/db/parse.rs
1//! The `parsed_doc` salsa query: parses a `SourceFile` into an `Arc<ParsedDoc>`
2//! under salsa memoization. Downstream queries (file_index, symbol_map,
3//! semantic diagnostics) depend on this one, so each file is parsed at most
4//! once per revision.
5//!
6//! `ParsedDoc` owns a self-referential bumpalo arena and cannot safely
7//! implement the structural `Update` trait — instead we wrap in a `ParsedArc`
8//! newtype whose `Update` impl uses `Arc::ptr_eq`. Every reparse produces a
9//! new `Arc`, so pointer equality is a correct (if conservative) "changed"
10//! signal: salsa never falsely backdates, and downstream queries re-run after
11//! every input text change.
12
13use std::sync::Arc;
14
15use crate::document::ast::ParsedDoc;
16
17/// Opaque handle to a parsed document. Cheap to clone (refcount bump); never
18/// compared structurally. See module docs for the `Update` contract.
19///
20/// No `Debug` impl because `ParsedDoc` isn't `Debug` (it owns raw pointers
21/// into a bumpalo arena). Salsa doesn't require `Debug` on tracked returns
22/// when `no_eq` is used.
23#[derive(Clone)]
24pub struct ParsedArc(pub Arc<ParsedDoc>);
25
26impl ParsedArc {
27 pub fn get(&self) -> &ParsedDoc {
28 &self.0
29 }
30}
31
32// SAFETY: The `ptr_eq` short-circuit returns `false` without writing, matching
33// salsa's "no observable change" contract. `ParsedDoc` is already `Send + Sync`
34// (see `ast.rs:98`).
35crate::impl_arc_update!(ParsedArc);