This commit is contained in:
Max Brunsfeld 2021-05-23 21:42:45 -07:00
parent b0859d4265
commit b51ae1f668
3 changed files with 66 additions and 15 deletions

3
Cargo.lock generated
View File

@ -2705,8 +2705,7 @@ dependencies = [
[[package]]
name = "tree-sitter"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad726ec26496bf4c083fff0f43d4eb3a2ad1bba305323af5ff91383c0b6ecac0"
source = "git+https://github.com/tree-sitter/tree-sitter?rev=8c3d1466ecae2a22a9625d1456ffaae84b13fd3e#8c3d1466ecae2a22a9625d1456ffaae84b13fd3e"
dependencies = [
"cc",
"regex",

View File

@ -3,6 +3,7 @@ members = ["zed", "gpui", "gpui_macros", "fsevent", "scoped_pool"]
[patch.crates-io]
async-task = {git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e"}
tree-sitter = {git = "https://github.com/tree-sitter/tree-sitter", rev = "8c3d1466ecae2a22a9625d1456ffaae84b13fd3e"}
# TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457
cocoa = {git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737"}

View File

@ -4,13 +4,12 @@ pub mod rope;
mod selection;
pub use anchor::*;
use parking_lot::Mutex;
pub use point::*;
pub use rope::{ChunksIter, Rope, TextSummary};
use seahash::SeaHasher;
pub use selection::*;
use similar::{ChangeTag, TextDiff};
use tree_sitter::{InputEdit, Parser};
use tree_sitter::{InputEdit, Parser, QueryCursor};
use crate::{
editor::Bias,
@ -77,9 +76,10 @@ pub struct Buffer {
history: History,
file: Option<FileHandle>,
language: Option<Arc<Language>>,
tree: Mutex<Option<(Tree, time::Global)>>,
tree: Option<(Tree, time::Global)>,
is_parsing: bool,
selections: HashMap<SelectionSetId, Arc<[Selection]>>,
cursor: QueryCursor,
pub selections_last_update: SelectionsVersion,
deferred_ops: OperationQueue<Operation>,
deferred_replicas: HashSet<ReplicaId>,
@ -487,8 +487,9 @@ impl Buffer {
undo_map: Default::default(),
history,
file,
tree: Mutex::new(None),
tree: None,
is_parsing: false,
cursor: QueryCursor::new(),
language,
saved_mtime,
selections: HashMap::default(),
@ -549,8 +550,8 @@ impl Buffer {
ctx.emit(Event::Saved);
}
pub fn syntax_tree(&self) -> Option<Tree> {
if let Some((tree, tree_version)) = self.tree.lock().as_mut() {
pub fn syntax_tree(&mut self) -> Option<Tree> {
if let Some((mut tree, tree_version)) = self.tree.take() {
let mut delta = 0_isize;
for Edit {
old_range,
@ -572,8 +573,9 @@ impl Buffer {
});
delta += new_bytes as isize - old_bytes as isize;
}
*tree_version = self.version();
Some(tree.clone())
let result = tree.clone();
self.tree = Some((tree, self.version()));
Some(result)
} else {
None
}
@ -581,7 +583,6 @@ impl Buffer {
fn should_reparse(&self) -> bool {
self.tree
.lock()
.as_ref()
.map_or(true, |(_, tree_version)| *tree_version != self.version)
}
@ -613,7 +614,7 @@ impl Buffer {
.await;
handle.update(&mut ctx, |this, ctx| {
*this.tree.lock() = Some((new_tree, new_version));
this.tree = Some((new_tree, new_version));
ctx.emit(Event::Reparsed);
});
}
@ -750,6 +751,36 @@ impl Buffer {
self.visible_text.chunks_in_range(start..end)
}
pub fn highlighted_text_for_range<'a, T: ToOffset>(
&'a mut self,
range: Range<T>,
) -> impl Iterator<Item = (&'a str, usize)> {
if let (Some(language), Some((tree, _))) = (&self.language, self.tree.as_ref()) {
let visible_text = &self.visible_text;
let start = range.start.to_offset(self);
let end = range.end.to_offset(self);
self.cursor.set_byte_range(start, end);
let chunks = self.visible_text.chunks_in_range(start..end);
let captures = self.cursor.captures(
&language.highlight_query,
tree.root_node(),
move |node: tree_sitter::Node| {
visible_text
.chunks_in_range(node.byte_range())
.map(str::as_bytes)
},
);
HighlightedChunksIter {
captures,
chunks,
stack: Default::default(),
}
} else {
todo!()
}
}
pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars_at(0)
}
@ -2003,8 +2034,9 @@ impl Clone for Buffer {
selections_last_update: self.selections_last_update.clone(),
deferred_ops: self.deferred_ops.clone(),
file: self.file.clone(),
cursor: tree_sitter::QueryCursor::new(),
language: self.language.clone(),
tree: Mutex::new(self.tree.lock().clone()),
tree: self.tree.clone(),
is_parsing: false,
deferred_replicas: self.deferred_replicas.clone(),
replica_id: self.replica_id,
@ -2135,6 +2167,25 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
}
}
pub struct HighlightedChunksIter<'a, T: tree_sitter::TextProvider<'a>> {
chunks: ChunksIter<'a>,
captures: tree_sitter::QueryCaptures<'a, 'a, T>,
stack: Vec<(usize, usize)>,
}
impl<'a, T: tree_sitter::TextProvider<'a>> Iterator for HighlightedChunksIter<'a, T> {
type Item = (&'a str, usize);
fn next(&mut self) -> Option<Self::Item> {
if let Some((mat, capture_ix)) = self.captures.next() {
let capture = mat.captures[capture_ix as usize];
let range = capture.node.range();
}
todo!()
}
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
struct FragmentId(Arc<[u16]>);
@ -3276,7 +3327,7 @@ mod tests {
let buffer = Buffer::from_history(0, History::new(text.into()), None, rust_lang, ctx);
assert!(buffer.is_parsing);
assert!(buffer.syntax_tree().is_none());
assert!(buffer.tree.is_none());
buffer
});
@ -3390,7 +3441,7 @@ mod tests {
fn get_tree_sexp(buffer: &ModelHandle<Buffer>, ctx: &gpui::TestAppContext) -> String {
buffer.read_with(ctx, |buffer, _| {
buffer.syntax_tree().unwrap().root_node().to_sexp()
buffer.tree.as_ref().unwrap().0.root_node().to_sexp()
})
}
}