From 41ca46cf8ca65dbd98df7e038fc12a272f0c9e2a Mon Sep 17 00:00:00 2001 From: Philipp Mildenberger Date: Tue, 9 Jan 2024 02:01:04 +0100 Subject: Initialize diagnostics when opening a document (#8873) --- helix-term/src/application.rs | 160 +++++++++++------------------------------- 1 file changed, 40 insertions(+), 120 deletions(-) (limited to 'helix-term/src/application.rs') diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 3abe9cae..4eda8097 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -1,14 +1,8 @@ use arc_swap::{access::Map, ArcSwap}; use futures_util::Stream; -use helix_core::{ - chars::char_is_word, - diagnostic::{DiagnosticTag, NumberOrString}, - path::get_relative_path, - pos_at_coords, syntax, Selection, -}; +use helix_core::{path::get_relative_path, pos_at_coords, syntax, Selection}; use helix_lsp::{ lsp::{self, notification::Notification}, - util::lsp_pos_to_pos, LspProgressMap, }; use helix_view::{ @@ -392,6 +386,12 @@ impl Application { self.editor.syn_loader = self.syn_loader.clone(); for document in self.editor.documents.values_mut() { document.detect_language(self.syn_loader.clone()); + let diagnostics = Editor::doc_diagnostics( + &self.editor.language_servers, + &self.editor.diagnostics, + document, + ); + document.replace_diagnostics(diagnostics, &[], None); } Ok(()) @@ -567,6 +567,14 @@ impl Application { let id = doc.id(); doc.detect_language(loader); self.editor.refresh_language_servers(id); + // and again a borrow checker workaround... + let doc = doc_mut!(self.editor, &doc_save_event.doc_id); + let diagnostics = Editor::doc_diagnostics( + &self.editor.language_servers, + &self.editor.diagnostics, + doc, + ); + doc.replace_diagnostics(diagnostics, &[], None); } // TODO: fix being overwritten by lsp @@ -731,7 +739,6 @@ impl Application { log::error!("Discarding publishDiagnostic notification sent by an uninitialized server: {}", language_server.name()); return; } - let offset_encoding = language_server.offset_encoding(); // have to inline the function because of borrow checking... let doc = self.editor.documents.values_mut() .find(|doc| doc.path().map(|p| p == &path).unwrap_or(false)) @@ -745,11 +752,10 @@ impl Application { true }); - if let Some(doc) = doc { + let mut unchanged_diag_sources = Vec::new(); + if let Some(doc) = &doc { let lang_conf = doc.language.clone(); - let text = doc.text().clone(); - let mut unchaged_diag_sources_ = Vec::new(); if let Some(lang_conf) = &lang_conf { if let Some(old_diagnostics) = self.editor.diagnostics.get(¶ms.uri) @@ -774,118 +780,11 @@ impl Application { }) .map(|(d, _)| d); if new_diagnostics.eq(old_diagnostics) { - unchaged_diag_sources_.push(source.clone()) + unchanged_diag_sources.push(source.clone()) } } } } - - let unchaged_diag_sources = &unchaged_diag_sources_; - let diagnostics = - params.diagnostics.iter().filter_map(move |diagnostic| { - use helix_core::diagnostic::{Diagnostic, Range, Severity::*}; - use lsp::DiagnosticSeverity; - - if diagnostic.source.as_ref().map_or(false, |source| { - unchaged_diag_sources.contains(source) - }) { - return None; - } - - // TODO: convert inside server - let start = if let Some(start) = lsp_pos_to_pos( - &text, - diagnostic.range.start, - offset_encoding, - ) { - start - } else { - log::warn!("lsp position out of bounds - {:?}", diagnostic); - return None; - }; - - let end = if let Some(end) = - lsp_pos_to_pos(&text, diagnostic.range.end, offset_encoding) - { - end - } else { - log::warn!("lsp position out of bounds - {:?}", diagnostic); - return None; - }; - let severity = - diagnostic.severity.map(|severity| match severity { - DiagnosticSeverity::ERROR => Error, - DiagnosticSeverity::WARNING => Warning, - DiagnosticSeverity::INFORMATION => Info, - DiagnosticSeverity::HINT => Hint, - severity => unreachable!( - "unrecognized diagnostic severity: {:?}", - severity - ), - }); - - if let Some(lang_conf) = &lang_conf { - if let Some(severity) = severity { - if severity < lang_conf.diagnostic_severity { - return None; - } - } - }; - - let code = match diagnostic.code.clone() { - Some(x) => match x { - lsp::NumberOrString::Number(x) => { - Some(NumberOrString::Number(x)) - } - lsp::NumberOrString::String(x) => { - Some(NumberOrString::String(x)) - } - }, - None => None, - }; - - let tags = if let Some(tags) = &diagnostic.tags { - let new_tags = tags - .iter() - .filter_map(|tag| match *tag { - lsp::DiagnosticTag::DEPRECATED => { - Some(DiagnosticTag::Deprecated) - } - lsp::DiagnosticTag::UNNECESSARY => { - Some(DiagnosticTag::Unnecessary) - } - _ => None, - }) - .collect(); - - new_tags - } else { - Vec::new() - }; - - let ends_at_word = start != end - && end != 0 - && text.get_char(end - 1).map_or(false, char_is_word); - let starts_at_word = start != end - && text.get_char(start).map_or(false, char_is_word); - - Some(Diagnostic { - range: Range { start, end }, - ends_at_word, - starts_at_word, - zero_width: start == end, - line: diagnostic.range.start.line as usize, - message: diagnostic.message.clone(), - severity, - code, - tags, - source: diagnostic.source.clone(), - data: diagnostic.data.clone(), - language_server_id: server_id, - }) - }); - - doc.replace_diagnostics(diagnostics, unchaged_diag_sources, server_id); } let diagnostics = params.diagnostics.into_iter().map(|d| (d, server_id)); @@ -910,6 +809,27 @@ impl Application { diagnostics.sort_unstable_by_key(|(d, server_id)| { (d.severity, d.range.start, *server_id) }); + + if let Some(doc) = doc { + let diagnostic_of_language_server_and_not_in_unchanged_sources = + |diagnostic: &lsp::Diagnostic, ls_id| { + ls_id == server_id + && diagnostic.source.as_ref().map_or(true, |source| { + !unchanged_diag_sources.contains(source) + }) + }; + let diagnostics = Editor::doc_diagnostics_with_filter( + &self.editor.language_servers, + &self.editor.diagnostics, + doc, + diagnostic_of_language_server_and_not_in_unchanged_sources, + ); + doc.replace_diagnostics( + diagnostics, + &unchanged_diag_sources, + Some(server_id), + ); + } } Notification::ShowMessage(params) => { log::warn!("unhandled window/showMessage: {:?}", params); @@ -1017,7 +937,7 @@ impl Application { // Clear any diagnostics for documents with this server open. for doc in self.editor.documents_mut() { - doc.clear_diagnostics(server_id); + doc.clear_diagnostics(Some(server_id)); } // Remove the language server from the registry. -- cgit v1.2.3-70-g09d2