Merge branch 'pull-diagnostics' of https://github.com/SofusA/helix into pull-diagnostics

pull/11315/head
Sofus Addington 4 months ago
commit dcd4d45a45

@ -15,7 +15,7 @@ use helix_view::{
graphics::Rect, graphics::Rect,
theme, theme,
tree::Layout, tree::Layout,
Align, Editor, Align, Document, Editor,
}; };
use serde_json::json; use serde_json::json;
use tui::backend::Backend; use tui::backend::Backend;
@ -737,7 +737,7 @@ impl Application {
)); ));
} }
} }
Notification::PublishDiagnostics(mut params) => { Notification::PublishDiagnostics(params) => {
let uri = match helix_core::Uri::try_from(params.uri) { let uri = match helix_core::Uri::try_from(params.uri) {
Ok(uri) => uri, Ok(uri) => uri,
Err(err) => { Err(err) => {
@ -763,41 +763,24 @@ impl Application {
true true
}); });
let diagnostics: Vec<(lsp::Diagnostic, LanguageServerId)> = params
.diagnostics
.into_iter()
.map(|d| (d, server_id))
.collect();
let mut unchanged_diag_sources = Vec::new(); let mut unchanged_diag_sources = Vec::new();
if let Some(doc) = &doc { if let Some(doc) = &doc {
let lang_conf = doc.language.clone();
if let Some(lang_conf) = &lang_conf {
if let Some(old_diagnostics) = self.editor.diagnostics.get(&uri) { if let Some(old_diagnostics) = self.editor.diagnostics.get(&uri) {
if !lang_conf.persistent_diagnostic_sources.is_empty() { unchanged_diag_sources = get_unchanged_diagnostic_sources(
// Sort diagnostics first by severity and then by line numbers. doc,
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order &diagnostics,
params old_diagnostics,
.diagnostics server_id,
.sort_by_key(|d| (d.severity, d.range.start)); );
}
for source in &lang_conf.persistent_diagnostic_sources {
let new_diagnostics = params
.diagnostics
.iter()
.filter(|d| d.source.as_ref() == Some(source));
let old_diagnostics = old_diagnostics
.iter()
.filter(|(d, d_server)| {
*d_server == server_id
&& d.source.as_ref() == Some(source)
})
.map(|(d, _)| d);
if new_diagnostics.eq(old_diagnostics) {
unchanged_diag_sources.push(source.clone())
}
}
}
} }
} }
let diagnostics = params.diagnostics.into_iter().map(|d| (d, server_id));
// Insert the original lsp::Diagnostics here because we may have no open document // Insert the original lsp::Diagnostics here because we may have no open document
// for diagnosic message and so we can't calculate the exact position. // for diagnosic message and so we can't calculate the exact position.
// When using them later in the diagnostics picker, we calculate them on-demand. // When using them later in the diagnostics picker, we calculate them on-demand.
@ -810,7 +793,7 @@ impl Application {
current_diagnostics current_diagnostics
// Sort diagnostics first by severity and then by line numbers. // Sort diagnostics first by severity and then by line numbers.
} }
Entry::Vacant(v) => v.insert(diagnostics.collect()), Entry::Vacant(v) => v.insert(diagnostics),
}; };
// Sort diagnostics first by severity and then by line numbers. // Sort diagnostics first by severity and then by line numbers.
@ -1257,3 +1240,30 @@ impl Application {
errs errs
} }
} }
pub fn get_unchanged_diagnostic_sources(
doc: &Document,
diagnostics: &[(lsp::Diagnostic, LanguageServerId)],
old_diagnostics: &[(lsp::Diagnostic, LanguageServerId)],
server_id: LanguageServerId,
) -> Vec<String> {
let mut unchanged_diag_sources = Vec::new();
let lang_conf = doc.language.clone();
if let Some(lang_conf) = &lang_conf {
for source in &lang_conf.persistent_diagnostic_sources {
let new_diagnostics = diagnostics
.iter()
.filter(|d| d.0.source.as_ref() == Some(source));
let old_diagnostics = old_diagnostics
.iter()
.filter(|(d, d_server)| *d_server == server_id && d.source.as_ref() == Some(source))
.map(|(d, _)| d);
if new_diagnostics.map(|x| &x.0).eq(old_diagnostics) {
unchanged_diag_sources.push(source.clone())
}
}
}
unchanged_diag_sources
}

