mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-25 19:29:49 +00:00
Update FoldMap snapshot versions when only the parse tree changes
even if the buffer's text has not changed Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
94959d18c4
commit
11b8577d1b
2 changed files with 30 additions and 13 deletions
|
@ -121,6 +121,7 @@ pub struct Buffer {
|
||||||
language: Option<Arc<Language>>,
|
language: Option<Arc<Language>>,
|
||||||
syntax_tree: Mutex<Option<SyntaxTree>>,
|
syntax_tree: Mutex<Option<SyntaxTree>>,
|
||||||
is_parsing: bool,
|
is_parsing: bool,
|
||||||
|
parse_count: usize,
|
||||||
selections: HashMap<SelectionSetId, SelectionSet>,
|
selections: HashMap<SelectionSetId, SelectionSet>,
|
||||||
deferred_ops: OperationQueue,
|
deferred_ops: OperationQueue,
|
||||||
deferred_replicas: HashSet<ReplicaId>,
|
deferred_replicas: HashSet<ReplicaId>,
|
||||||
|
@ -141,7 +142,7 @@ pub struct SelectionSet {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct SyntaxTree {
|
struct SyntaxTree {
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
parsed: bool,
|
dirty: bool,
|
||||||
version: time::Global,
|
version: time::Global,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,6 +582,7 @@ impl Buffer {
|
||||||
file,
|
file,
|
||||||
syntax_tree: Mutex::new(None),
|
syntax_tree: Mutex::new(None),
|
||||||
is_parsing: false,
|
is_parsing: false,
|
||||||
|
parse_count: 0,
|
||||||
language,
|
language,
|
||||||
saved_mtime,
|
saved_mtime,
|
||||||
selections: HashMap::default(),
|
selections: HashMap::default(),
|
||||||
|
@ -790,9 +792,12 @@ impl Buffer {
|
||||||
cx.emit(Event::FileHandleChanged);
|
cx.emit(Event::FileHandleChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_count(&self) -> usize {
|
||||||
|
self.parse_count
|
||||||
|
}
|
||||||
|
|
||||||
pub fn syntax_tree(&self) -> Option<Tree> {
|
pub fn syntax_tree(&self) -> Option<Tree> {
|
||||||
if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
|
if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
|
||||||
let mut edited = false;
|
|
||||||
let mut delta = 0_isize;
|
let mut delta = 0_isize;
|
||||||
for edit in self.edits_since(syntax_tree.version.clone()) {
|
for edit in self.edits_since(syntax_tree.version.clone()) {
|
||||||
let start_offset = (edit.old_bytes.start as isize + delta) as usize;
|
let start_offset = (edit.old_bytes.start as isize + delta) as usize;
|
||||||
|
@ -809,9 +814,8 @@ impl Buffer {
|
||||||
.into(),
|
.into(),
|
||||||
});
|
});
|
||||||
delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
|
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();
|
syntax_tree.version = self.version();
|
||||||
Some(syntax_tree.tree.clone())
|
Some(syntax_tree.tree.clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -819,13 +823,14 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn is_parsing(&self) -> bool {
|
pub fn is_parsing(&self) -> bool {
|
||||||
self.is_parsing
|
self.is_parsing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_reparse(&self) -> bool {
|
fn should_reparse(&self) -> bool {
|
||||||
if let Some(syntax_tree) = self.syntax_tree.lock().as_ref() {
|
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 {
|
} else {
|
||||||
self.language.is_some()
|
self.language.is_some()
|
||||||
}
|
}
|
||||||
|
@ -841,7 +846,7 @@ impl Buffer {
|
||||||
if let Some(language) = self.language.clone() {
|
if let Some(language) = self.language.clone() {
|
||||||
self.is_parsing = true;
|
self.is_parsing = true;
|
||||||
cx.spawn(|handle, mut cx| async move {
|
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
|
// 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.
|
// splice all the edits that have happened since the last parse.
|
||||||
let new_tree = handle.update(&mut cx, |this, _| this.syntax_tree());
|
let new_tree = handle.update(&mut cx, |this, _| this.syntax_tree());
|
||||||
|
@ -857,17 +862,28 @@ impl Buffer {
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
handle.update(&mut cx, |this, cx| {
|
let parse_again = handle.update(&mut cx, |this, cx| {
|
||||||
*this.syntax_tree.lock() = Some(SyntaxTree {
|
*this.syntax_tree.lock() = Some(SyntaxTree {
|
||||||
tree: new_tree,
|
tree: new_tree,
|
||||||
parsed: true,
|
dirty: false,
|
||||||
version: new_version,
|
version: new_version,
|
||||||
});
|
});
|
||||||
|
this.parse_count += 1;
|
||||||
cx.emit(Event::Reparsed);
|
cx.emit(Event::Reparsed);
|
||||||
cx.notify();
|
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();
|
.detach();
|
||||||
}
|
}
|
||||||
|
@ -1916,6 +1932,7 @@ impl Clone for Buffer {
|
||||||
language: self.language.clone(),
|
language: self.language.clone(),
|
||||||
syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
|
syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
|
||||||
is_parsing: false,
|
is_parsing: false,
|
||||||
|
parse_count: self.parse_count,
|
||||||
deferred_replicas: self.deferred_replicas.clone(),
|
deferred_replicas: self.deferred_replicas.clone(),
|
||||||
replica_id: self.replica_id,
|
replica_id: self.replica_id,
|
||||||
remote_id: self.remote_id.clone(),
|
remote_id: self.remote_id.clone(),
|
||||||
|
|
|
@ -201,7 +201,7 @@ pub struct FoldMap {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct SyncState {
|
struct SyncState {
|
||||||
version: time::Global,
|
version: time::Global,
|
||||||
is_parsing: bool,
|
parse_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FoldMap {
|
impl FoldMap {
|
||||||
|
@ -222,7 +222,7 @@ impl FoldMap {
|
||||||
)),
|
)),
|
||||||
last_sync: Mutex::new(SyncState {
|
last_sync: Mutex::new(SyncState {
|
||||||
version: buffer.version(),
|
version: buffer.version(),
|
||||||
is_parsing: buffer.is_parsing(),
|
parse_count: buffer.parse_count(),
|
||||||
}),
|
}),
|
||||||
version: AtomicUsize::new(0),
|
version: AtomicUsize::new(0),
|
||||||
};
|
};
|
||||||
|
@ -253,7 +253,7 @@ impl FoldMap {
|
||||||
&mut *self.last_sync.lock(),
|
&mut *self.last_sync.lock(),
|
||||||
SyncState {
|
SyncState {
|
||||||
version: buffer.version(),
|
version: buffer.version(),
|
||||||
is_parsing: buffer.is_parsing(),
|
parse_count: buffer.parse_count(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let edits = buffer
|
let edits = buffer
|
||||||
|
@ -261,7 +261,7 @@ impl FoldMap {
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if edits.is_empty() {
|
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);
|
self.version.fetch_add(1, SeqCst);
|
||||||
}
|
}
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
|
Loading…
Reference in a new issue