From 91a7bbbba2e4229641edba0175e8494bad35028b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 9 Dec 2021 17:53:08 +0100 Subject: [PATCH] Fix some of the diagnostic tests and make DiagnosticEntry generic Co-Authored-By: Nathan Sobo --- crates/editor/src/editor.rs | 39 +++---- crates/editor/src/items.rs | 11 +- crates/language/src/buffer.rs | 61 +++++++---- crates/language/src/diagnostic_set.rs | 54 +++++++--- crates/language/src/language.rs | 1 + crates/language/src/proto.rs | 6 +- crates/language/src/tests.rs | 150 ++++++++++++-------------- crates/project/src/worktree.rs | 13 ++- crates/server/src/rpc.rs | 21 ++-- 9 files changed, 189 insertions(+), 167 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 497fbb2e83..e913174199 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2825,14 +2825,13 @@ impl Editor { loop { let next_group = buffer - .diagnostics_in_range(search_start..buffer.len()) + .diagnostics_in_range::<_, usize>(search_start..buffer.len()) .find_map(|entry| { - let range = entry.range.to_offset(buffer); if entry.diagnostic.is_primary - && !range.is_empty() - && Some(range.end) != active_primary_range.as_ref().map(|r| *r.end()) + && !entry.range.is_empty() + && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end()) { - Some((range, entry.diagnostic.group_id)) + Some((entry.range, entry.diagnostic.group_id)) } else { None } @@ -2866,12 +2865,11 @@ impl Editor { let buffer = self.buffer.read(cx); let primary_range_start = active_diagnostics.primary_range.start.to_offset(buffer); let is_valid = buffer - .diagnostics_in_range(active_diagnostics.primary_range.clone()) + .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone()) .any(|entry| { - let range = entry.range.to_offset(buffer); entry.diagnostic.is_primary - && !range.is_empty() - && range.start == primary_range_start + && !entry.range.is_empty() + && entry.range.start == primary_range_start && entry.diagnostic.message == active_diagnostics.primary_message }); @@ -2902,17 +2900,16 @@ impl Editor { let mut primary_message = None; let mut group_end = Point::zero(); let diagnostic_group = buffer - .diagnostic_group(group_id) + .diagnostic_group::(group_id) .map(|entry| { - let range = entry.range.to_point(buffer); - if range.end > group_end { - group_end = range.end; + if entry.range.end > group_end { + group_end = entry.range.end; } if entry.diagnostic.is_primary { - primary_range = Some(range.clone()); + primary_range = Some(entry.range.clone()); primary_message = Some(entry.diagnostic.message.clone()); } - (range, entry.diagnostic.clone()) + entry }) .collect::>(); let primary_range = primary_range.unwrap(); @@ -2922,13 +2919,13 @@ impl Editor { let blocks = display_map .insert_blocks( - diagnostic_group.iter().map(|(range, diagnostic)| { + diagnostic_group.iter().map(|entry| { let build_settings = self.build_settings.clone(); - let diagnostic = diagnostic.clone(); + let diagnostic = entry.diagnostic.clone(); let message_height = diagnostic.message.lines().count() as u8; BlockProperties { - position: range.start, + position: entry.range.start, height: message_height, render: Arc::new(move |cx| { let settings = build_settings.borrow()(cx.cx); @@ -2941,11 +2938,7 @@ impl Editor { cx, ) .into_iter() - .zip( - diagnostic_group - .into_iter() - .map(|(_, diagnostic)| diagnostic), - ) + .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic)) .collect(); Some(ActiveDiagnosticGroup { diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 061aece652..7fa25eb884 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -5,7 +5,7 @@ use gpui::{ MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakModelHandle, }; -use language::{AnchorRangeExt, Buffer, Diagnostic, File as _}; +use language::{Buffer, Diagnostic, File as _}; use postage::watch; use project::{ProjectPath, Worktree}; use std::fmt::Write; @@ -317,11 +317,10 @@ impl DiagnosticMessage { let cursor_position = editor.newest_selection::(cx).head(); let buffer = editor.buffer().read(cx); let new_diagnostic = buffer - .diagnostics_in_range(cursor_position..cursor_position) - .map(|entry| (entry.range.to_offset(buffer), &entry.diagnostic)) - .filter(|(range, _)| !range.is_empty()) - .min_by_key(|(range, diagnostic)| (diagnostic.severity, range.len())) - .map(|(_, diagnostic)| diagnostic.clone()); + .diagnostics_in_range::<_, usize>(cursor_position..cursor_position) + .filter(|entry| !entry.range.is_empty()) + .min_by_key(|entry| (entry.diagnostic.severity, entry.range.len())) + .map(|entry| entry.diagnostic); if new_diagnostic != self.diagnostic { self.diagnostic = new_diagnostic; cx.notify(); diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 99239a3089..d34528c784 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -23,6 +23,7 @@ use std::{ ffi::OsString, future::Future, iter::{Iterator, Peekable}, + mem, ops::{Deref, DerefMut, Range}, path::{Path, PathBuf}, str, @@ -109,7 +110,7 @@ struct LanguageServerSnapshot { pub enum Operation { Buffer(text::Operation), UpdateDiagnostics { - diagnostics: Arc<[DiagnosticEntry]>, + diagnostics: Arc<[DiagnosticEntry]>, lamport_timestamp: clock::Lamport, }, } @@ -781,29 +782,33 @@ impl Buffer { diagnostics_by_group_id .entry(group_id) .or_insert(Vec::new()) - .push(( + .push(DiagnosticEntry { range, - Diagnostic { + diagnostic: Diagnostic { severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR), message: diagnostic.message.clone(), group_id, is_primary: false, }, - )); + }); } drop(edits_since_save); - self.diagnostics - .reset( - diagnostics_by_group_id - .into_values() - .flat_map(|mut diagnostics| { - let primary_diagnostic = - diagnostics.iter_mut().min_by_key(|d| d.1.severity).unwrap(); - primary_diagnostic.1.is_primary = true; - diagnostics - }), - ); + let mut diagnostics = mem::take(&mut self.diagnostics); + diagnostics.reset( + diagnostics_by_group_id + .into_values() + .flat_map(|mut diagnostics| { + let primary = diagnostics + .iter_mut() + .min_by_key(|entry| entry.diagnostic.severity) + .unwrap(); + primary.diagnostic.is_primary = true; + diagnostics + }), + self, + ); + self.diagnostics = diagnostics; if let Some(version) = version { let language_server = self.language_server.as_mut().unwrap(); @@ -826,18 +831,25 @@ impl Buffer { }) } - pub fn diagnostics_in_range<'a, T>( + pub fn diagnostics_in_range<'a, T, O>( &'a self, search_range: Range, - ) -> impl Iterator + ) -> impl 'a + Iterator> where T: 'a + ToOffset, + O: 'a + FromAnchor, { self.diagnostics.range(search_range, self, true) } - pub fn diagnostic_group(&self, group_id: usize) -> impl Iterator { - self.diagnostics.group(group_id) + pub fn diagnostic_group<'a, O>( + &'a self, + group_id: usize, + ) -> impl 'a + Iterator> + where + O: 'a + FromAnchor, + { + self.diagnostics.group(group_id, self) } pub fn diagnostics_update_count(&self) -> usize { @@ -1468,7 +1480,7 @@ impl Buffer { fn apply_diagnostic_update( &mut self, - diagnostics: Arc<[DiagnosticEntry]>, + diagnostics: Arc<[DiagnosticEntry]>, cx: &mut ModelContext, ) { self.diagnostics = DiagnosticSet::from_sorted_entries(diagnostics.iter().cloned(), self); @@ -1679,14 +1691,17 @@ impl Snapshot { let mut highlights = None; let mut diagnostic_endpoints = Vec::::new(); if let Some(theme) = theme { - for entry in self.diagnostics.range(range.clone(), self, true) { + for entry in self + .diagnostics + .range::<_, usize>(range.clone(), self, true) + { diagnostic_endpoints.push(DiagnosticEndpoint { - offset: entry.range.start.to_offset(self), + offset: entry.range.start, is_start: true, severity: entry.diagnostic.severity, }); diagnostic_endpoints.push(DiagnosticEndpoint { - offset: entry.range.end.to_offset(self), + offset: entry.range.end, is_start: false, severity: entry.diagnostic.severity, }); diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 9640ded372..0a04ef17e8 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -5,16 +5,16 @@ use std::{ ops::Range, }; use sum_tree::{self, Bias, SumTree}; -use text::{Anchor, PointUtf16, ToOffset}; +use text::{Anchor, FromAnchor, PointUtf16, ToOffset}; #[derive(Clone, Default)] pub struct DiagnosticSet { - diagnostics: SumTree, + diagnostics: SumTree>, } -#[derive(Clone, Debug)] -pub struct DiagnosticEntry { - pub range: Range, +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DiagnosticEntry { + pub range: Range, pub diagnostic: Diagnostic, } @@ -30,33 +30,42 @@ pub struct Summary { impl DiagnosticSet { pub fn from_sorted_entries(iter: I, buffer: &text::Snapshot) -> Self where - I: IntoIterator, + I: IntoIterator>, { Self { diagnostics: SumTree::from_iter(iter, buffer), } } - pub fn reset(&mut self, iter: I) + pub fn reset(&mut self, iter: I, buffer: &text::Snapshot) where - I: IntoIterator, Diagnostic)>, + I: IntoIterator>, { let mut entries = iter.into_iter().collect::>(); - entries.sort_unstable_by_key(|(range, _)| (range.start, Reverse(range.end))); + entries.sort_unstable_by_key(|entry| (entry.range.start, Reverse(entry.range.end))); + self.diagnostics = SumTree::from_iter( + entries.into_iter().map(|entry| DiagnosticEntry { + range: buffer.anchor_before(entry.range.start) + ..buffer.anchor_after(entry.range.end), + diagnostic: entry.diagnostic, + }), + buffer, + ); } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator> { self.diagnostics.iter() } - pub fn range<'a, T>( + pub fn range<'a, T, O>( &'a self, range: Range, buffer: &'a text::Snapshot, inclusive: bool, - ) -> impl Iterator + ) -> impl 'a + Iterator> where T: 'a + ToOffset, + O: FromAnchor, { let end_bias = if inclusive { Bias::Right } else { Bias::Left }; let range = buffer.anchor_before(range.start)..buffer.anchor_at(range.end, end_bias); @@ -79,7 +88,7 @@ impl DiagnosticSet { move || { if let Some(diagnostic) = cursor.item() { cursor.next(buffer); - Some(diagnostic) + Some(diagnostic.resolve(buffer)) } else { None } @@ -87,13 +96,18 @@ impl DiagnosticSet { }) } - pub fn group(&self, group_id: usize) -> impl Iterator { + pub fn group<'a, O: FromAnchor>( + &'a self, + group_id: usize, + buffer: &'a text::Snapshot, + ) -> impl 'a + Iterator> { self.iter() .filter(move |entry| entry.diagnostic.group_id == group_id) + .map(|entry| entry.resolve(buffer)) } } -impl sum_tree::Item for DiagnosticEntry { +impl sum_tree::Item for DiagnosticEntry { type Summary = Summary; fn summary(&self) -> Self::Summary { @@ -107,6 +121,16 @@ impl sum_tree::Item for DiagnosticEntry { } } +impl DiagnosticEntry { + pub fn resolve(&self, buffer: &text::Snapshot) -> DiagnosticEntry { + DiagnosticEntry { + range: O::from_anchor(&self.range.start, buffer) + ..O::from_anchor(&self.range.end, buffer), + diagnostic: self.diagnostic.clone(), + } + } +} + impl Default for Summary { fn default() -> Self { Self { diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 619ce19689..99161d1f5c 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -8,6 +8,7 @@ mod tests; use anyhow::{anyhow, Result}; pub use buffer::Operation; pub use buffer::*; +pub use diagnostic_set::DiagnosticEntry; use gpui::{executor::Background, AppContext}; use highlight_map::HighlightMap; use lazy_static::lazy_static; diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 851ab76bca..6f36c7dc0b 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -127,7 +127,7 @@ pub fn serialize_selection_set(set: &SelectionSet) -> proto::SelectionSet { } pub fn serialize_diagnostics<'a>( - diagnostics: impl IntoIterator, + diagnostics: impl IntoIterator>, ) -> Vec { diagnostics .into_iter() @@ -304,7 +304,9 @@ pub fn deserialize_selection_set(set: proto::SelectionSet) -> SelectionSet { } } -pub fn deserialize_diagnostics(diagnostics: Vec) -> Vec { +pub fn deserialize_diagnostics( + diagnostics: Vec, +) -> Vec> { diagnostics .into_iter() .filter_map(|diagnostic| { diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index d1f48245db..cc873f253a 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -532,28 +532,27 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { // The diagnostics have moved down since they were created. assert_eq!( buffer - .diagnostics_in_range(Point::new(3, 0)..Point::new(5, 0)) - .map(|entry| (entry.range.to_point(buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(Point::new(3, 0)..Point::new(5, 0)) .collect::>(), &[ - ( - Point::new(3, 9)..Point::new(3, 11), - &Diagnostic { + DiagnosticEntry { + range: Point::new(3, 9)..Point::new(3, 11), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), group_id: 1, is_primary: true, }, - ), - ( - Point::new(4, 9)..Point::new(4, 12), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(4, 9)..Point::new(4, 12), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'CCC'".to_string(), group_id: 2, is_primary: true, } - ) + } ] ); assert_eq!( @@ -600,28 +599,27 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { .unwrap(); assert_eq!( buffer - .diagnostics_in_range(Point::new(2, 0)..Point::new(3, 0)) - .map(|entry| (entry.range.to_point(buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(Point::new(2, 0)..Point::new(3, 0)) .collect::>(), &[ - ( - Point::new(2, 9)..Point::new(2, 12), - &Diagnostic { + DiagnosticEntry { + range: Point::new(2, 9)..Point::new(2, 12), + diagnostic: Diagnostic { severity: DiagnosticSeverity::WARNING, message: "unreachable statement".to_string(), group_id: 1, is_primary: true, } - ), - ( - Point::new(2, 9)..Point::new(2, 10), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(2, 9)..Point::new(2, 10), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), group_id: 0, is_primary: true, }, - ) + } ] ); assert_eq!( @@ -680,28 +678,27 @@ async fn test_diagnostics(mut cx: gpui::TestAppContext) { .unwrap(); assert_eq!( buffer - .diagnostics_in_range(0..buffer.len()) - .map(|entry| (entry.range.to_point(buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(0..buffer.len()) .collect::>(), &[ - ( - Point::new(2, 21)..Point::new(2, 22), - &Diagnostic { + DiagnosticEntry { + range: Point::new(2, 21)..Point::new(2, 22), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), group_id: 0, is_primary: true, } - ), - ( - Point::new(3, 9)..Point::new(3, 11), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(3, 9)..Point::new(3, 11), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), group_id: 1, is_primary: true, }, - ) + } ] ); }); @@ -866,117 +863,110 @@ async fn test_grouped_diagnostics(mut cx: gpui::TestAppContext) { buffer.update_diagnostics(None, diagnostics, cx).unwrap(); assert_eq!( buffer - .diagnostics_in_range(0..buffer.len()) - .map(|entry| (entry.range.to_point(&buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(0..buffer.len()) .collect::>(), &[ - ( - Point::new(1, 8)..Point::new(1, 9), - &Diagnostic { + DiagnosticEntry { + range: Point::new(1, 8)..Point::new(1, 9), + diagnostic: Diagnostic { severity: DiagnosticSeverity::WARNING, message: "error 1".to_string(), group_id: 0, is_primary: true, } - ), - ( - Point::new(1, 8)..Point::new(1, 9), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(1, 8)..Point::new(1, 9), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 1 hint 1".to_string(), group_id: 0, is_primary: false, } - ), - ( - Point::new(1, 13)..Point::new(1, 15), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(1, 13)..Point::new(1, 15), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 2 hint 1".to_string(), group_id: 1, is_primary: false, } - ), - ( - Point::new(1, 13)..Point::new(1, 15), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(1, 13)..Point::new(1, 15), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 2 hint 2".to_string(), group_id: 1, is_primary: false, } - ), - ( - Point::new(2, 8)..Point::new(2, 17), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(2, 8)..Point::new(2, 17), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "error 2".to_string(), group_id: 1, is_primary: true, } - ) + } ] ); assert_eq!( - buffer - .diagnostic_group(0) - .map(|entry| (entry.range.to_point(&buffer), &entry.diagnostic)) - .collect::>(), + buffer.diagnostic_group::(0).collect::>(), &[ - ( - Point::new(1, 8)..Point::new(1, 9), - &Diagnostic { + DiagnosticEntry { + range: Point::new(1, 8)..Point::new(1, 9), + diagnostic: Diagnostic { severity: DiagnosticSeverity::WARNING, message: "error 1".to_string(), group_id: 0, is_primary: true, } - ), - ( - Point::new(1, 8)..Point::new(1, 9), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(1, 8)..Point::new(1, 9), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 1 hint 1".to_string(), group_id: 0, is_primary: false, } - ), + }, ] ); assert_eq!( - buffer - .diagnostic_group(1) - .map(|entry| (entry.range.to_point(&buffer), &entry.diagnostic)) - .collect::>(), + buffer.diagnostic_group::(1).collect::>(), &[ - ( - Point::new(1, 13)..Point::new(1, 15), - &Diagnostic { + DiagnosticEntry { + range: Point::new(1, 13)..Point::new(1, 15), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 2 hint 1".to_string(), group_id: 1, is_primary: false, } - ), - ( - Point::new(1, 13)..Point::new(1, 15), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(1, 13)..Point::new(1, 15), + diagnostic: Diagnostic { severity: DiagnosticSeverity::HINT, message: "error 2 hint 2".to_string(), group_id: 1, is_primary: false, } - ), - ( - Point::new(2, 8)..Point::new(2, 17), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(2, 8)..Point::new(2, 17), + diagnostic: Diagnostic { severity: DiagnosticSeverity::ERROR, message: "error 2".to_string(), group_id: 1, is_primary: true, } - ) + } ] ); diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 393e92dfb9..943ab6dbd0 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -3005,7 +3005,7 @@ mod tests { use anyhow::Result; use client::test::{FakeHttpClient, FakeServer}; use fs::RealFs; - use language::{tree_sitter_rust, AnchorRangeExt, LanguageServerConfig}; + use language::{tree_sitter_rust, DiagnosticEntry, LanguageServerConfig}; use language::{Diagnostic, LanguageConfig}; use lsp::Url; use rand::prelude::*; @@ -3721,20 +3721,19 @@ mod tests { buffer.read_with(&cx, |buffer, _| { let diagnostics = buffer - .diagnostics_in_range(0..buffer.len()) - .map(|entry| (entry.range.to_point(buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(0..buffer.len()) .collect::>(); assert_eq!( diagnostics, - &[( - Point::new(0, 9)..Point::new(0, 10), - &Diagnostic { + &[DiagnosticEntry { + range: Point::new(0, 9)..Point::new(0, 10), + diagnostic: Diagnostic { severity: lsp::DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), group_id: 0, is_primary: true } - )] + }] ) }); } diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 6d1b1238c6..a37dc56532 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -947,7 +947,7 @@ mod tests { editor::{Editor, EditorSettings, Input}, fs::{FakeFs, Fs as _}, language::{ - tree_sitter_rust, AnchorRangeExt, Diagnostic, Language, LanguageConfig, + tree_sitter_rust, Diagnostic, DiagnosticEntry, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig, Point, }, lsp, @@ -1704,28 +1704,27 @@ mod tests { buffer_b.read_with(&cx_b, |buffer, _| { assert_eq!( buffer - .diagnostics_in_range(0..buffer.len()) - .map(|entry| (entry.range.to_point(buffer), &entry.diagnostic)) + .diagnostics_in_range::<_, Point>(0..buffer.len()) .collect::>(), &[ - ( - Point::new(0, 4)..Point::new(0, 7), - &Diagnostic { + DiagnosticEntry { + range: Point::new(0, 4)..Point::new(0, 7), + diagnostic: Diagnostic { group_id: 0, message: "message 1".to_string(), severity: lsp::DiagnosticSeverity::ERROR, is_primary: true } - ), - ( - Point::new(0, 10)..Point::new(0, 13), - &Diagnostic { + }, + DiagnosticEntry { + range: Point::new(0, 10)..Point::new(0, 13), + diagnostic: Diagnostic { group_id: 1, severity: lsp::DiagnosticSeverity::WARNING, message: "message 2".to_string(), is_primary: true } - ) + } ] ); });