WIP
Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
parent
2018537bb8
commit
54932a8050
1 changed files with 78 additions and 48 deletions
|
@ -151,6 +151,7 @@ impl Drop for QueryCursorHandle {
|
||||||
QUERY_CURSORS.lock().push(cursor)
|
QUERY_CURSORS.lock().push(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
fragments: SumTree<Fragment>,
|
fragments: SumTree<Fragment>,
|
||||||
visible_text: Rope,
|
visible_text: Rope,
|
||||||
|
@ -192,6 +193,30 @@ struct SyntaxTree {
|
||||||
version: clock::Global,
|
version: clock::Global,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SyntaxTree {
|
||||||
|
fn interpolate(&mut self, buffer: &Buffer) {
|
||||||
|
let mut delta = 0_isize;
|
||||||
|
for edit in buffer.edits_since(self.version.clone()) {
|
||||||
|
let start_offset = (edit.old_bytes.start as isize + delta) as usize;
|
||||||
|
let start_point = buffer.visible_text.to_point(start_offset);
|
||||||
|
self.tree.edit(&InputEdit {
|
||||||
|
start_byte: start_offset,
|
||||||
|
old_end_byte: start_offset + edit.deleted_bytes(),
|
||||||
|
new_end_byte: start_offset + edit.inserted_bytes(),
|
||||||
|
start_position: start_point.into(),
|
||||||
|
old_end_position: (start_point + edit.deleted_lines()).into(),
|
||||||
|
new_end_position: buffer
|
||||||
|
.visible_text
|
||||||
|
.to_point(start_offset + edit.inserted_bytes())
|
||||||
|
.into(),
|
||||||
|
});
|
||||||
|
delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
|
||||||
|
self.dirty = true;
|
||||||
|
}
|
||||||
|
self.version = buffer.version();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct AutoindentRequest {
|
struct AutoindentRequest {
|
||||||
position: Anchor,
|
position: Anchor,
|
||||||
|
@ -850,27 +875,9 @@ impl Buffer {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syntax_tree(&self) -> Option<Tree> {
|
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 delta = 0_isize;
|
syntax_tree.interpolate(self);
|
||||||
for edit in self.edits_since(syntax_tree.version.clone()) {
|
|
||||||
let start_offset = (edit.old_bytes.start as isize + delta) as usize;
|
|
||||||
let start_point = self.visible_text.to_point(start_offset);
|
|
||||||
syntax_tree.tree.edit(&InputEdit {
|
|
||||||
start_byte: start_offset,
|
|
||||||
old_end_byte: start_offset + edit.deleted_bytes(),
|
|
||||||
new_end_byte: start_offset + edit.inserted_bytes(),
|
|
||||||
start_position: start_point.into(),
|
|
||||||
old_end_position: (start_point + edit.deleted_lines()).into(),
|
|
||||||
new_end_position: self
|
|
||||||
.visible_text
|
|
||||||
.to_point(start_offset + edit.inserted_bytes())
|
|
||||||
.into(),
|
|
||||||
});
|
|
||||||
delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
|
|
||||||
syntax_tree.dirty = true;
|
|
||||||
}
|
|
||||||
syntax_tree.version = self.version();
|
|
||||||
Some(syntax_tree.tree.clone())
|
Some(syntax_tree.tree.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -893,13 +900,16 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(language) = self.language.clone() {
|
if let Some(language) = self.language.clone() {
|
||||||
let old_snapshot = self.snapshot();
|
let old_tree = self.syntax_tree.lock().as_mut().map(|tree| {
|
||||||
|
tree.interpolate(self);
|
||||||
|
tree.clone()
|
||||||
|
});
|
||||||
|
let text = self.visible_text.clone();
|
||||||
let parsed_version = self.version();
|
let parsed_version = self.version();
|
||||||
let parse_task = cx.background().spawn({
|
let parse_task = cx.background().spawn({
|
||||||
let language = language.clone();
|
let language = language.clone();
|
||||||
let text = old_snapshot.visible_text.clone();
|
let old_tree = old_tree.as_ref().map(|t| t.tree.clone());
|
||||||
let tree = old_snapshot.tree.clone();
|
async move { Self::parse_text(&text, old_tree, &language) }
|
||||||
async move { Self::parse_text(&text, tree, &language) }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
match cx
|
match cx
|
||||||
|
@ -907,13 +917,13 @@ impl Buffer {
|
||||||
.block_with_timeout(self.sync_parse_timeout, parse_task)
|
.block_with_timeout(self.sync_parse_timeout, parse_task)
|
||||||
{
|
{
|
||||||
Ok(new_tree) => {
|
Ok(new_tree) => {
|
||||||
*self.syntax_tree.lock() = Some(SyntaxTree {
|
self.did_finish_parsing(
|
||||||
tree: new_tree.clone(),
|
old_tree.map(|t| t.tree),
|
||||||
dirty: false,
|
new_tree,
|
||||||
version: parsed_version,
|
parsed_version,
|
||||||
});
|
language,
|
||||||
self.parse_count += 1;
|
cx,
|
||||||
self.did_finish_parsing(new_tree, old_snapshot, language, cx);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Err(parse_task) => {
|
Err(parse_task) => {
|
||||||
|
@ -926,19 +936,22 @@ impl Buffer {
|
||||||
!Arc::ptr_eq(curr_language, &language)
|
!Arc::ptr_eq(curr_language, &language)
|
||||||
});
|
});
|
||||||
let parse_again = this.version > parsed_version || language_changed;
|
let parse_again = this.version > parsed_version || language_changed;
|
||||||
*this.syntax_tree.lock() = Some(SyntaxTree {
|
let old_tree = old_tree.map(|mut old_tree| {
|
||||||
tree: new_tree.clone(),
|
old_tree.interpolate(this);
|
||||||
dirty: false,
|
old_tree.tree
|
||||||
version: parsed_version,
|
|
||||||
});
|
});
|
||||||
this.parse_count += 1;
|
|
||||||
this.parsing_in_background = false;
|
this.parsing_in_background = false;
|
||||||
|
this.did_finish_parsing(
|
||||||
|
old_tree,
|
||||||
|
new_tree,
|
||||||
|
parsed_version,
|
||||||
|
language,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
|
||||||
if parse_again && this.reparse(cx) {
|
if parse_again && this.reparse(cx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.did_finish_parsing(new_tree, old_snapshot, language, cx);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -970,8 +983,28 @@ impl Buffer {
|
||||||
|
|
||||||
fn did_finish_parsing(
|
fn did_finish_parsing(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
old_tree: Option<Tree>,
|
||||||
new_tree: Tree,
|
new_tree: Tree,
|
||||||
old_snapshot: Snapshot,
|
new_version: clock::Global,
|
||||||
|
language: Arc<Language>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) {
|
||||||
|
self.perform_autoindent(old_tree, &new_tree, language, cx);
|
||||||
|
|
||||||
|
self.parse_count += 1;
|
||||||
|
*self.syntax_tree.lock() = Some(SyntaxTree {
|
||||||
|
tree: new_tree,
|
||||||
|
dirty: false,
|
||||||
|
version: new_version,
|
||||||
|
});
|
||||||
|
cx.emit(Event::Reparsed);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn perform_autoindent(
|
||||||
|
&mut self,
|
||||||
|
old_tree: Option<Tree>,
|
||||||
|
new_tree: &Tree,
|
||||||
language: Arc<Language>,
|
language: Arc<Language>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
|
@ -999,10 +1032,10 @@ impl Buffer {
|
||||||
if range.end == row {
|
if range.end == row {
|
||||||
range.end += 1;
|
range.end += 1;
|
||||||
} else {
|
} else {
|
||||||
self.perform_autoindent(
|
self.perform_autoindent_for_rows(
|
||||||
range.clone(),
|
range.clone(),
|
||||||
|
old_tree.as_ref(),
|
||||||
&new_tree,
|
&new_tree,
|
||||||
&old_snapshot,
|
|
||||||
&autoindent_requests_by_row,
|
&autoindent_requests_by_row,
|
||||||
language.as_ref(),
|
language.as_ref(),
|
||||||
&mut cursor,
|
&mut cursor,
|
||||||
|
@ -1014,10 +1047,10 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(range) = row_range {
|
if let Some(range) = row_range {
|
||||||
self.perform_autoindent(
|
self.perform_autoindent_for_rows(
|
||||||
range,
|
range,
|
||||||
|
old_tree.as_ref(),
|
||||||
&new_tree,
|
&new_tree,
|
||||||
&old_snapshot,
|
|
||||||
&autoindent_requests_by_row,
|
&autoindent_requests_by_row,
|
||||||
language.as_ref(),
|
language.as_ref(),
|
||||||
&mut cursor,
|
&mut cursor,
|
||||||
|
@ -1025,16 +1058,13 @@ impl Buffer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.end_transaction(None, cx).unwrap();
|
self.end_transaction(None, cx).unwrap();
|
||||||
|
|
||||||
cx.emit(Event::Reparsed);
|
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_autoindent(
|
fn perform_autoindent_for_rows(
|
||||||
&mut self,
|
&mut self,
|
||||||
row_range: Range<u32>,
|
row_range: Range<u32>,
|
||||||
|
old_tree: Option<&Tree>,
|
||||||
new_tree: &Tree,
|
new_tree: &Tree,
|
||||||
old_snapshot: &Snapshot,
|
|
||||||
autoindent_requests: &BTreeMap<u32, AutoindentRequest>,
|
autoindent_requests: &BTreeMap<u32, AutoindentRequest>,
|
||||||
language: &Language,
|
language: &Language,
|
||||||
cursor: &mut QueryCursor,
|
cursor: &mut QueryCursor,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue