Fix enclosing-bracket bug that appeared in JS for loops
Previously, we were relying on the tree-sitter query's range restriction to avoid returning brackets that did not contain the given range. But the query's range restriction only guarantees that we don't descend into parent nodes unless they intersect the range.
This commit is contained in:
parent
5e7652698d
commit
aeea47323a
2 changed files with 79 additions and 18 deletions
|
@ -2225,11 +2225,12 @@ impl BufferSnapshot {
|
|||
range: Range<T>,
|
||||
) -> Option<(Range<usize>, Range<usize>)> {
|
||||
// Find bracket pairs that *inclusively* contain the given range.
|
||||
let range = range.start.to_offset(self).saturating_sub(1)
|
||||
..self.len().min(range.end.to_offset(self) + 1);
|
||||
let mut matches = self.syntax.matches(range, &self.text, |grammar| {
|
||||
grammar.brackets_config.as_ref().map(|c| &c.query)
|
||||
});
|
||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||
let mut matches = self.syntax.matches(
|
||||
range.start.saturating_sub(1)..self.len().min(range.end + 1),
|
||||
&self.text,
|
||||
|grammar| grammar.brackets_config.as_ref().map(|c| &c.query),
|
||||
);
|
||||
let configs = matches
|
||||
.grammars()
|
||||
.iter()
|
||||
|
@ -2252,18 +2253,20 @@ impl BufferSnapshot {
|
|||
|
||||
matches.advance();
|
||||
|
||||
if let Some((open, close)) = open.zip(close) {
|
||||
let len = close.end - open.start;
|
||||
|
||||
if let Some((existing_open, existing_close)) = &result {
|
||||
let existing_len = existing_close.end - existing_open.start;
|
||||
if len > existing_len {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result = Some((open, close));
|
||||
let Some((open, close)) = open.zip(close) else { continue };
|
||||
if open.start > range.start || close.end < range.end {
|
||||
continue;
|
||||
}
|
||||
let len = close.end - open.start;
|
||||
|
||||
if let Some((existing_open, existing_close)) = &result {
|
||||
let existing_len = existing_close.end - existing_open.start;
|
||||
if len > existing_len {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result = Some((open, close));
|
||||
}
|
||||
|
||||
result
|
||||
|
|
|
@ -573,14 +573,72 @@ fn test_enclosing_bracket_ranges(cx: &mut MutableAppContext) {
|
|||
))
|
||||
);
|
||||
|
||||
// Regression test: avoid crash when querying at the end of the buffer.
|
||||
assert_eq!(
|
||||
buffer.enclosing_bracket_point_ranges(buffer.len() - 1..buffer.len()),
|
||||
buffer.enclosing_bracket_point_ranges(Point::new(4, 1)..Point::new(4, 1)),
|
||||
Some((
|
||||
Point::new(0, 6)..Point::new(0, 7),
|
||||
Point::new(4, 0)..Point::new(4, 1)
|
||||
))
|
||||
);
|
||||
|
||||
// Regression test: avoid crash when querying at the end of the buffer.
|
||||
assert_eq!(
|
||||
buffer.enclosing_bracket_point_ranges(Point::new(4, 1)..Point::new(5, 0)),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(
|
||||
cx: &mut MutableAppContext,
|
||||
) {
|
||||
let javascript_language = Arc::new(
|
||||
Language::new(
|
||||
LanguageConfig {
|
||||
name: "JavaScript".into(),
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_javascript::language()),
|
||||
)
|
||||
.with_brackets_query(
|
||||
r#"
|
||||
("{" @open "}" @close)
|
||||
("(" @open ")" @close)
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
cx.set_global(Settings::test(cx));
|
||||
let buffer = cx.add_model(|cx| {
|
||||
let text = "
|
||||
for (const a in b) {
|
||||
// a comment that's longer than the for-loop header
|
||||
}
|
||||
"
|
||||
.unindent();
|
||||
Buffer::new(0, text, cx).with_language(javascript_language, cx)
|
||||
});
|
||||
|
||||
let buffer = buffer.read(cx);
|
||||
assert_eq!(
|
||||
buffer.enclosing_bracket_point_ranges(Point::new(0, 18)..Point::new(0, 18)),
|
||||
Some((
|
||||
Point::new(0, 4)..Point::new(0, 5),
|
||||
Point::new(0, 17)..Point::new(0, 18)
|
||||
))
|
||||
);
|
||||
|
||||
// Regression test: even though the parent node of the parentheses (the for loop) does
|
||||
// intersect the given range, the parentheses themselves do not contain the range, so
|
||||
// they should not be returned. Only the curly braces contain the range.
|
||||
assert_eq!(
|
||||
buffer.enclosing_bracket_point_ranges(Point::new(0, 20)..Point::new(0, 20)),
|
||||
Some((
|
||||
Point::new(0, 19)..Point::new(0, 20),
|
||||
Point::new(2, 0)..Point::new(2, 1)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue