use std::collections::HashSet;
use std::path::PathBuf;
use tokio::sync::mpsc;
use tower_lsp::lsp_types::Url;
use super::server::RumdlLanguageServer;
use super::types::RelintRequest;
impl RumdlLanguageServer {
pub(super) async fn run_relint_worker(self, mut requests: mpsc::Receiver<RelintRequest>) {
while let Some(first) = requests.recv().await {
let mut paths: HashSet<PathBuf> = HashSet::new();
let mut all_open = false;
let mut request = Some(first);
while let Some(current) = request {
match current {
RelintRequest::File(path) => {
paths.insert(path);
}
RelintRequest::AllOpen => all_open = true,
}
request = requests.try_recv().ok();
}
self.republish_open_documents(&paths, all_open).await;
}
log::debug!("Re-lint worker stopped: the index worker is gone");
}
async fn republish_open_documents(&self, paths: &HashSet<PathBuf>, all_open: bool) {
let targets: Vec<Url> = {
let documents = self.documents.read().await;
documents
.iter()
.filter(|(_, entry)| !entry.from_disk)
.filter(|(uri, _)| all_open || super::resolve_uri(uri).is_some_and(|path| paths.contains(&path)))
.map(|(uri, _)| uri.clone())
.collect()
};
if targets.is_empty() {
return;
}
if *self.client_supports_pull_diagnostics.read().await {
if let Err(e) = self.client.workspace_diagnostic_refresh().await {
log::debug!("Client did not accept workspace/diagnostic/refresh: {e}");
}
return;
}
log::debug!("Re-linting {} open document(s) after an index change", targets.len());
for uri in targets {
self.republish_diagnostics(uri, all_open).await;
}
}
async fn republish_diagnostics(&self, uri: Url, run_external_tools: bool) {
let Some((text, version)) = ({
let documents = self.documents.read().await;
documents
.get(&uri)
.filter(|entry| !entry.from_disk)
.map(|entry| (entry.content.clone(), entry.version))
}) else {
return;
};
match self.lint_document(&uri, &text, run_external_tools).await {
Ok(diagnostics) => {
let current = {
let documents = self.documents.read().await;
documents.get(&uri).and_then(|entry| entry.version)
};
if current != version {
log::debug!("Dropping re-lint of {uri}: the document changed while it ran");
return;
}
self.client.publish_diagnostics(uri, diagnostics, version).await;
}
Err(e) => {
log::error!("Failed to re-lint {uri}: {e}");
}
}
}
}
#[cfg(test)]
#[path = "relint_tests.rs"]
mod tests;