@ -2,8 +2,8 @@ use futures_util::{stream::FuturesOrdered, FutureExt};
use helix_lsp::{ use helix_lsp::{
block_on, block_on,
lsp::{ lsp::{
self, CodeAction, CodeActionOrCommand, CodeActionTriggerKind, DiagnosticSeverity, self, CodeAction, CodeActionOrCommand, CodeActionTriggerKind, Diagnostic,
NumberOrString, DiagnosticSeverity, NumberOrString,
}, },
util::{diagnostic_to_lsp_diagnostic, lsp_range_to_range, range_to_lsp_range}, util::{diagnostic_to_lsp_diagnostic, lsp_range_to_range, range_to_lsp_range},
Client, LanguageServerId, OffsetEncoding, Client, LanguageServerId, OffsetEncoding,
@ -26,6 +26,7 @@ use helix_view::{
}; };
use crate::{ use crate::{
application::get_unchanged_diagnostic_sources,
compositor::{self, Compositor}, compositor::{self, Compositor},
job::Callback, job::Callback,
ui::{self, overlay::overlaid, FileLocation, Picker, Popup, PromptEvent}, ui::{self, overlay::overlaid, FileLocation, Picker, Popup, PromptEvent},
@ -36,7 +37,7 @@ use std::{
collections::{btree_map::Entry, BTreeMap, HashMap, HashSet}, collections::{btree_map::Entry, BTreeMap, HashMap, HashSet},
fmt::{Display, Write}, fmt::{Display, Write},
future::Future, future::Future,
path::Path, path::{Path, PathBuf},
}; };
/// Gets the first language server that is attached to a document which supports a specific feature. /// Gets the first language server that is attached to a document which supports a specific feature.
@ -1459,17 +1460,23 @@ pub fn pull_diagnostic_for_current_doc(editor: &Editor, jobs: &mut crate::job::J
let server_id = language_server.id(); let server_id = language_server.id();
let parse_diagnostic = |editor: &mut Editor, let parse_diagnostic = |editor: &mut Editor,
path, path: PathBuf,
report: Vec<lsp::Diagnostic>, report: Vec<lsp::Diagnostic>,
result_id: Option<String>| { result_id: Option<String>| {
let uri = helix_core::Uri::try_from(path.clone()).unwrap();
let mut diagnostics: Vec<(Diagnostic, LanguageServerId)> =
report.into_iter().map(|d| (d, server_id)).collect();
let old_diagnostics = editor.diagnostics.get(&uri).cloned();
if let Some(doc) = editor.document_by_path_mut(&path) { if let Some(doc) = editor.document_by_path_mut(&path) {
let diagnostics: Vec<helix_core::Diagnostic> = report let new_diagnostics: Vec<helix_core::Diagnostic> = diagnostics
.iter() .iter()
.map(|d| { .map(|d| {
Document::lsp_diagnostic_to_diagnostic( Document::lsp_diagnostic_to_diagnostic(
doc.text(), doc.text(),
doc.language_config(), doc.language_config(),
d, &d.0,
server_id, server_id,
offset_encoding, offset_encoding,
) )
@ -1478,13 +1485,25 @@ pub fn pull_diagnostic_for_current_doc(editor: &Editor, jobs: &mut crate::job::J
.collect(); .collect();
doc.previous_diagnostic_id = result_id; doc.previous_diagnostic_id = result_id;
// TODO: Should i get unchanged_sources?
doc.replace_diagnostics(diagnostics, &[], Some(server_id)); let mut unchanged_diag_sources = Vec::new();
if let Some(old_diagnostics) = old_diagnostics {
unchanged_diag_sources = get_unchanged_diagnostic_sources(
doc,
&diagnostics,
&old_diagnostics,
server_id,
);
}
doc.replace_diagnostics(
new_diagnostics,
&unchanged_diag_sources,
Some(server_id),
);
} }
let uri = helix_core::Uri::try_from(path).unwrap();
// TODO: Maybe share code with application.rs:802 // TODO: Maybe share code with application.rs:802
let mut diagnostics = report.into_iter().map(|d| (d, server_id)).collect();
match editor.diagnostics.entry(uri) { match editor.diagnostics.entry(uri) {
Entry::Occupied(o) => { Entry::Occupied(o) => {
let current_diagnostics = o.into_mut(); let current_diagnostics = o.into_mut();

Loading…
Cancel
Save