Skip to content

Commit c96c5ed

Browse files
committed
language: Make TreeSitterData only shared between snapshots of the same version
1 parent d6241b1 commit c96c5ed

File tree

3 files changed

+119
-143
lines changed

3 files changed

+119
-143
lines changed

crates/editor/src/bracket_colorization.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Editor {
4545

4646
let bracket_matches_by_accent = self.visible_excerpts(false, cx).into_iter().fold(
4747
HashMap::default(),
48-
|mut acc, (excerpt_id, (buffer, buffer_version, buffer_range))| {
48+
|mut acc, (excerpt_id, (buffer, _, buffer_range))| {
4949
let buffer_snapshot = buffer.read(cx).snapshot();
5050
if language_settings::language_settings(
5151
buffer_snapshot.language().map(|language| language.name()),
@@ -62,7 +62,7 @@ impl Editor {
6262
let brackets_by_accent = buffer_snapshot
6363
.fetch_bracket_ranges(
6464
buffer_range.start..buffer_range.end,
65-
Some((&buffer_version, fetched_chunks)),
65+
Some(fetched_chunks),
6666
)
6767
.into_iter()
6868
.flat_map(|(chunk_range, pairs)| {

crates/language/src/buffer.rs

Lines changed: 116 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ pub use crate::{
2222
proto,
2323
};
2424
use anyhow::{Context as _, Result};
25+
use clock::Lamport;
2526
pub use clock::ReplicaId;
26-
use clock::{Global, Lamport};
2727
use collections::{HashMap, HashSet};
2828
use fs::MTime;
2929
use futures::channel::oneshot;
@@ -33,7 +33,7 @@ use gpui::{
3333
};
3434

3535
use lsp::{LanguageServerId, NumberOrString};
36-
use parking_lot::{Mutex, RawMutex, lock_api::MutexGuard};
36+
use parking_lot::Mutex;
3737
use serde::{Deserialize, Serialize};
3838
use serde_json::Value;
3939
use settings::WorktreeId;
@@ -130,26 +130,30 @@ pub struct Buffer {
130130
has_unsaved_edits: Cell<(clock::Global, bool)>,
131131
change_bits: Vec<rc::Weak<Cell<bool>>>,
132132
_subscriptions: Vec<gpui::Subscription>,
133-
tree_sitter_data: Arc<Mutex<TreeSitterData>>,
133+
tree_sitter_data: Arc<TreeSitterData>,
134134
}
135135

136-
#[derive(Debug, Clone)]
136+
#[derive(Debug)]
137137
pub struct TreeSitterData {
138138
chunks: RowChunks,
139-
brackets_by_chunks: Vec<Option<Vec<BracketMatch<usize>>>>,
139+
brackets_by_chunks: Mutex<Vec<Option<Vec<BracketMatch<usize>>>>>,
140140
}
141141

142142
const MAX_ROWS_IN_A_CHUNK: u32 = 50;
143143

144144
impl TreeSitterData {
145-
fn clear(&mut self) {
146-
self.brackets_by_chunks = vec![None; self.chunks.len()];
145+
fn clear(&mut self, snapshot: text::BufferSnapshot) {
146+
self.chunks = RowChunks::new(snapshot, MAX_ROWS_IN_A_CHUNK);
147+
self.brackets_by_chunks.get_mut().clear();
148+
self.brackets_by_chunks
149+
.get_mut()
150+
.resize(self.chunks.len(), None);
147151
}
148152

149153
fn new(snapshot: text::BufferSnapshot) -> Self {
150154
let chunks = RowChunks::new(snapshot, MAX_ROWS_IN_A_CHUNK);
151155
Self {
152-
brackets_by_chunks: vec![None; chunks.len()],
156+
brackets_by_chunks: Mutex::new(vec![None; chunks.len()]),
153157
chunks,
154158
}
155159
}
@@ -176,7 +180,7 @@ pub struct BufferSnapshot {
176180
remote_selections: TreeMap<ReplicaId, SelectionSet>,
177181
language: Option<Arc<Language>>,
178182
non_text_state_update_count: usize,
179-
tree_sitter_data: Arc<Mutex<TreeSitterData>>,
183+
tree_sitter_data: Arc<TreeSitterData>,
180184
}
181185

182186
/// The kind and amount of indentation in a particular line. For now,
@@ -1061,7 +1065,7 @@ impl Buffer {
10611065
let tree_sitter_data = TreeSitterData::new(snapshot);
10621066
Self {
10631067
saved_mtime,
1064-
tree_sitter_data: Arc::new(Mutex::new(tree_sitter_data)),
1068+
tree_sitter_data: Arc::new(tree_sitter_data),
10651069
saved_version: buffer.version(),
10661070
preview_version: buffer.version(),
10671071
reload_task: None,
@@ -1118,7 +1122,7 @@ impl Buffer {
11181122
file: None,
11191123
diagnostics: Default::default(),
11201124
remote_selections: Default::default(),
1121-
tree_sitter_data: Arc::new(Mutex::new(tree_sitter_data)),
1125+
tree_sitter_data: Arc::new(tree_sitter_data),
11221126
language,
11231127
non_text_state_update_count: 0,
11241128
}
@@ -1140,7 +1144,7 @@ impl Buffer {
11401144
BufferSnapshot {
11411145
text,
11421146
syntax,
1143-
tree_sitter_data: Arc::new(Mutex::new(tree_sitter_data)),
1147+
tree_sitter_data: Arc::new(tree_sitter_data),
11441148
file: None,
11451149
diagnostics: Default::default(),
11461150
remote_selections: Default::default(),
@@ -1169,7 +1173,7 @@ impl Buffer {
11691173
BufferSnapshot {
11701174
text,
11711175
syntax,
1172-
tree_sitter_data: Arc::new(Mutex::new(tree_sitter_data)),
1176+
tree_sitter_data: Arc::new(tree_sitter_data),
11731177
file: None,
11741178
diagnostics: Default::default(),
11751179
remote_selections: Default::default(),
@@ -1746,7 +1750,14 @@ impl Buffer {
17461750
self.syntax_map.lock().did_parse(syntax_snapshot);
17471751
self.request_autoindent(cx);
17481752
self.parse_status.0.send(ParseStatus::Idle).unwrap();
1749-
self.tree_sitter_data.lock().clear();
1753+
let snapshot = self.text.snapshot();
1754+
match Arc::get_mut(&mut self.tree_sitter_data) {
1755+
Some(tree_sitter_data) => tree_sitter_data.clear(snapshot),
1756+
None => {
1757+
let tree_sitter_data = TreeSitterData::new(snapshot);
1758+
self.tree_sitter_data = Arc::new(tree_sitter_data)
1759+
}
1760+
}
17501761
cx.emit(BufferEvent::Reparsed);
17511762
cx.notify();
17521763
}
@@ -4278,155 +4289,125 @@ impl BufferSnapshot {
42784289
pub fn fetch_bracket_ranges(
42794290
&self,
42804291
range: Range<usize>,
4281-
known_chunks: Option<(&Global, &HashSet<Range<BufferRow>>)>,
4292+
known_chunks: Option<&HashSet<Range<BufferRow>>>,
42824293
) -> HashMap<Range<BufferRow>, Vec<BracketMatch<usize>>> {
4283-
let mut tree_sitter_data = self.latest_tree_sitter_data().clone();
4284-
4285-
let known_chunks = match known_chunks {
4286-
Some((known_version, known_chunks)) => {
4287-
if !tree_sitter_data
4288-
.chunks
4289-
.version()
4290-
.changed_since(known_version)
4291-
{
4292-
known_chunks.clone()
4293-
} else {
4294-
HashSet::default()
4295-
}
4296-
}
4297-
None => HashSet::default(),
4298-
};
4294+
let known_chunks = known_chunks.cloned().unwrap_or_default();
42994295

4300-
let mut new_bracket_matches = HashMap::default();
43014296
let mut all_bracket_matches = HashMap::default();
43024297

4303-
for chunk in tree_sitter_data
4298+
for chunk in self
4299+
.tree_sitter_data
43044300
.chunks
43054301
.applicable_chunks(&[self.anchor_before(range.start)..self.anchor_after(range.end)])
43064302
{
43074303
if known_chunks.contains(&chunk.row_range()) {
43084304
continue;
43094305
}
4310-
let Some(chunk_range) = tree_sitter_data.chunks.chunk_range(chunk) else {
4306+
let Some(chunk_range) = self.tree_sitter_data.chunks.chunk_range(chunk) else {
43114307
continue;
43124308
};
4313-
let chunk_range = chunk_range.to_offset(&tree_sitter_data.chunks.snapshot);
4314-
4315-
let bracket_matches = match tree_sitter_data.brackets_by_chunks[chunk.id].take() {
4316-
Some(cached_brackets) => cached_brackets,
4317-
None => {
4318-
let mut all_brackets = Vec::new();
4319-
let mut opens = Vec::new();
4320-
let mut color_pairs = Vec::new();
4321-
4322-
let mut matches =
4323-
self.syntax
4324-
.matches(chunk_range.clone(), &self.text, |grammar| {
4325-
grammar.brackets_config.as_ref().map(|c| &c.query)
4326-
});
4327-
let configs = matches
4328-
.grammars()
4329-
.iter()
4330-
.map(|grammar| grammar.brackets_config.as_ref().unwrap())
4331-
.collect::<Vec<_>>();
4332-
4333-
while let Some(mat) = matches.peek() {
4334-
let mut open = None;
4335-
let mut close = None;
4336-
let syntax_layer_depth = mat.depth;
4337-
let config = configs[mat.grammar_index];
4338-
let pattern = &config.patterns[mat.pattern_index];
4339-
for capture in mat.captures {
4340-
if capture.index == config.open_capture_ix {
4341-
open = Some(capture.node.byte_range());
4342-
} else if capture.index == config.close_capture_ix {
4343-
close = Some(capture.node.byte_range());
4344-
}
4345-
}
4309+
let chunk_range = chunk_range.to_offset(&self);
43464310

4347-
matches.advance();
4311+
if let Some(cached_brackets) =
4312+
&self.tree_sitter_data.brackets_by_chunks.lock()[chunk.id]
4313+
{
4314+
all_bracket_matches.insert(chunk.row_range(), cached_brackets.clone());
4315+
continue;
4316+
}
43484317

4349-
let Some((open_range, close_range)) = open.zip(close) else {
4350-
continue;
4351-
};
4318+
let mut all_brackets = Vec::new();
4319+
let mut opens = Vec::new();
4320+
let mut color_pairs = Vec::new();
43524321

4353-
let bracket_range = open_range.start..=close_range.end;
4354-
if !bracket_range.overlaps(&chunk_range) {
4355-
continue;
4356-
}
4322+
let mut matches = self
4323+
.syntax
4324+
.matches(chunk_range.clone(), &self.text, |grammar| {
4325+
grammar.brackets_config.as_ref().map(|c| &c.query)
4326+
});
4327+
let configs = matches
4328+
.grammars()
4329+
.iter()
4330+
.map(|grammar| grammar.brackets_config.as_ref().unwrap())
4331+
.collect::<Vec<_>>();
4332+
4333+
while let Some(mat) = matches.peek() {
4334+
let mut open = None;
4335+
let mut close = None;
4336+
let syntax_layer_depth = mat.depth;
4337+
let config = configs[mat.grammar_index];
4338+
let pattern = &config.patterns[mat.pattern_index];
4339+
for capture in mat.captures {
4340+
if capture.index == config.open_capture_ix {
4341+
open = Some(capture.node.byte_range());
4342+
} else if capture.index == config.close_capture_ix {
4343+
close = Some(capture.node.byte_range());
4344+
}
4345+
}
43574346

4358-
let index = all_brackets.len();
4359-
all_brackets.push(BracketMatch {
4360-
open_range: open_range.clone(),
4361-
close_range: close_range.clone(),
4362-
newline_only: pattern.newline_only,
4363-
syntax_layer_depth,
4364-
color_index: None,
4365-
});
4347+
matches.advance();
43664348

4367-
// Certain languages have "brackets" that are not brackets, e.g. tags. and such
4368-
// bracket will match the entire tag with all text inside.
4369-
// For now, avoid highlighting any pair that has more than single char in each bracket.
4370-
// We need to colorize `<Element/>` bracket pairs, so cannot make this check stricter.
4371-
let should_color = !pattern.rainbow_exclude
4372-
&& (open_range.len() == 1 || close_range.len() == 1);
4373-
if should_color {
4374-
opens.push(open_range.clone());
4375-
color_pairs.push((open_range, close_range, index));
4376-
}
4377-
}
4349+
let Some((open_range, close_range)) = open.zip(close) else {
4350+
continue;
4351+
};
43784352

4379-
opens.sort_by_key(|r| (r.start, r.end));
4380-
opens.dedup_by(|a, b| a.start == b.start && a.end == b.end);
4381-
color_pairs.sort_by_key(|(_, close, _)| close.end);
4353+
let bracket_range = open_range.start..=close_range.end;
4354+
if !bracket_range.overlaps(&chunk_range) {
4355+
continue;
4356+
}
43824357

4383-
let mut open_stack = Vec::new();
4384-
let mut open_index = 0;
4385-
for (open, close, index) in color_pairs {
4386-
while open_index < opens.len() && opens[open_index].start < close.start {
4387-
open_stack.push(opens[open_index].clone());
4388-
open_index += 1;
4389-
}
4358+
let index = all_brackets.len();
4359+
all_brackets.push(BracketMatch {
4360+
open_range: open_range.clone(),
4361+
close_range: close_range.clone(),
4362+
newline_only: pattern.newline_only,
4363+
syntax_layer_depth,
4364+
color_index: None,
4365+
});
43904366

4391-
if open_stack.last() == Some(&open) {
4392-
let depth_index = open_stack.len() - 1;
4393-
all_brackets[index].color_index = Some(depth_index);
4394-
open_stack.pop();
4395-
}
4396-
}
4367+
// Certain languages have "brackets" that are not brackets, e.g. tags. and such
4368+
// bracket will match the entire tag with all text inside.
4369+
// For now, avoid highlighting any pair that has more than single char in each bracket.
4370+
// We need to colorize `<Element/>` bracket pairs, so cannot make this check stricter.
4371+
let should_color =
4372+
!pattern.rainbow_exclude && (open_range.len() == 1 || close_range.len() == 1);
4373+
if should_color {
4374+
opens.push(open_range.clone());
4375+
color_pairs.push((open_range, close_range, index));
4376+
}
4377+
}
43974378

4398-
all_brackets.sort_by_key(|bracket_match| {
4399-
(bracket_match.open_range.start, bracket_match.open_range.end)
4400-
});
4401-
new_bracket_matches.insert(chunk.id, all_brackets.clone());
4402-
all_brackets
4379+
opens.sort_by_key(|r| (r.start, r.end));
4380+
opens.dedup_by(|a, b| a.start == b.start && a.end == b.end);
4381+
color_pairs.sort_by_key(|(_, close, _)| close.end);
4382+
4383+
let mut open_stack = Vec::new();
4384+
let mut open_index = 0;
4385+
for (open, close, index) in color_pairs {
4386+
while open_index < opens.len() && opens[open_index].start < close.start {
4387+
open_stack.push(opens[open_index].clone());
4388+
open_index += 1;
44034389
}
4404-
};
4405-
all_bracket_matches.insert(chunk.row_range(), bracket_matches);
4406-
}
44074390

4408-
let mut latest_tree_sitter_data = self.latest_tree_sitter_data();
4409-
if latest_tree_sitter_data.chunks.version() == &self.version {
4410-
for (chunk_id, new_matches) in new_bracket_matches {
4411-
let old_chunks = &mut latest_tree_sitter_data.brackets_by_chunks[chunk_id];
4412-
if old_chunks.is_none() {
4413-
*old_chunks = Some(new_matches);
4391+
if open_stack.last() == Some(&open) {
4392+
let depth_index = open_stack.len() - 1;
4393+
all_brackets[index].color_index = Some(depth_index);
4394+
open_stack.pop();
44144395
}
44154396
}
4416-
}
44174397

4418-
all_bracket_matches
4419-
}
4398+
all_brackets.sort_by_key(|bracket_match| {
4399+
(bracket_match.open_range.start, bracket_match.open_range.end)
4400+
});
44204401

4421-
fn latest_tree_sitter_data(&self) -> MutexGuard<'_, RawMutex, TreeSitterData> {
4422-
let mut tree_sitter_data = self.tree_sitter_data.lock();
4423-
if self
4424-
.version
4425-
.changed_since(tree_sitter_data.chunks.version())
4426-
{
4427-
*tree_sitter_data = TreeSitterData::new(self.text.clone());
4402+
if let empty_slot @ None =
4403+
&mut self.tree_sitter_data.brackets_by_chunks.lock()[chunk.id]
4404+
{
4405+
*empty_slot = Some(all_brackets.clone());
4406+
}
4407+
all_bracket_matches.insert(chunk.row_range(), all_brackets);
44284408
}
4429-
tree_sitter_data
4409+
4410+
all_bracket_matches
44304411
}
44314412

44324413
pub fn all_bracket_ranges(

0 commit comments

Comments
 (0)