use std::collections::HashMap;
use lsp_types::{
FullDocumentDiagnosticReport, WorkspaceDiagnosticParams, WorkspaceDiagnosticReport,
WorkspaceFullDocumentDiagnosticReport,
};
use tokio_util::sync::CancellationToken;
use crate::context::{ServerContextSnapshot, WorkspaceDiagnosticLevel};
pub async fn on_pull_workspace_diagnostic(
context: ServerContextSnapshot,
_: WorkspaceDiagnosticParams,
token: CancellationToken,
) -> WorkspaceDiagnosticReport {
if !context.debounced_analysis().wait_until_fresh(&token).await {
return WorkspaceDiagnosticReport { items: vec![] };
}
let Some(workspace_manager) = context.read_workspace_manager(&token).await else {
return WorkspaceDiagnosticReport { items: vec![] };
};
let status = workspace_manager.get_workspace_diagnostic_level();
if status == WorkspaceDiagnosticLevel::None {
return WorkspaceDiagnosticReport { items: vec![] };
}
let client_id = workspace_manager.client_config.client_id;
let open_files = workspace_manager.current_open_files.clone();
workspace_manager.update_workspace_version(WorkspaceDiagnosticLevel::None, false);
drop(workspace_manager);
if client_id.is_vscode() && context.lsp_features().supports_refresh_diagnostic() {
context.client().refresh_workspace_diagnostics();
}
let file_diagnostics = match status {
WorkspaceDiagnosticLevel::None => Vec::new(),
WorkspaceDiagnosticLevel::Fast => {
context
.file_diagnostic()
.pull_workspace_diagnostics_fast(token)
.await
}
WorkspaceDiagnosticLevel::Slow => {
context
.file_diagnostic()
.pull_workspace_diagnostics_slow(token)
.await
}
};
let open_file_versions = {
let analysis = context.analysis().read().await;
file_diagnostics
.iter()
.filter_map(|(uri, _)| {
if !open_files.contains(uri) {
return None;
}
let version = analysis.get_file_id(uri).and_then(|file_id| {
analysis
.compilation
.get_db()
.get_vfs()
.get_file_version(&file_id)
});
Some((uri.clone(), version))
})
.collect::<HashMap<_, _>>()
};
WorkspaceDiagnosticReport {
items: file_diagnostics
.into_iter()
.map(|(uri, diagnostics)| {
WorkspaceFullDocumentDiagnosticReport {
version: open_file_versions
.get(&uri)
.copied()
.flatten()
.map(i64::from),
uri,
full_document_diagnostic_report: FullDocumentDiagnosticReport {
items: diagnostics,
result_id: None,
},
}
.into()
})
.collect(),
}
}