mun_syntax/utils.rs
1use crate::{AstNode, SyntaxNode, TextSize};
2use itertools::Itertools;
3
4/// Returns ancestors of the node at the offset, sorted by length. This should do the right thing at
5/// an edge, e.g. when searching for expressions at `{ $0foo }` we will get the name reference
6/// instead of the whole block, which we would get if we just did `find_token_at_offset(...).
7/// flat_map(|t| t.parent().ancestors())`.
8pub fn ancestors_at_offset(
9 node: &SyntaxNode,
10 offset: TextSize,
11) -> impl Iterator<Item = SyntaxNode> {
12 node.token_at_offset(offset)
13 .map(|token| token.parent_ancestors())
14 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
15}
16
17/// Finds a node of specific Ast type at offset. Note that this is slightly imprecise: if the cursor
18/// is strictly between two nodes of the desired type, as in
19///
20/// ```mun
21/// struct Foo {}|struct Bar;
22/// ```
23///
24/// then the shorter node will be silently preferred.
25pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextSize) -> Option<N> {
26 ancestors_at_offset(syntax, offset).find_map(N::cast)
27}