diff options
Diffstat (limited to 'crates/ra_syntax/src/algo.rs')
-rw-r--r-- | crates/ra_syntax/src/algo.rs | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index e2b4f0388..06b45135c 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs | |||
@@ -1,18 +1,14 @@ | |||
1 | pub mod visit; | 1 | pub mod visit; |
2 | 2 | ||
3 | use rowan::TransparentNewType; | 3 | use crate::{SyntaxNode, TextRange, TextUnit, AstNode, Direction, SyntaxToken, SyntaxElement}; |
4 | 4 | ||
5 | use crate::{SyntaxNode, TextRange, TextUnit, AstNode, Direction}; | 5 | pub use rowan::TokenAtOffset; |
6 | 6 | ||
7 | pub use rowan::LeafAtOffset; | 7 | pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffset<SyntaxToken> { |
8 | 8 | match node.0.token_at_offset(offset) { | |
9 | pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset<&SyntaxNode> { | 9 | TokenAtOffset::None => TokenAtOffset::None, |
10 | match node.0.leaf_at_offset(offset) { | 10 | TokenAtOffset::Single(n) => TokenAtOffset::Single(n.into()), |
11 | LeafAtOffset::None => LeafAtOffset::None, | 11 | TokenAtOffset::Between(l, r) => TokenAtOffset::Between(l.into(), r.into()), |
12 | LeafAtOffset::Single(n) => LeafAtOffset::Single(SyntaxNode::from_repr(n)), | ||
13 | LeafAtOffset::Between(l, r) => { | ||
14 | LeafAtOffset::Between(SyntaxNode::from_repr(l), SyntaxNode::from_repr(r)) | ||
15 | } | ||
16 | } | 12 | } |
17 | } | 13 | } |
18 | 14 | ||
@@ -26,16 +22,29 @@ pub fn find_leaf_at_offset(node: &SyntaxNode, offset: TextUnit) -> LeafAtOffset< | |||
26 | /// | 22 | /// |
27 | /// then the left node will be silently preferred. | 23 | /// then the left node will be silently preferred. |
28 | pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { | 24 | pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { |
29 | find_leaf_at_offset(syntax, offset).find_map(|leaf| leaf.ancestors().find_map(N::cast)) | 25 | find_token_at_offset(syntax, offset) |
26 | .find_map(|leaf| leaf.parent().ancestors().find_map(N::cast)) | ||
30 | } | 27 | } |
31 | 28 | ||
32 | /// Finds the first sibling in the given direction which is not `trivia` | 29 | /// Finds the first sibling in the given direction which is not `trivia` |
33 | pub fn non_trivia_sibling(node: &SyntaxNode, direction: Direction) -> Option<&SyntaxNode> { | 30 | pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> { |
34 | node.siblings(direction).skip(1).find(|node| !node.kind().is_trivia()) | 31 | return match element { |
32 | SyntaxElement::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia), | ||
33 | SyntaxElement::Token(token) => { | ||
34 | token.siblings_with_tokens(direction).skip(1).find(not_trivia) | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | fn not_trivia(element: &SyntaxElement) -> bool { | ||
39 | match element { | ||
40 | SyntaxElement::Node(_) => true, | ||
41 | SyntaxElement::Token(token) => !token.kind().is_trivia(), | ||
42 | } | ||
43 | } | ||
35 | } | 44 | } |
36 | 45 | ||
37 | pub fn find_covering_node(root: &SyntaxNode, range: TextRange) -> &SyntaxNode { | 46 | pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement { |
38 | SyntaxNode::from_repr(root.0.covering_node(range)) | 47 | root.0.covering_node(range).into() |
39 | } | 48 | } |
40 | 49 | ||
41 | // Replace with `std::iter::successors` in `1.34.0` | 50 | // Replace with `std::iter::successors` in `1.34.0` |