1use dashmap::DashMap;
4use lsp_server::Connection;
5use lsp_types::{Diagnostic, PublishDiagnosticsParams, Url};
6
7pub struct DiagnosticEngine {
9 diagnostics: DashMap<Url, Vec<Diagnostic>>,
11}
12
13impl DiagnosticEngine {
14 pub fn new() -> Self {
16 Self {
17 diagnostics: DashMap::new(),
18 }
19 }
20
21 pub fn add(&self, uri: Url, diagnostic: Diagnostic) {
23 self.diagnostics.entry(uri).or_default().push(diagnostic);
24 }
25
26 pub fn clear(&self, uri: &Url) {
28 self.diagnostics.remove(uri);
29 }
30
31 pub fn get(&self, uri: &Url) -> Vec<Diagnostic> {
33 self.diagnostics
34 .get(uri)
35 .map(|v| v.clone())
36 .unwrap_or_default()
37 }
38
39 pub fn publish(&self, connection: &Connection, uri: &Url) -> crate::Result<()> {
53 use lsp_server::{Message, Notification};
54 use lsp_types::notification::{Notification as _, PublishDiagnostics};
55
56 let diagnostics = self.get(uri);
58 let diagnostics_count = diagnostics.len();
59
60 let params = PublishDiagnosticsParams {
62 uri: uri.clone(),
63 diagnostics,
64 version: None,
65 };
66
67 let notification = Notification {
69 method: PublishDiagnostics::METHOD.to_string(),
70 params: serde_json::to_value(params).map_err(|e| {
71 crate::Error::Other(anyhow::anyhow!("Failed to serialize diagnostics: {}", e))
72 })?,
73 };
74
75 connection
77 .sender
78 .send(Message::Notification(notification))
79 .map_err(|e| {
80 crate::Error::Other(anyhow::anyhow!("Failed to send diagnostics: {}", e))
81 })?;
82
83 tracing::debug!("Published {} diagnostics for {}", diagnostics_count, uri);
84
85 Ok(())
86 }
87}
88
89impl Default for DiagnosticEngine {
90 fn default() -> Self {
91 Self::new()
92 }
93}