Merge pull request #1912 from zed-industries/matching-brackets-must-contain-range
Fix enclosing-bracket bug that appeared in JS for loops
This commit is contained in:
commit
0b0fe91545
2 changed files with 79 additions and 18 deletions
|
@ -2225,11 +2225,12 @@ impl BufferSnapshot {
|
||||||
range: Range<T>,
|
range: Range<T>,
|
||||||
) -> Option<(Range<usize>, Range<usize>)> {
|
) -> Option<(Range<usize>, Range<usize>)> {
|
||||||
// Find bracket pairs that *inclusively* contain the given range.
|
// Find bracket pairs that *inclusively* contain the given range.
|
||||||
let range = range.start.to_offset(self).saturating_sub(1)
|
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||||
..self.len().min(range.end.to_offset(self) + 1);
|
let mut matches = self.syntax.matches(
|
||||||
let mut matches = self.syntax.matches(range, &self.text, |grammar| {
|
range.start.saturating_sub(1)..self.len().min(range.end + 1),
|
||||||
grammar.brackets_config.as_ref().map(|c| &c.query)
|
&self.text,
|
||||||
});
|
|grammar| grammar.brackets_config.as_ref().map(|c| &c.query),
|
||||||
|
);
|
||||||
let configs = matches
|
let configs = matches
|
||||||
.grammars()
|
.grammars()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2252,18 +2253,20 @@ impl BufferSnapshot {
|
||||||
|
|
||||||
matches.advance();
|
matches.advance();
|
||||||
|
|
||||||
if let Some((open, close)) = open.zip(close) {
|
let Some((open, close)) = open.zip(close) else { continue };
|
||||||
let len = close.end - open.start;
|
if open.start > range.start || close.end < range.end {
|
||||||
|
continue;
|
||||||
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 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
|
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!(
|
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((
|
Some((
|
||||||
Point::new(0, 6)..Point::new(0, 7),
|
Point::new(0, 6)..Point::new(0, 7),
|
||||||
Point::new(4, 0)..Point::new(4, 1)
|
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]
|
#[gpui::test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue