[ty] Add CoveringNode::find_last
This routine lets us climb up the AST tree when we find a contiguous sequence of nodes that satisfy our predicate. This will be useful for making things like `a.b.<CURSOR>` work. That is, we don't want the `ExprAttribute` closest to a leaf. We also don't always want the `ExprAttribute` closest to the root. Rather, (I think) we want the `ExprAttribute` closest to the root that has an unbroken chain to the `ExprAttribute` closest to the leaf.
This commit is contained in:
committed by
Andrew Gallant
parent
65f32edbc7
commit
8fdf3fc47f
@@ -78,15 +78,44 @@ impl<'a> CoveringNode<'a> {
|
||||
self.nodes.get(penultimate).copied()
|
||||
}
|
||||
|
||||
/// Finds the minimal node that fully covers the range and fulfills the given predicate.
|
||||
pub(crate) fn find(mut self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Result<Self, Self> {
|
||||
match self.nodes.iter().rposition(|node| f(*node)) {
|
||||
Some(index) => {
|
||||
self.nodes.truncate(index + 1);
|
||||
Ok(self)
|
||||
}
|
||||
None => Err(self),
|
||||
/// Finds the first node that fully covers the range and fulfills
|
||||
/// the given predicate.
|
||||
///
|
||||
/// The "first" here means that the node closest to a leaf is
|
||||
/// returned.
|
||||
pub(crate) fn find_first(mut self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Result<Self, Self> {
|
||||
let Some(index) = self.find_first_index(f) else {
|
||||
return Err(self);
|
||||
};
|
||||
self.nodes.truncate(index + 1);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Finds the last node that fully covers the range and fulfills
|
||||
/// the given predicate.
|
||||
///
|
||||
/// The "last" here means that after finding the "first" such node,
|
||||
/// the highest ancestor found satisfying the given predicate is
|
||||
/// returned. Note that this is *not* the same as finding the node
|
||||
/// closest to the root that satisfies the given predictate.
|
||||
pub(crate) fn find_last(mut self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Result<Self, Self> {
|
||||
let Some(mut index) = self.find_first_index(&f) else {
|
||||
return Err(self);
|
||||
};
|
||||
while index > 0 && f(self.nodes[index - 1]) {
|
||||
index -= 1;
|
||||
}
|
||||
self.nodes.truncate(index + 1);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Finds the index of the node that fully covers the range and
|
||||
/// fulfills the given predicate.
|
||||
///
|
||||
/// If there are no nodes matching the given predictate, then
|
||||
/// `None` is returned.
|
||||
fn find_first_index(&self, f: impl Fn(AnyNodeRef<'a>) -> bool) -> Option<usize> {
|
||||
self.nodes.iter().rposition(|node| f(*node))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ pub(crate) fn find_goto_target(
|
||||
})?;
|
||||
|
||||
let covering_node = covering_node(parsed.syntax().into(), token.range())
|
||||
.find(|node| node.is_identifier() || node.is_expression())
|
||||
.find_first(|node| node.is_identifier() || node.is_expression())
|
||||
.ok()?;
|
||||
|
||||
tracing::trace!("Covering node is of kind {:?}", covering_node.node().kind());
|
||||
|
||||
Reference in New Issue
Block a user