Skip to content

Commit c834a52

Browse files
Merge pull request #21792 from bend-n/make-matching-brace-almost-always-proc
make matching brace work when cursor not at bracket
2 parents 7696e68 + 53ceaf7 commit c834a52

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

crates/ide/src/matching_brace.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,37 @@ use syntax::{
1717
pub(crate) fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> {
1818
const BRACES: &[SyntaxKind] =
1919
&[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>], T![|], T![|]];
20-
let (brace_token, brace_idx) = file
21-
.syntax()
22-
.token_at_offset(offset)
20+
let current = file.syntax().token_at_offset(offset);
21+
if let Some((brace_token, brace_idx)) = current
22+
.clone()
2323
.filter_map(|node| {
2424
let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
2525
Some((node, idx))
2626
})
27-
.last()?;
28-
let parent = brace_token.parent()?;
29-
if brace_token.kind() == T![|] && !ast::ParamList::can_cast(parent.kind()) {
30-
cov_mark::hit!(pipes_not_braces);
31-
return None;
27+
.last()
28+
{
29+
let parent = brace_token.parent()?;
30+
if brace_token.kind() == T![|] && !ast::ParamList::can_cast(parent.kind()) {
31+
cov_mark::hit!(pipes_not_braces);
32+
return None;
33+
}
34+
let matching_kind = BRACES[brace_idx ^ 1];
35+
let matching_node = parent
36+
.children_with_tokens()
37+
.filter_map(|it| it.into_token())
38+
.find(|node| node.kind() == matching_kind && node != &brace_token)?;
39+
Some(matching_node.text_range().start())
40+
} else {
41+
// when the offset is not at a brace, find first parent
42+
current.last()?.parent_ancestors().find_map(|x| {
43+
x.children_with_tokens()
44+
.filter_map(|it| it.into_token())
45+
// with ending brace
46+
.filter(|node| BRACES.contains(&node.kind()))
47+
.last()
48+
.map(|x| x.text_range().start())
49+
})
3250
}
33-
let matching_kind = BRACES[brace_idx ^ 1];
34-
let matching_node = parent
35-
.children_with_tokens()
36-
.filter_map(|it| it.into_token())
37-
.find(|node| node.kind() == matching_kind && node != &brace_token)?;
38-
Some(matching_node.text_range().start())
3951
}
4052

4153
#[cfg(test)]
@@ -64,6 +76,14 @@ mod tests {
6476
"fn func(x) { return (2 * (x + 3)$0) + 5;}",
6577
"fn func(x) { return $0(2 * (x + 3)) + 5;}",
6678
);
79+
do_check(
80+
"fn func(x) { return (2 * (x $0+ 3)) + 5;}",
81+
"fn func(x) { return (2 * (x + 3$0)) + 5;}",
82+
);
83+
do_check(
84+
"fn func(x) { re$0turn (2 * (x + 3)) + 5;}",
85+
"fn func(x) { return (2 * (x + 3)) + 5;$0}",
86+
);
6787

6888
{
6989
cov_mark::check!(pipes_not_braces);

0 commit comments

Comments
 (0)