From 515ef17207878b78e4f5eda8bf710fa0aa1eae87 Mon Sep 17 00:00:00 2001 From: Pascal Kuthe Date: Sun, 26 Mar 2023 18:14:42 +0200 Subject: make diagnostics stick to word boundaries Diagnostics are currently extended if text is inserted at their end. This is desirable when inserting text after an identifier. For example consider: let foo = 2; --- unused variable Renaming the identifier should extend the diagnostic: let foobar = 2; ------ unused variable This is currently implemented in helix but as a consequence adding whitespaces or a type hint also extends the diagnostic: let foo = 2; -------- unused variable let foo: Bar = 2; -------- unused variable In these cases the diagnostic should remain unchanged: let foo = 2; --- unused variable let foo: Bar = 2; --- unused variable As a heuristic helix will now only extend diagnostics that end on a word char if new chars are appended to the word (so not for punctuation/ whitespace). The idea for this mapping was inspired for the word level tracking vscode uses for many positions. While VSCode doesn't currently update diagnostics after receiving publishDiagnostic it does use this system for inlay hints for example. Similarly, the new association mechanism implemented here can be used for word level tracking of inlay hints. A similar mapping function is implemented for word starts. Together these can be used to make a diagnostic stick to a word. If that word is removed that diagnostic is automatically removed too. This is the exact same behavior VSCode inlay hints eixibit. --- helix-term/src/application.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'helix-term') diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 35111ca5..2dd97b42 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -1,6 +1,7 @@ use arc_swap::{access::Map, ArcSwap}; use futures_util::Stream; use helix_core::{ + chars::char_is_word, diagnostic::{DiagnosticTag, NumberOrString}, path::get_relative_path, pos_at_coords, syntax, Selection, @@ -811,7 +812,6 @@ impl Application { log::warn!("lsp position out of bounds - {:?}", diagnostic); return None; }; - let severity = diagnostic.severity.map(|severity| match severity { DiagnosticSeverity::ERROR => Error, @@ -863,8 +863,17 @@ impl Application { Vec::new() }; + let ends_at_word = start != end + && end != 0 + && text.get_char(end - 1).map_or(false, char_is_word); + let starts_at_word = start != end + && text.get_char(start).map_or(false, char_is_word); + Some(Diagnostic { range: Range { start, end }, + ends_at_word, + starts_at_word, + zero_width: start == end, line: diagnostic.range.start.line as usize, message: diagnostic.message.clone(), severity, -- cgit v1.2.3-70-g09d2