Skip to main content

lattice_host/
diagnostics_query.rs

1//! L4b (lsp-architecture.md ยง15): host-side [`lattice_lsp::modes::DiagnosticsQuery`]
2//! impl backing `lsp-diagnostics-mode`'s mode-owned `gl` handler.
3//!
4//! The mode handler (in `lattice-lsp`) has only `ctx.buffer_id` +
5//! `ctx.cursor` + the service registry โ€” it cannot resolve a buffer to
6//! its LSP URI (that map is editor-local). This impl closes that gap:
7//! it reads the live published [`RenderState`] snapshot, resolves
8//! `buffer_id โ†’ uri` through `buffers.uris`, and queries the
9//! `DiagnosticsLayer` โ€” all without exposing a host method or the URI
10//! map to the mode. Registered once at boot under
11//! [`lattice_lsp::modes::DiagnosticsQueryHandle`].
12
13use std::sync::Arc;
14
15use arc_swap::ArcSwap;
16
17use crate::render_state::RenderState;
18
19/// Reads a buffer's per-line diagnostics over the published render
20/// state. Cheap: one `ArcSwap::load` + a `HashMap` lookup + the layer's
21/// wait-free `diagnostics_on_line`.
22pub(crate) struct HostDiagnosticsQuery {
23    render_state: Arc<ArcSwap<RenderState>>,
24}
25
26impl HostDiagnosticsQuery {
27    pub(crate) fn new(render_state: Arc<ArcSwap<RenderState>>) -> Self {
28        Self { render_state }
29    }
30}
31
32impl lattice_lsp::modes::DiagnosticsQuery for HostDiagnosticsQuery {
33    fn on_line(
34        &self,
35        buffer_id: lattice_protocol::ids::BufferId,
36        line: u32,
37    ) -> Vec<lattice_lsp::Diagnostic> {
38        let rs = self.render_state.load();
39        let core_id = lattice_core::BufferId(buffer_id.raw() as u32);
40        let Some(uri) = rs.buffers.uris.get(&core_id) else {
41            return Vec::new();
42        };
43        rs.diagnostics.layer.diagnostics_on_line(uri, line)
44    }
45
46    /// IDE-protocol I2.0: all diagnostics for a file `uri` (string form).
47    /// Parses the uri and reads the layer's `diagnostics_for`; both are
48    /// wait-free over the published render state, so this is safe to call
49    /// off the editor thread (the Claude Code IDE peer's WS task does).
50    fn for_uri(&self, uri: &str) -> Vec<lattice_lsp::Diagnostic> {
51        let Ok(parsed) = lattice_lsp::uri_from_str(uri) else {
52            return Vec::new();
53        };
54        self.render_state
55            .load()
56            .diagnostics
57            .layer
58            .diagnostics_for(&parsed)
59    }
60
61    /// IDE-protocol I2.0: every uri (string form) with diagnostics.
62    fn uris_with_diagnostics(&self) -> Vec<String> {
63        self.render_state
64            .load()
65            .diagnostics
66            .layer
67            .iter_uris()
68            .into_iter()
69            .map(|u| u.as_str().to_string())
70            .collect()
71    }
72}