Skip to content

Commit

Permalink
Add config to mark diagnostic sources as persistent
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalkuthe committed Mar 26, 2023
1 parent f9a25a7 commit a80ec1c
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 21 deletions.
2 changes: 2 additions & 0 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ pub struct LanguageConfiguration {
pub auto_pairs: Option<AutoPairs>,

pub rulers: Option<Vec<u16>>, // if set, override editor's rulers
#[serde(default)]
pub persistant_diagnostic_sources: Vec<String>,
}

#[derive(Debug, PartialEq, Eq, Hash)]
Expand Down
59 changes: 43 additions & 16 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,13 @@ impl Application {
}
}
Notification::PublishDiagnostics(mut params) => {
// Sort diagnostics first by severity and then by line numbers.
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
params
.diagnostics
.sort_unstable_by_key(|d| (d.severity, d.range.start));
let old_diagnostics = self.editor.diagnostics.remove(&params.uri);

let path = match params.uri.to_file_path() {
Ok(path) => path,
Err(_) => {
Expand All @@ -721,17 +728,43 @@ impl Application {
});

if let Some(doc) = doc {
let lang_conf = doc.language_config();
let text = doc.text();
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) = old_diagnostics {
for source in &lang_conf.persistant_diagnostic_sources {
let new_diagnostics = params
.diagnostics
.iter()
.filter(|it| it.source.as_ref() == Some(source));
let old_diagnostics = old_diagnostics
.iter()
.filter(|it| it.source.as_ref() == Some(source));
if new_diagnostics.eq(old_diagnostics) {
unchaged_diag_sources_.push(source.clone())
}
}
}
}

let unchaged_diag_sources = &unchaged_diag_sources_;
let language_server = doc.language_server.clone();
let diagnostics = params
.diagnostics
.iter()
.filter_map(|diagnostic| {
.filter_map(move |diagnostic| {
use helix_core::diagnostic::{Diagnostic, Range, Severity::*};
use lsp::DiagnosticSeverity;

let language_server = if let Some(language_server) = doc.language_server() {
if let Some(source) = &diagnostic.source{
if unchaged_diag_sources.contains(source){
return None;
}
}

let language_server = if let Some(language_server) = &language_server {
language_server
} else {
log::warn!("Discarding diagnostic because language server is not initialized: {:?}", diagnostic);
Expand All @@ -740,7 +773,7 @@ impl Application {

// TODO: convert inside server
let start = if let Some(start) = lsp_pos_to_pos(
text,
&text,
diagnostic.range.start,
language_server.offset_encoding(),
) {
Expand All @@ -751,7 +784,7 @@ impl Application {
};

let end = if let Some(end) = lsp_pos_to_pos(
text,
&text,
diagnostic.range.end,
language_server.offset_encoding(),
) {
Expand All @@ -773,7 +806,7 @@ impl Application {
),
});

if let Some(lang_conf) = lang_conf {
if let Some(lang_conf) = &lang_conf {
if let Some(severity) = severity {
if severity < lang_conf.diagnostic_severity {
return None;
Expand Down Expand Up @@ -817,17 +850,11 @@ impl Application {
source: diagnostic.source.clone(),
data: diagnostic.data.clone(),
})
})
.collect();
});

doc.set_diagnostics(diagnostics);
doc.set_diagnostics(diagnostics, unchaged_diag_sources);
}

// Sort diagnostics first by severity and then by line numbers.
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
params
.diagnostics
.sort_unstable_by_key(|d| (d.severity, d.range.start));

// 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.
Expand Down Expand Up @@ -939,7 +966,7 @@ impl Application {
if doc.language_server().map(|server| server.id())
== Some(server_id)
{
doc.set_diagnostics(Vec::new());
doc.set_diagnostics([], &[]);
doc.url()
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,7 @@ fn lsp_stop(
for doc in cx.editor.documents_mut() {
if doc.language_server().map_or(false, |ls| ls.id() == ls_id) {
doc.set_language_server(None);
doc.set_diagnostics(Default::default());
doc.set_diagnostics([], &[]);
}
}

Expand Down
23 changes: 19 additions & 4 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub struct Document {

syntax: Option<Syntax>,
/// Corresponding language scope name. Usually `source.<lang>`.
pub(crate) language: Option<Arc<LanguageConfiguration>>,
pub language: Option<Arc<LanguageConfiguration>>,

/// Pending changes since last history commit.
changes: ChangeSet,
Expand All @@ -165,7 +165,7 @@ pub struct Document {
pub(crate) modified_since_accessed: bool,

diagnostics: Vec<Diagnostic>,
language_server: Option<Arc<helix_lsp::Client>>,
pub language_server: Option<Arc<helix_lsp::Client>>,

diff_handle: Option<DiffHandle>,
version_control_head: Option<Arc<ArcSwap<Box<str>>>>,
Expand Down Expand Up @@ -1385,8 +1385,23 @@ impl Document {
&self.diagnostics
}

pub fn set_diagnostics(&mut self, diagnostics: Vec<Diagnostic>) {
self.diagnostics = diagnostics;
pub fn set_diagnostics(
&mut self,
diagnostics: impl IntoIterator<Item = Diagnostic>,
unchanged_sources: &[String],
) {
if unchanged_sources.is_empty() {
self.diagnostics.clear()
} else {
self.diagnostics.retain(|diagnostic| {
if let Some(source) = &diagnostic.source {
unchanged_sources.contains(source)
} else {
false
}
});
}
self.diagnostics.extend(diagnostics);
self.diagnostics
.sort_unstable_by_key(|diagnostic| diagnostic.range);
}
Expand Down
1 change: 1 addition & 0 deletions languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ auto-format = true
comment-token = "//"
language-server = { command = "rust-analyzer" }
indent = { tab-width = 4, unit = " " }
persistant-diagnostic-sources = ["rustc", "clippy"]

[language.auto-pairs]
'(' = ')'
Expand Down

0 comments on commit a80ec1c

Please sign in to comment.