From 11b8577d1bdef6bf424e6256499a7df72537a79d Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 6 Sep 2021 11:57:55 -0700 Subject: [PATCH] Update FoldMap snapshot versions when only the parse tree changes even if the buffer's text has not changed Co-Authored-By: Nathan Sobo --- zed/src/editor/buffer.rs | 35 +++++++++++++++++++------- zed/src/editor/display_map/fold_map.rs | 8 +++--- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index da3fd22280..f353a48c42 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -121,6 +121,7 @@ pub struct Buffer { language: Option>, syntax_tree: Mutex>, is_parsing: bool, + parse_count: usize, selections: HashMap, deferred_ops: OperationQueue, deferred_replicas: HashSet, @@ -141,7 +142,7 @@ pub struct SelectionSet { #[derive(Clone)] struct SyntaxTree { tree: Tree, - parsed: bool, + dirty: bool, version: time::Global, } @@ -581,6 +582,7 @@ impl Buffer { file, syntax_tree: Mutex::new(None), is_parsing: false, + parse_count: 0, language, saved_mtime, selections: HashMap::default(), @@ -790,9 +792,12 @@ impl Buffer { cx.emit(Event::FileHandleChanged); } + pub fn parse_count(&self) -> usize { + self.parse_count + } + pub fn syntax_tree(&self) -> Option { if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() { - let mut edited = false; let mut delta = 0_isize; for edit in self.edits_since(syntax_tree.version.clone()) { let start_offset = (edit.old_bytes.start as isize + delta) as usize; @@ -809,9 +814,8 @@ impl Buffer { .into(), }); delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize; - edited = true; + syntax_tree.dirty = true; } - syntax_tree.parsed &= !edited; syntax_tree.version = self.version(); Some(syntax_tree.tree.clone()) } else { @@ -819,13 +823,14 @@ impl Buffer { } } + #[cfg(test)] pub fn is_parsing(&self) -> bool { self.is_parsing } fn should_reparse(&self) -> bool { if let Some(syntax_tree) = self.syntax_tree.lock().as_ref() { - !syntax_tree.parsed || syntax_tree.version != self.version + syntax_tree.dirty || syntax_tree.version != self.version } else { self.language.is_some() } @@ -841,7 +846,7 @@ impl Buffer { if let Some(language) = self.language.clone() { self.is_parsing = true; cx.spawn(|handle, mut cx| async move { - while handle.read_with(&cx, |this, _| this.should_reparse()) { + loop { // The parse tree is out of date, so grab the syntax tree to synchronously // splice all the edits that have happened since the last parse. let new_tree = handle.update(&mut cx, |this, _| this.syntax_tree()); @@ -857,17 +862,28 @@ impl Buffer { }) .await; - handle.update(&mut cx, |this, cx| { + let parse_again = handle.update(&mut cx, |this, cx| { *this.syntax_tree.lock() = Some(SyntaxTree { tree: new_tree, - parsed: true, + dirty: false, version: new_version, }); + this.parse_count += 1; cx.emit(Event::Reparsed); cx.notify(); + + if this.should_reparse() { + true + } else { + this.is_parsing = false; + false + } }); + + if !parse_again { + break; + } } - handle.update(&mut cx, |this, _| this.is_parsing = false); }) .detach(); } @@ -1916,6 +1932,7 @@ impl Clone for Buffer { language: self.language.clone(), syntax_tree: Mutex::new(self.syntax_tree.lock().clone()), is_parsing: false, + parse_count: self.parse_count, deferred_replicas: self.deferred_replicas.clone(), replica_id: self.replica_id, remote_id: self.remote_id.clone(), diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 1c24bacafc..8aa01495e8 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -201,7 +201,7 @@ pub struct FoldMap { #[derive(Clone)] struct SyncState { version: time::Global, - is_parsing: bool, + parse_count: usize, } impl FoldMap { @@ -222,7 +222,7 @@ impl FoldMap { )), last_sync: Mutex::new(SyncState { version: buffer.version(), - is_parsing: buffer.is_parsing(), + parse_count: buffer.parse_count(), }), version: AtomicUsize::new(0), }; @@ -253,7 +253,7 @@ impl FoldMap { &mut *self.last_sync.lock(), SyncState { version: buffer.version(), - is_parsing: buffer.is_parsing(), + parse_count: buffer.parse_count(), }, ); let edits = buffer @@ -261,7 +261,7 @@ impl FoldMap { .map(Into::into) .collect::>(); if edits.is_empty() { - if last_sync.is_parsing != buffer.is_parsing() { + if last_sync.parse_count != buffer.parse_count() { self.version.fetch_add(1, SeqCst); } Vec::new()