aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/matching_brace.rs27
1 files changed, 22 insertions, 5 deletions
diff --git a/crates/ra_ide/src/matching_brace.rs b/crates/ra_ide/src/matching_brace.rs
index 407a9636d..685ba10ad 100644
--- a/crates/ra_ide/src/matching_brace.rs
+++ b/crates/ra_ide/src/matching_brace.rs
@@ -1,8 +1,12 @@
1use ra_syntax::{ast::AstNode, SourceFile, SyntaxKind, TextSize, T}; 1use ra_syntax::{
2 ast::{self, AstNode},
3 SourceFile, SyntaxKind, TextSize, T,
4};
5use test_utils::mark;
2 6
3// Feature: Matching Brace 7// Feature: Matching Brace
4// 8//
5// If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair, 9// If the cursor is on any brace (`<>(){}[]||`) which is a part of a brace-pair,
6// moves cursor to the matching brace. It uses the actual parser to determine 10// moves cursor to the matching brace. It uses the actual parser to determine
7// braces, so it won't confuse generics with comparisons. 11// braces, so it won't confuse generics with comparisons.
8// 12//
@@ -13,8 +17,8 @@ use ra_syntax::{ast::AstNode, SourceFile, SyntaxKind, TextSize, T};
13// |=== 17// |===
14pub fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> { 18pub fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> {
15 const BRACES: &[SyntaxKind] = 19 const BRACES: &[SyntaxKind] =
16 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>]]; 20 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>], T![|], T![|]];
17 let (brace_node, brace_idx) = file 21 let (brace_token, brace_idx) = file
18 .syntax() 22 .syntax()
19 .token_at_offset(offset) 23 .token_at_offset(offset)
20 .filter_map(|node| { 24 .filter_map(|node| {
@@ -22,7 +26,11 @@ pub fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> {
22 Some((node, idx)) 26 Some((node, idx))
23 }) 27 })
24 .next()?; 28 .next()?;
25 let parent = brace_node.parent(); 29 let parent = brace_token.parent();
30 if brace_token.kind() == T![|] && !ast::ParamList::can_cast(parent.kind()) {
31 mark::hit!(pipes_not_braces);
32 return None;
33 }
26 let matching_kind = BRACES[brace_idx ^ 1]; 34 let matching_kind = BRACES[brace_idx ^ 1];
27 let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?; 35 let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?;
28 Some(matching_node.text_range().start()) 36 Some(matching_node.text_range().start())
@@ -48,5 +56,14 @@ mod tests {
48 } 56 }
49 57
50 do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }"); 58 do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }");
59 do_check("fn main() { |x: i32|<|> x * 2;}", "fn main() { <|>|x: i32| x * 2;}");
60
61 {
62 mark::check!(pipes_not_braces);
63 do_check(
64 "fn main() { match 92 { 1 | 2 |<|> 3 => 92 } }",
65 "fn main() { match 92 { 1 | 2 |<|> 3 => 92 } }",
66 );
67 }
51 } 68 }
52} 69}