Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/matching_brace.rs')
| -rw-r--r-- | crates/ide/src/matching_brace.rs | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/crates/ide/src/matching_brace.rs b/crates/ide/src/matching_brace.rs index faf3642942..f21f3fe677 100644 --- a/crates/ide/src/matching_brace.rs +++ b/crates/ide/src/matching_brace.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + use syntax::{ SourceFile, SyntaxKind, T, TextSize, ast::{self, AstNode}, @@ -17,25 +19,40 @@ use syntax::{ pub(crate) fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<(TextSize, TextSize)> { const BRACES: &[SyntaxKind] = &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>], T![|], T![|]]; - let (brace_token, brace_idx) = file + + if let Some((brace_token, brace_idx)) = file .syntax() .token_at_offset(offset) .filter_map(|node| { let idx = BRACES.iter().position(|&brace| brace == node.kind())?; Some((node, idx)) }) - .last()?; - let parent = brace_token.parent()?; - if brace_token.kind() == T![|] && !ast::ParamList::can_cast(parent.kind()) { - cov_mark::hit!(pipes_not_braces); - return None; + .last() + { + let parent = brace_token.parent()?; + if brace_token.kind() == T![|] && !ast::ParamList::can_cast(parent.kind()) { + cov_mark::hit!(pipes_not_braces); + return None; + } + let matching_kind = BRACES[brace_idx ^ 1]; + let matching_node = parent + .children_with_tokens() + .filter_map(|it| it.into_token()) + .find(|node| node.kind() == matching_kind && node != &brace_token)?; + Some((brace_token.text_range().start(), matching_node.text_range().start())) + } else { + // when the offset is not at a brace + let thingy = file.syntax().token_at_offset(offset).last()?; + // find first parent + thingy.parent_ancestors().find_map(|x| { + x.children_with_tokens() + .filter_map(|it| it.into_token()) + // with ending brace + .filter(|node| BRACES.contains(&node.kind())) + .last() + .map(|x| (thingy.text_range().start(), x.text_range().start())) + }) } - let matching_kind = BRACES[brace_idx ^ 1]; - let matching_node = parent - .children_with_tokens() - .filter_map(|it| it.into_token()) - .find(|node| node.kind() == matching_kind && node != &brace_token)?; - Some((brace_token.text_range().start(), matching_node.text_range().start())) } #[cfg(test)] |