Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/algo.rs')
| -rw-r--r-- | crates/syntax/src/algo.rs | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs index 2acb215831..3b85b137aa 100644 --- a/crates/syntax/src/algo.rs +++ b/crates/syntax/src/algo.rs @@ -3,8 +3,8 @@ use itertools::Itertools; use crate::{ - AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, - TextSize, + syntax_editor::Element, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, + SyntaxToken, TextRange, TextSize, }; /// Returns ancestors of the node at the offset, sorted by length. This should @@ -89,6 +89,26 @@ pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNod Some(res) } +pub fn least_common_ancestor_element(u: impl Element, v: impl Element) -> Option<SyntaxNode> { + let u = u.syntax_element(); + let v = v.syntax_element(); + if u == v { + return match u { + NodeOrToken::Node(node) => Some(node), + NodeOrToken::Token(token) => token.parent(), + }; + } + + let u_depth = u.ancestors().count(); + let v_depth = v.ancestors().count(); + let keep = u_depth.min(v_depth); + + let u_candidates = u.ancestors().skip(u_depth - keep); + let v_candidates = v.ancestors().skip(v_depth - keep); + let (res, _) = u_candidates.zip(v_candidates).find(|(x, y)| x == y)?; + Some(res) +} + pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> { me.syntax().siblings(direction).skip(1).find_map(T::cast) } |