use dashmap::DashMap;
use lsp_server::Connection;
use lsp_types::{Diagnostic, PublishDiagnosticsParams, Url};
pub struct DiagnosticEngine {
diagnostics: DashMap<Url, Vec<Diagnostic>>,
}
impl DiagnosticEngine {
pub fn new() -> Self {
Self {
diagnostics: DashMap::new(),
}
}
pub fn add(&self, uri: Url, diagnostic: Diagnostic) {
self.diagnostics.entry(uri).or_default().push(diagnostic);
}
pub fn clear(&self, uri: &Url) {
self.diagnostics.remove(uri);
}
pub fn get(&self, uri: &Url) -> Vec<Diagnostic> {
self.diagnostics
.get(uri)
.map(|v| v.clone())
.unwrap_or_default()
}
pub fn publish(&self, connection: &Connection, uri: &Url) -> crate::Result<()> {
use lsp_server::{Message, Notification};
use lsp_types::notification::{Notification as _, PublishDiagnostics};
let diagnostics = self.get(uri);
let diagnostics_count = diagnostics.len();
let params = PublishDiagnosticsParams {
uri: uri.clone(),
diagnostics,
version: None,
};
let notification = Notification {
method: PublishDiagnostics::METHOD.to_string(),
params: serde_json::to_value(params).map_err(|e| {
crate::Error::Other(anyhow::anyhow!("Failed to serialize diagnostics: {}", e))
})?,
};
connection
.sender
.send(Message::Notification(notification))
.map_err(|e| {
crate::Error::Other(anyhow::anyhow!("Failed to send diagnostics: {}", e))
})?;
tracing::debug!("Published {} diagnostics for {}", diagnostics_count, uri);
Ok(())
}
}
impl Default for DiagnosticEngine {
fn default() -> Self {
Self::new()
}
}