|
| 1 | +use crate::diagnostics::LspError; |
1 | 2 | use crate::documents::Document; |
| 3 | +use crate::utils; |
2 | 4 | use anyhow::Result; |
| 5 | +use futures::stream::FuturesUnordered; |
| 6 | +use futures::StreamExt; |
3 | 7 | use pg_configuration::ConfigurationPathHint; |
4 | 8 | use pg_diagnostics::{DiagnosticExt, Error}; |
5 | 9 | use pg_fs::{FileSystem, PgLspPath}; |
6 | 10 | use pg_lsp_converters::{negotiated_encoding, PositionEncoding, WideEncoding}; |
7 | 11 | use pg_workspace_new::configuration::{load_configuration, LoadedConfiguration}; |
8 | 12 | use pg_workspace_new::settings::PartialConfigurationExt; |
9 | | -use pg_workspace_new::workspace::UpdateSettingsParams; |
| 13 | +use pg_workspace_new::workspace::{PullDiagnosticsParams, UpdateSettingsParams}; |
10 | 14 | use pg_workspace_new::Workspace; |
11 | 15 | use pg_workspace_new::{DynRef, WorkspaceError}; |
12 | 16 | use rustc_hash::FxHashMap; |
@@ -237,6 +241,75 @@ impl Session { |
237 | 241 | } |
238 | 242 | } |
239 | 243 |
|
| 244 | + /// Computes diagnostics for the file matching the provided url and publishes |
| 245 | + /// them to the client. Called from [`handlers::text_document`] when a file's |
| 246 | + /// contents changes. |
| 247 | + #[tracing::instrument(level = "trace", skip_all, fields(url = display(&url), diagnostic_count), err)] |
| 248 | + pub(crate) async fn update_diagnostics(&self, url: lsp_types::Url) -> Result<(), LspError> { |
| 249 | + let pglsp_path = self.file_path(&url)?; |
| 250 | + let doc = self.document(&url)?; |
| 251 | + if self.configuration_status().is_error() && !self.notified_broken_configuration() { |
| 252 | + self.set_notified_broken_configuration(); |
| 253 | + self.client |
| 254 | + .show_message(MessageType::WARNING, "The configuration file has errors. Biome will report only parsing errors until the configuration is fixed.") |
| 255 | + .await; |
| 256 | + } |
| 257 | + |
| 258 | + let diagnostics: Vec<lsp_types::Diagnostic> = { |
| 259 | + let result = self.workspace.pull_diagnostics(PullDiagnosticsParams { |
| 260 | + path: pglsp_path.clone(), |
| 261 | + max_diagnostics: u64::MAX, |
| 262 | + })?; |
| 263 | + |
| 264 | + tracing::trace!("biome diagnostics: {:#?}", result.diagnostics); |
| 265 | + |
| 266 | + result |
| 267 | + .diagnostics |
| 268 | + .into_iter() |
| 269 | + .filter_map(|d| { |
| 270 | + match utils::diagnostic_to_lsp( |
| 271 | + d, |
| 272 | + &url, |
| 273 | + &doc.line_index, |
| 274 | + self.position_encoding(), |
| 275 | + None, |
| 276 | + ) { |
| 277 | + Ok(diag) => Some(diag), |
| 278 | + Err(err) => { |
| 279 | + error!("failed to convert diagnostic to LSP: {err:?}"); |
| 280 | + None |
| 281 | + } |
| 282 | + } |
| 283 | + }) |
| 284 | + .collect() |
| 285 | + }; |
| 286 | + |
| 287 | + tracing::Span::current().record("diagnostic_count", diagnostics.len()); |
| 288 | + |
| 289 | + self.client |
| 290 | + .publish_diagnostics(url, diagnostics, Some(doc.version)) |
| 291 | + .await; |
| 292 | + |
| 293 | + Ok(()) |
| 294 | + } |
| 295 | + |
| 296 | + /// Updates diagnostics for every [`Document`] in this [`Session`] |
| 297 | + pub(crate) async fn update_all_diagnostics(&self) { |
| 298 | + let mut futures: FuturesUnordered<_> = self |
| 299 | + .documents |
| 300 | + .read() |
| 301 | + .unwrap() |
| 302 | + .keys() |
| 303 | + .map(|url| self.update_diagnostics(url.clone())) |
| 304 | + .collect(); |
| 305 | + |
| 306 | + while let Some(result) = futures.next().await { |
| 307 | + if let Err(e) = result { |
| 308 | + error!("Error while updating diagnostics: {}", e); |
| 309 | + } |
| 310 | + } |
| 311 | + } |
| 312 | + |
240 | 313 | /// Get a [`Document`] matching the provided [`lsp_types::Url`] |
241 | 314 | /// |
242 | 315 | /// If document does not exist, result is [WorkspaceError::NotFound] |
|
0 commit comments