diff options
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/node.rs | 75 | ||||
| -rw-r--r-- | src/syntax/source.rs | 15 |
2 files changed, 44 insertions, 46 deletions
diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 392633f6..afbebe97 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -204,14 +204,6 @@ impl SyntaxNode { Ok(()) } - /// If the span points into this node, convert it to a byte range. - pub(super) fn range(&self, span: Span, offset: usize) -> Option<Range<usize>> { - match &self.0 { - Repr::Inner(inner) => inner.range(span, offset), - _ => (self.span() == span).then(|| offset..offset + self.len()), - } - } - /// Whether this is a leaf node. pub(super) fn is_leaf(&self) -> bool { matches!(self.0, Repr::Leaf(_)) @@ -429,40 +421,6 @@ impl InnerNode { Ok(()) } - /// If the span points into this node, convert it to a byte range. - fn range(&self, span: Span, mut offset: usize) -> Option<Range<usize>> { - // Check whether we found it. - if span == self.span { - return Some(offset..offset + self.len); - } - - // The parent of a subtree has a smaller span number than all of its - // descendants. Therefore, we can bail out early if the target span's - // number is smaller than our number. - if span.number() < self.span.number() { - return None; - } - - let mut children = self.children.iter().peekable(); - while let Some(child) = children.next() { - // Every node in this child's subtree has a smaller span number than - // the next sibling. Therefore we only need to recurse if the next - // sibling's span number is larger than the target span's number. - if children - .peek() - .map_or(true, |next| next.span().number() > span.number()) - { - if let Some(range) = child.range(span, offset) { - return Some(range); - } - } - - offset += child.len(); - } - - None - } - /// Replaces a range of children with a replacement. /// /// May have mutated the children if it returns `Err(_)`. @@ -669,6 +627,39 @@ impl<'a> LinkedNode<'a> { back: self.offset + self.len(), } } + + /// Find a descendant with the given span. + pub fn find(&self, span: Span) -> Option<LinkedNode<'a>> { + if self.span() == span { + return Some(self.clone()); + } + + if let Repr::Inner(inner) = &self.0 { + // The parent of a subtree has a smaller span number than all of its + // descendants. Therefore, we can bail out early if the target span's + // number is smaller than our number. + if span.number() < inner.span.number() { + return None; + } + + let mut children = self.children().peekable(); + while let Some(child) = children.next() { + // Every node in this child's subtree has a smaller span number than + // the next sibling. Therefore we only need to recurse if the next + // sibling's span number is larger than the target span's number. + if children + .peek() + .map_or(true, |next| next.span().number() > span.number()) + { + if let Some(found) = child.find(span) { + return Some(found); + } + } + } + } + + None + } } /// Access to parents and siblings. diff --git a/src/syntax/source.rs b/src/syntax/source.rs index f00d779b..607a2603 100644 --- a/src/syntax/source.rs +++ b/src/syntax/source.rs @@ -9,7 +9,7 @@ use comemo::Prehashed; use unscanny::Scanner; use super::ast::Markup; -use super::{is_newline, parse, reparse, Span, SyntaxNode}; +use super::{is_newline, parse, reparse, LinkedNode, Span, SyntaxNode}; use crate::diag::SourceResult; use crate::util::{PathExt, StrExt}; @@ -149,13 +149,20 @@ impl Source { self.lines.len() } + /// Find the node with the given span. + /// + /// Panics if the span does not point into this source file. + pub fn find(&self, span: Span) -> LinkedNode<'_> { + LinkedNode::new(&self.root) + .find(span) + .expect("span does not point into this source file") + } + /// Map a span that points into this source file to a byte range. /// /// Panics if the span does not point into this source file. pub fn range(&self, span: Span) -> Range<usize> { - self.root - .range(span, 0) - .expect("span does not point into this source file") + self.find(span).range() } /// Return the index of the UTF-16 code unit at the byte index. |
