Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--helix-term/src/ui/editor.rs78
1 files changed, 55 insertions, 23 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index ad7aa5c5..97a08beb 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -359,8 +359,8 @@ impl EditorView {
pub fn doc_diagnostics_highlights(
doc: &Document,
theme: &Theme,
- ) -> [Vec<(usize, std::ops::Range<usize>)>; 5] {
- use helix_core::diagnostic::{DiagnosticTag, Severity};
+ ) -> [Vec<(usize, std::ops::Range<usize>)>; 7] {
+ use helix_core::diagnostic::{DiagnosticTag, Range, Severity};
let get_scope_of = |scope| {
theme
.find_scope_index_exact(scope)
@@ -389,6 +389,25 @@ impl EditorView {
let mut hint_vec = Vec::new();
let mut warning_vec = Vec::new();
let mut error_vec = Vec::new();
+ let mut unnecessary_vec = Vec::new();
+ let mut deprecated_vec = Vec::new();
+
+ let push_diagnostic =
+ |vec: &mut Vec<(usize, std::ops::Range<usize>)>, scope, range: Range| {
+ // If any diagnostic overlaps ranges with the prior diagnostic,
+ // merge the two together. Otherwise push a new span.
+ match vec.last_mut() {
+ Some((_, existing_range)) if range.start <= existing_range.end => {
+ // This branch merges overlapping diagnostics, assuming that the current
+ // diagnostic starts on range.start or later. If this assertion fails,
+ // we will discard some part of `diagnostic`. This implies that
+ // `doc.diagnostics()` is not sorted by `diagnostic.range`.
+ debug_assert!(existing_range.start <= range.start);
+ existing_range.end = range.end.max(existing_range.end)
+ }
+ _ => vec.push((scope, range.start..range.end)),
+ }
+ };
for diagnostic in doc.diagnostics() {
// Separate diagnostics into different Vecs by severity.
@@ -400,31 +419,44 @@ impl EditorView {
_ => (&mut default_vec, r#default),
};
- let scope = diagnostic
- .tags
- .first()
- .and_then(|tag| match tag {
- DiagnosticTag::Unnecessary => unnecessary,
- DiagnosticTag::Deprecated => deprecated,
- })
- .unwrap_or(scope);
-
- // If any diagnostic overlaps ranges with the prior diagnostic,
- // merge the two together. Otherwise push a new span.
- match vec.last_mut() {
- Some((_, range)) if diagnostic.range.start <= range.end => {
- // This branch merges overlapping diagnostics, assuming that the current
- // diagnostic starts on range.start or later. If this assertion fails,
- // we will discard some part of `diagnostic`. This implies that
- // `doc.diagnostics()` is not sorted by `diagnostic.range`.
- debug_assert!(range.start <= diagnostic.range.start);
- range.end = diagnostic.range.end.max(range.end)
+ // If the diagnostic has tags and a non-warning/error severity, skip rendering
+ // the diagnostic as info/hint/default and only render it as unnecessary/deprecated
+ // instead. For warning/error diagnostics, render both the severity highlight and
+ // the tag highlight.
+ if diagnostic.tags.is_empty()
+ || matches!(
+ diagnostic.severity,
+ Some(Severity::Warning | Severity::Error)
+ )
+ {
+ push_diagnostic(vec, scope, diagnostic.range);
+ }
+
+ for tag in &diagnostic.tags {
+ match tag {
+ DiagnosticTag::Unnecessary => {
+ if let Some(scope) = unnecessary {
+ push_diagnostic(&mut unnecessary_vec, scope, diagnostic.range)
+ }
+ }
+ DiagnosticTag::Deprecated => {
+ if let Some(scope) = deprecated {
+ push_diagnostic(&mut deprecated_vec, scope, diagnostic.range)
+ }
+ }
}
- _ => vec.push((scope, diagnostic.range.start..diagnostic.range.end)),
}
}
- [default_vec, info_vec, hint_vec, warning_vec, error_vec]
+ [
+ default_vec,
+ unnecessary_vec,
+ deprecated_vec,
+ info_vec,
+ hint_vec,
+ warning_vec,
+ error_vec,
+ ]
}
/// Get highlight spans for selections in a document view.