Skip to content

Commit

Permalink
Merge branch 'pull-diagnostics' of https://github.com/SofusA/helix in…
Browse files Browse the repository at this point in the history
…to pull-diagnostics
  • Loading branch information
SofusA committed Aug 3, 2024
2 parents d8fd204 + 009f414 commit dcd4d45
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 43 deletions.
76 changes: 43 additions & 33 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use helix_view::{
graphics::Rect,
theme,
tree::Layout,
Align, Editor,
Align, Document, Editor,
};
use serde_json::json;
use tui::backend::Backend;
Expand Down Expand Up @@ -737,7 +737,7 @@ impl Application {
));
}
}
Notification::PublishDiagnostics(mut params) => {
Notification::PublishDiagnostics(params) => {
let uri = match helix_core::Uri::try_from(params.uri) {
Ok(uri) => uri,
Err(err) => {
Expand All @@ -763,41 +763,24 @@ impl Application {
true
});

let diagnostics: Vec<(lsp::Diagnostic, LanguageServerId)> = params
.diagnostics
.into_iter()
.map(|d| (d, server_id))
.collect();

let mut unchanged_diag_sources = Vec::new();
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 !lang_conf.persistent_diagnostic_sources.is_empty() {
// Sort diagnostics first by severity and then by line numbers.
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
params
.diagnostics
.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())
}
}
}
if let Some(old_diagnostics) = self.editor.diagnostics.get(&uri) {
unchanged_diag_sources = get_unchanged_diagnostic_sources(
doc,
&diagnostics,
old_diagnostics,
server_id,
);
}
}

let diagnostics = params.diagnostics.into_iter().map(|d| (d, server_id));

// 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.
// When using them later in the diagnostics picker, we calculate them on-demand.
Expand All @@ -810,7 +793,7 @@ impl Application {
current_diagnostics
// 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.
Expand Down Expand Up @@ -1257,3 +1240,30 @@ impl Application {
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
}
39 changes: 29 additions & 10 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use futures_util::{stream::FuturesOrdered, FutureExt};
use helix_lsp::{
block_on,
lsp::{
self, CodeAction, CodeActionOrCommand, CodeActionTriggerKind, DiagnosticSeverity,
NumberOrString,
self, CodeAction, CodeActionOrCommand, CodeActionTriggerKind, Diagnostic,
DiagnosticSeverity, NumberOrString,
},
util::{diagnostic_to_lsp_diagnostic, lsp_range_to_range, range_to_lsp_range},
Client, LanguageServerId, OffsetEncoding,
Expand All @@ -26,6 +26,7 @@ use helix_view::{
};

use crate::{
application::get_unchanged_diagnostic_sources,
compositor::{self, Compositor},
job::Callback,
ui::{self, overlay::overlaid, FileLocation, Picker, Popup, PromptEvent},
Expand All @@ -36,7 +37,7 @@ use std::{
collections::{btree_map::Entry, BTreeMap, HashMap, HashSet},
fmt::{Display, Write},
future::Future,
path::Path,
path::{Path, PathBuf},
};

/// Gets the first language server that is attached to a document which supports a specific feature.
Expand Down Expand Up @@ -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 parse_diagnostic = |editor: &mut Editor,
path,
path: PathBuf,
report: Vec<lsp::Diagnostic>,
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) {
let diagnostics: Vec<helix_core::Diagnostic> = report
let new_diagnostics: Vec<helix_core::Diagnostic> = diagnostics
.iter()
.map(|d| {
Document::lsp_diagnostic_to_diagnostic(
doc.text(),
doc.language_config(),
d,
&d.0,
server_id,
offset_encoding,
)
Expand All @@ -1478,13 +1485,25 @@ pub fn pull_diagnostic_for_current_doc(editor: &Editor, jobs: &mut crate::job::J
.collect();

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
let mut diagnostics = report.into_iter().map(|d| (d, server_id)).collect();
match editor.diagnostics.entry(uri) {
Entry::Occupied(o) => {
let current_diagnostics = o.into_mut();
Expand Down

0 comments on commit dcd4d45

Please sign in to comment.