From baf636a4a427006bede32743ba8477d55f8b7efb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 3 Nov 2021 13:49:39 -0700 Subject: [PATCH] Extend empty diagnostic ranges at the ends of lines --- crates/language/src/lib.rs | 4 ++ crates/language/src/tests.rs | 89 ++++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/crates/language/src/lib.rs b/crates/language/src/lib.rs index a4ac497776..58f0ecad64 100644 --- a/crates/language/src/lib.rs +++ b/crates/language/src/lib.rs @@ -751,6 +751,10 @@ impl Buffer { if range.start == range.end { range.end.column += 1; range.end = content.clip_point_utf16(range.end, Bias::Right); + if range.start == range.end && range.end.column > 0 { + range.start.column -= 1; + range.start = content.clip_point_utf16(range.start, Bias::Left); + } } Some(( range, diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index b8dfbdfd50..b83fb4c671 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -633,24 +633,83 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { ] ); }); +} - fn chunks_with_diagnostics( - buffer: &Buffer, - range: Range, - ) -> Vec<(String, Option)> { - let mut chunks: Vec<(String, Option)> = Vec::new(); - for chunk in buffer.snapshot().highlighted_text_for_range(range) { - if chunks - .last() - .map_or(false, |prev_chunk| prev_chunk.1 == chunk.diagnostic) - { - chunks.last_mut().unwrap().0.push_str(chunk.text); - } else { - chunks.push((chunk.text.to_string(), chunk.diagnostic)); - } +#[gpui::test] +async fn test_empty_diagnostic_ranges(mut cx: gpui::TestAppContext) { + cx.add_model(|cx| { + let text = concat!( + "let one = ;\n", // + "let two = \n", + "let three = 3;\n", + ); + + let mut buffer = Buffer::new(0, text, cx); + buffer.set_language(Some(Arc::new(rust_lang())), None, cx); + buffer + .update_diagnostics( + None, + vec![ + lsp::Diagnostic { + range: lsp::Range::new( + lsp::Position::new(0, 10), + lsp::Position::new(0, 10), + ), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "syntax error 1".to_string(), + ..Default::default() + }, + lsp::Diagnostic { + range: lsp::Range::new( + lsp::Position::new(1, 10), + lsp::Position::new(1, 10), + ), + severity: Some(lsp::DiagnosticSeverity::ERROR), + message: "syntax error 2".to_string(), + ..Default::default() + }, + ], + cx, + ) + .unwrap(); + + // An empty range is extended forward to include the following character. + // At the end of a line, an empty range is extended backward to include + // the preceding character. + let chunks = chunks_with_diagnostics(&buffer, 0..buffer.len()); + assert_eq!( + chunks + .iter() + .map(|(s, d)| (s.as_str(), *d)) + .collect::>(), + &[ + ("let one = ", None), + (";", Some(lsp::DiagnosticSeverity::ERROR)), + ("\nlet two =", None), + (" ", Some(lsp::DiagnosticSeverity::ERROR)), + ("\nlet three = 3;\n", None) + ] + ); + buffer + }); +} + +fn chunks_with_diagnostics( + buffer: &Buffer, + range: Range, +) -> Vec<(String, Option)> { + let mut chunks: Vec<(String, Option)> = Vec::new(); + for chunk in buffer.snapshot().highlighted_text_for_range(range) { + if chunks + .last() + .map_or(false, |prev_chunk| prev_chunk.1 == chunk.diagnostic) + { + chunks.last_mut().unwrap().0.push_str(chunk.text); + } else { + chunks.push((chunk.text.to_string(), chunk.diagnostic)); } - chunks } + chunks } #[test]