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}