Pick smaller node ancestors first when descending at offset

This commit is contained in:
Lukas Wirth 2021-09-14 14:09:52 +02:00
parent 538ac599d2
commit d1e489185f
2 changed files with 18 additions and 5 deletions

View File

@ -562,6 +562,8 @@ impl<'db> SemanticsImpl<'db> {
// Note this return type is deliberate as [`find_nodes_at_offset_with_descend`] wants to stop
// traversing the inner iterator when it finds a node.
// The outer iterator is over the tokens descendants
// The inner iterator is the ancestors of a descendant
fn descend_node_at_offset(
&self,
node: &SyntaxNode,
@ -570,8 +572,16 @@ impl<'db> SemanticsImpl<'db> {
// Handle macro token cases
node.token_at_offset(offset)
.map(move |token| self.descend_into_macros(token))
.map(|it| it.into_iter().map(move |it| self.token_ancestors_with_macros(it)))
.flatten()
.map(|descendants| {
descendants.into_iter().map(move |it| self.token_ancestors_with_macros(it))
})
// re-order the tokens from token_at_offset by returning the ancestors with the smaller first nodes first
// See algo::ancestors_at_offset, which uses the same approach
.kmerge_by(|left, right| {
left.clone()
.map(|node| node.text_range().len())
.lt(right.clone().map(|node| node.text_range().len()))
})
}
fn original_range(&self, node: &SyntaxNode) -> FileRange {
@ -589,11 +599,14 @@ impl<'db> SemanticsImpl<'db> {
fn token_ancestors_with_macros(
&self,
token: SyntaxToken,
) -> impl Iterator<Item = SyntaxNode> + '_ {
) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
token.parent().into_iter().flat_map(move |parent| self.ancestors_with_macros(parent))
}
fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
fn ancestors_with_macros(
&self,
node: SyntaxNode,
) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
let node = self.find_file(node);
node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
}

View File

@ -525,7 +525,7 @@ impl InFile<SyntaxNode> {
pub fn ancestors_with_macros(
self,
db: &dyn db::AstDatabase,
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
iter::successors(Some(self), move |node| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)),
None => {