diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 877eaf6c27..0a907d838c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -13535,11 +13535,11 @@ pub trait DiagnosticsProvider { buffer: &Model, position: text::Anchor, cx: &mut AppContext, - ) -> Task>>; + ) -> Task>>>; fn update_diagnostics( &self, - diagnostics: Vec, + diagnostics: Vec>, cx: &mut AppContext, ) -> Result<()>; } @@ -13884,7 +13884,7 @@ impl DiagnosticsProvider for Model { buffer: &Model, position: text::Anchor, cx: &mut AppContext, - ) -> Task>> { + ) -> Task>>> { self.update(cx, |project, cx| { project.document_diagnostics(buffer, position, cx) }) @@ -13892,23 +13892,27 @@ impl DiagnosticsProvider for Model { fn update_diagnostics( &self, - diagnostics: Vec, + diagnostics: Vec>, cx: &mut AppContext, ) -> Result<()> { self.update(cx, |project, cx| { diagnostics - .into_iter() - .map(|diagnostic_set| { - project.update_diagnostics( + .iter() + .filter_map(|diagnostic_set| match diagnostic_set { + Some(diagnostic_set) => Some(project.update_diagnostics( diagnostic_set.server_id, lsp::PublishDiagnosticsParams { - uri: diagnostic_set.uri.unwrap(), - diagnostics: diagnostic_set.diagnostics.unwrap_or_else(Vec::new), + uri: diagnostic_set.uri.as_ref().unwrap().clone(), + diagnostics: match diagnostic_set.diagnostics.as_ref() { + Some(diagnostics) => diagnostics.clone(), + None => Vec::new(), + }, version: None, }, &[], cx, - ) + )), + None => None, }) .collect() }) diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index ff2a00134f..ec864a9519 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -318,7 +318,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result { @@ -397,7 +397,7 @@ pub fn deserialize_selection(selection: proto::Selection) -> Option, -) -> Vec> { +) -> Arc<[DiagnosticEntry]> { diagnostics .into_iter() .filter_map(|diagnostic| { diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index eb82e1c040..62d53a0df6 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -4,7 +4,7 @@ use crate::{ lsp_store::{LocalLspStore, LspStore}, CodeAction, CoreCompletion, DocumentHighlight, Hover, HoverBlock, HoverBlockKind, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location, - LocationLink, MarkupContent, ProjectTransaction, ResolveState, + LocationLink, LspDiagnostics, MarkupContent, ProjectTransaction, ResolveState, }; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; @@ -3161,7 +3161,7 @@ impl GetDocumentDiagnostics { #[async_trait(?Send)] impl LspCommand for GetDocumentDiagnostics { - type Response = LspDiagnostics; + type Response = Option; type LspRequest = lsp::request::DocumentDiagnosticRequest; type ProtoRequest = proto::GetDocumentDiagnostics; @@ -3211,24 +3211,28 @@ impl LspCommand for GetDocumentDiagnostics { Some(lsp::Url::from_file_path(file.abs_path(cx).clone()).unwrap()) })?; + if uri.is_none() { + return Ok(None); + } + match message { lsp::DocumentDiagnosticReportResult::Report(report) => match report { - lsp::DocumentDiagnosticReport::Full(report) => Ok(LspDiagnostics { + lsp::DocumentDiagnosticReport::Full(report) => Ok(Some(LspDiagnostics { server_id, uri, diagnostics: Some(report.full_document_diagnostic_report.items.clone()), - }), - lsp::DocumentDiagnosticReport::Unchanged(_) => Ok(LspDiagnostics { + })), + lsp::DocumentDiagnosticReport::Unchanged(_) => Ok(Some(LspDiagnostics { server_id, uri, diagnostics: None, - }), + })), }, - lsp::DocumentDiagnosticReportResult::Partial(_) => Ok(LspDiagnostics { + lsp::DocumentDiagnosticReportResult::Partial(_) => Ok(Some(LspDiagnostics { server_id, uri, diagnostics: None, - }), + })), } } @@ -3268,19 +3272,27 @@ impl LspCommand for GetDocumentDiagnostics { _: &clock::Global, _: &mut AppContext, ) -> proto::GetDocumentDiagnosticsResponse { - let diagnostics = if let Some(diagnostics) = response.diagnostics { - diagnostics - .into_iter() - .map(GetDocumentDiagnostics::serialize_lsp_diagnostic) - .collect() - } else { - Vec::new() - }; + if let Some(response) = response { + let diagnostics = if let Some(diagnostics) = response.diagnostics { + diagnostics + .into_iter() + .map(GetDocumentDiagnostics::serialize_lsp_diagnostic) + .collect() + } else { + Vec::new() + }; - proto::GetDocumentDiagnosticsResponse { - server_id: LanguageServerId::to_proto(response.server_id), - uri: response.uri.unwrap().to_string(), - diagnostics, + proto::GetDocumentDiagnosticsResponse { + server_id: LanguageServerId::to_proto(response.server_id), + uri: response.uri.unwrap().to_string(), + diagnostics, + } + } else { + proto::GetDocumentDiagnosticsResponse { + server_id: 0, + uri: Default::default(), + diagnostics: Vec::new(), + } } } @@ -3297,11 +3309,11 @@ impl LspCommand for GetDocumentDiagnostics { .map(GetDocumentDiagnostics::deserialize_lsp_diagnostic) .collect(); - Ok(LspDiagnostics { + Ok(Some(LspDiagnostics { server_id: LanguageServerId::from_proto(response.server_id), uri: Some(lsp::Url::from_str(response.uri.as_str()).unwrap()), diagnostics: Some(diagnostics), - }) + })) } fn buffer_id_from_proto(message: &proto::GetDocumentDiagnostics) -> Result { diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index ae52ea0301..8a1ee2a88c 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -4497,7 +4497,7 @@ impl LspStore { buffer_handle: &Model, position: Anchor, cx: &mut ModelContext, - ) -> Task>> { + ) -> Task>>> { let buffer = buffer_handle.read(cx); let buffer_id = buffer.remote_id(); @@ -4933,57 +4933,6 @@ impl LspStore { } } - fn pull_diagnostic( - &mut self, - language_server_id: LanguageServerId, - buffer_handle: Model, - cx: &mut ModelContext, - ) -> Option<()> { - const PULL_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_millis(125); - - let previous_result_id = match self.as_local()?.language_servers.get(&language_server_id) { - Some(LanguageServerState::Running { - previous_document_diagnostic_result_id, - .. - }) => previous_document_diagnostic_result_id.clone(), - _ => None, - }; - - let lsp_request_task = self.request_lsp( - buffer_handle.clone(), - LanguageServerToQuery::Other(language_server_id), - GetDocumentDiagnostics { - language_server_id, - previous_result_id, - }, - cx, - ); - - let snapshot = - self.buffer_snapshot_for_lsp_version(&buffer_handle, language_server_id, None, cx); - - cx.spawn(move |_, mut cx| async move { - let snapshot = snapshot?; - - cx.background_executor() - .timer(PULL_DIAGNOSTICS_DEBOUNCE) - .await; - - let diagnostics = lsp_request_task - .await - .context("Unable to pull document diagnostic") - .unwrap_or_default(); - - buffer_handle.update(&mut cx, |buffer, cx| { - let set = DiagnosticSet::from_sorted_entries(diagnostics, &snapshot); - buffer.update_diagnostics(language_server_id, set, cx); - }) - }) - .detach(); - - None - } - pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary { let mut summary = DiagnosticSummary::default(); for (_, _, path_summary) in self.diagnostic_summaries(include_ignored, cx) { @@ -5898,6 +5847,47 @@ impl LspStore { .collect(), }) } + Some(proto::multi_lsp_query::Request::GetDocumentDiagnostics( + get_document_diagnostics, + )) => { + let get_document_diagnostics = GetDocumentDiagnostics::from_proto( + get_document_diagnostics, + this.clone(), + buffer.clone(), + cx.clone(), + ) + .await?; + + let all_diagnostics = this + .update(&mut cx, |project, cx| { + project.request_multiple_lsp_locally( + &buffer, + Some(get_document_diagnostics.position), + get_document_diagnostics, + cx, + ) + })? + .await + .into_iter(); + + this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse { + responses: all_diagnostics + .map(|lsp_diagnostic| proto::LspResponse { + response: Some( + proto::lsp_response::Response::GetDocumentDiagnosticsResponse( + GetDocumentDiagnostics::response_to_proto( + lsp_diagnostic, + project, + sender_id, + &buffer_version, + cx, + ), + ), + ), + }) + .collect(), + }) + } None => anyhow::bail!("empty multi lsp query request"), } } @@ -7318,63 +7308,6 @@ impl LspStore { .detach(); } - fn pull_diagnostic( - &mut self, - language_server_id: LanguageServerId, - buffer_handle: Model, - cx: &mut ModelContext, - ) -> Option<()> { - let buffer = buffer_handle.read(cx); - let file = File::from_dyn(buffer.file())?; - let abs_path = file.as_local()?.abs_path(cx); - let uri = lsp::Url::from_file_path(abs_path).log_err()?; - - const PULL_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_millis(125); - - let previous_result_id = match self.as_local()?.language_servers.get(&language_server_id) { - Some(LanguageServerState::Running { - previous_document_diagnostic_result_id, - .. - }) => previous_document_diagnostic_result_id.clone(), - _ => None, - }; - - let lsp_request_task = self.request_lsp( - buffer_handle, - LanguageServerToQuery::Other(language_server_id), - GetDocumentDiagnostics { - language_server_id, - previous_result_id, - }, - cx, - ); - - cx.spawn(move |this, mut cx| async move { - cx.background_executor() - .timer(PULL_DIAGNOSTICS_DEBOUNCE) - .await; - - let diagnostics = lsp_request_task.await; - this.update(&mut cx, |this, cx| { - this.update_diagnostics( - language_server_id, - lsp::PublishDiagnosticsParams { - uri: uri.clone(), - diagnostics: diagnostics.unwrap(), - version: None, - }, - &[], - cx, - ) - .log_err() - }) - .ok(); - }) - .detach(); - - None - } - pub fn update_diagnostics( &mut self, language_server_id: LanguageServerId, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 7e441cffb0..644be34360 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -3037,12 +3037,24 @@ impl Project { buffer_handle: &Model, position: Anchor, cx: &mut ModelContext, - ) -> Task>> { + ) -> Task>>> { self.lsp_store.update(cx, |lsp_store, cx| { lsp_store.document_diagnostic(buffer_handle, position, cx) }) } + pub fn update_diagnostics( + &mut self, + language_server_id: LanguageServerId, + params: lsp::PublishDiagnosticsParams, + disk_based_sources: &[String], + cx: &mut ModelContext, + ) -> Result<(), anyhow::Error> { + self.lsp_store.update(cx, |lsp_store, cx| { + lsp_store.update_diagnostics(language_server_id, params, disk_based_sources, cx) + }) + } + pub fn search( &mut self, query: SearchQuery,