summaryrefslogtreecommitdiff
path: root/helix-term/src/application.rs
diff options
context:
space:
mode:
authorPascal Kuthe2023-03-26 16:10:09 +0000
committerBlaž Hrastnik2023-12-27 06:28:14 +0000
commit8653e1b02f6193330f8b0f2afff0a2ff103bd6a4 (patch)
treef6a04a6e55b437359d77a8d857e803593c625ef3 /helix-term/src/application.rs
parentc874a896a5151043a5cd7336e12ebc3a928fc677 (diff)
Add config to mark diagnostic sources as persistent
Diffstat (limited to 'helix-term/src/application.rs')
-rw-r--r--helix-term/src/application.rs105
1 files changed, 68 insertions, 37 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index ed085749..35111ca5 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -717,7 +717,7 @@ impl Application {
));
}
}
- Notification::PublishDiagnostics(params) => {
+ Notification::PublishDiagnostics(mut params) => {
let path = match params.uri.to_file_path() {
Ok(path) => path,
Err(_) => {
@@ -731,31 +731,69 @@ impl Application {
return;
}
let offset_encoding = language_server.offset_encoding();
- let doc = self.editor.document_by_path_mut(&path).filter(|doc| {
- if let Some(version) = params.version {
- if version != doc.version() {
- log::info!("Version ({version}) is out of date for {path:?} (expected ({}), dropping PublishDiagnostic notification", doc.version());
- return false;
+ // 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))
+ .filter(|doc| {
+ if let Some(version) = params.version {
+ if version != doc.version() {
+ log::info!("Version ({version}) is out of date for {path:?} (expected ({}), dropping PublishDiagnostic notification", doc.version());
+ return false;
+ }
}
- }
-
- true
- });
+ true
+ });
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) =
+ self.editor.diagnostics.get(&params.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_unstable_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) {
+ unchaged_diag_sources_.push(source.clone())
+ }
+ }
+ }
+ }
- let diagnostics = params
- .diagnostics
- .iter()
- .filter_map(|diagnostic| {
+ 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,
+ &text,
diagnostic.range.start,
offset_encoding,
) {
@@ -766,7 +804,7 @@ impl Application {
};
let end = if let Some(end) =
- lsp_pos_to_pos(text, diagnostic.range.end, offset_encoding)
+ lsp_pos_to_pos(&text, diagnostic.range.end, offset_encoding)
{
end
} else {
@@ -786,7 +824,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;
@@ -836,38 +874,31 @@ impl Application {
data: diagnostic.data.clone(),
language_server_id: server_id,
})
- })
- .collect();
+ });
- doc.replace_diagnostics(diagnostics, server_id);
+ doc.replace_diagnostics(diagnostics, unchaged_diag_sources, server_id);
}
- let mut diagnostics = params
- .diagnostics
- .into_iter()
- .map(|d| (d, server_id))
- .collect();
+ 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.
- match self.editor.diagnostics.entry(params.uri) {
+ let diagnostics = match self.editor.diagnostics.entry(params.uri) {
Entry::Occupied(o) => {
let current_diagnostics = o.into_mut();
// there may entries of other language servers, which is why we can't overwrite the whole entry
current_diagnostics.retain(|(_, lsp_id)| *lsp_id != server_id);
- current_diagnostics.append(&mut diagnostics);
- // Sort diagnostics first by severity and then by line numbers.
- // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
+ current_diagnostics.extend(diagnostics);
current_diagnostics
- .sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
- }
- Entry::Vacant(v) => {
- diagnostics
- .sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
- v.insert(diagnostics);
+ // Sort diagnostics first by severity and then by line numbers.
}
+ Entry::Vacant(v) => v.insert(diagnostics.collect()),
};
+
+ // Sort diagnostics first by severity and then by line numbers.
+ // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
+ diagnostics.sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
}
Notification::ShowMessage(params) => {
log::warn!("unhandled window/showMessage: {:?}", params);