From dfbfa86548bb5dbbddff590f7ebb07302ef045fc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 19 Nov 2021 15:31:33 +0100 Subject: [PATCH] WIP --- crates/editor/src/display_map.rs | 12 ++++- crates/editor/src/display_map/block_map.rs | 23 +++++++-- crates/editor/src/lib.rs | 60 ++++++++++++++++++++-- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 5eb3d108df..d671773d25 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -10,7 +10,10 @@ use buffer::Rope; use fold_map::{FoldMap, ToFoldPoint as _}; use gpui::{fonts::FontId, AppContext, Entity, ModelContext, ModelHandle}; use language::{Anchor, Buffer, Point, ToOffset, ToPoint}; -use std::{collections::HashSet, ops::Range}; +use std::{ + collections::{HashMap, HashSet}, + ops::Range, +}; use sum_tree::Bias; use tab_map::TabMap; use theme::{BlockStyle, SyntaxTheme}; @@ -128,6 +131,13 @@ impl DisplayMap { block_map.insert(blocks, cx) } + pub fn restyle_blocks(&mut self, styles: HashMap>) + where + F: 'static + Fn(&AppContext) -> BlockStyle, + { + self.block_map.restyle(styles); + } + pub fn remove_blocks(&mut self, ids: HashSet, cx: &mut ModelContext) { let (snapshot, edits) = self.fold_map.read(cx); let (snapshot, edits) = self.tab_map.sync(snapshot, edits); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 62efc61eec..7e7cdc328f 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -8,7 +8,7 @@ use language::{Buffer, Chunk}; use parking_lot::Mutex; use std::{ cmp::{self, Ordering}, - collections::HashSet, + collections::{HashMap, HashSet}, fmt::Debug, iter, ops::{Deref, Range}, @@ -53,7 +53,7 @@ pub struct Block { position: Anchor, text: Rope, build_runs: Option Vec<(usize, HighlightStyle)>>>, - build_style: Option BlockStyle>>, + build_style: Mutex BlockStyle>>>, disposition: BlockDisposition, } @@ -332,6 +332,19 @@ impl BlockMap { drop(cursor); *transforms = new_transforms; } + + pub fn restyle(&mut self, mut styles: HashMap>) + where + F: 'static + Fn(&AppContext) -> BlockStyle, + { + for block in &self.blocks { + if let Some(build_style) = styles.remove(&block.id) { + *block.build_style.lock() = build_style.map(|build_style| { + Arc::new(build_style) as Arc BlockStyle> + }); + } + } + } } fn push_isomorphic(tree: &mut SumTree, rows: u32) { @@ -421,7 +434,7 @@ impl<'a> BlockMapWriter<'a> { position, text: block.text.into(), build_runs: block.build_runs, - build_style: block.build_style, + build_style: Mutex::new(block.build_style), disposition: block.disposition, }), ); @@ -896,7 +909,7 @@ impl<'a> Iterator for BufferRows<'a> { if let Some(block) = &transform.block { let style = self .cx - .and_then(|cx| block.build_style.as_ref().map(|f| f(cx))); + .and_then(|cx| block.build_style.lock().as_ref().map(|f| f(cx))); Some(DisplayRow::Block(block.id, style)) } else { Some(self.input_buffer_rows.next().unwrap()) @@ -1017,7 +1030,7 @@ mod tests { id: BlockId(0), position: Anchor::min(), text: "one!\ntwo three\nfour".into(), - build_style: None, + build_style: Mutex::new(None), build_runs: Some(Arc::new(move |_| { vec![(3, red.into()), (6, Default::default()), (5, blue.into())] })), diff --git a/crates/editor/src/lib.rs b/crates/editor/src/lib.rs index 72cc75fa39..151dffa324 100644 --- a/crates/editor/src/lib.rs +++ b/crates/editor/src/lib.rs @@ -24,7 +24,7 @@ use smol::Timer; use std::{ cell::RefCell, cmp::{self, Ordering}, - collections::HashSet, + collections::{HashMap, HashSet}, iter, mem, ops::{Range, RangeInclusive}, rc::Rc, @@ -341,8 +341,10 @@ struct BracketPairState { #[derive(Debug)] struct ActiveDiagnosticGroup { primary_range: Range, + primary_message: String, + blocks: HashMap, group_range: Range, - block_ids: HashSet, + is_valid: bool, } #[derive(Serialize, Deserialize)] @@ -2268,13 +2270,17 @@ impl Editor { ..buffer.anchor_before(group_end); let primary_range = buffer.anchor_after(primary_range.start) ..buffer.anchor_before(primary_range.end); + let mut primary_message = None; - let block_ids = display_map + let blocks = display_map .insert_blocks( diagnostic_group.iter().map(|(range, diagnostic)| { let build_settings = self.build_settings.clone(); let message_len = diagnostic.message.len(); let severity = diagnostic.severity; + if diagnostic.is_primary { + primary_message = Some(diagnostic.message.clone()); + } BlockProperties { position: range.start, text: diagnostic.message.as_str(), @@ -2303,12 +2309,19 @@ impl Editor { cx, ) .into_iter() + .zip( + diagnostic_group + .into_iter() + .map(|(_, diagnostic)| diagnostic), + ) .collect(); Some(ActiveDiagnosticGroup { primary_range, + primary_message: primary_message.unwrap(), group_range, - block_ids, + blocks, + is_valid: true, }) }); @@ -2333,10 +2346,46 @@ impl Editor { } } + fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext) { + if let Some(active_diagnostics) = self.active_diagnostics.as_mut() { + let buffer = self.buffer.read(cx); + let primary_range_start = active_diagnostics.primary_range.start.to_offset(buffer); + let matching_diagnostic = buffer + .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone()) + .find_map(|(range, diagnostic)| { + if diagnostic.is_primary + && range.start == primary_range_start + && diagnostic.message == active_diagnostics.primary_message + { + Some(diagnostic.group_id) + } else { + None + } + }); + if let Some(matching_diagnostic) = matching_diagnostic { + } else if active_diagnostics.is_valid { + let mut new_styles = HashMap::new(); + for (block_id, diagnostic) in &active_diagnostics.blocks { + let build_settings = self.build_settings.clone(); + let severity = diagnostic.severity; + new_styles.insert( + *block_id, + Some(move |cx: &AppContext| { + let settings = build_settings.borrow()(cx); + diagnostic_style(severity, false, &settings.style).block + }), + ); + } + self.display_map + .update(cx, |display_map, _| display_map.restyle_blocks(new_styles)); + } + } + } + fn dismiss_diagnostics(&mut self, cx: &mut ViewContext) { if let Some(active_diagnostic_group) = self.active_diagnostics.take() { self.display_map.update(cx, |display_map, cx| { - display_map.remove_blocks(active_diagnostic_group.block_ids, cx); + display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx); }); cx.notify(); } @@ -2799,6 +2848,7 @@ impl Editor { } fn on_buffer_changed(&mut self, _: ModelHandle, cx: &mut ViewContext) { + self.refresh_active_diagnostics(cx); cx.notify(); }