summaryrefslogtreecommitdiff
path: root/src/syntax/linked.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/syntax/linked.rs')
-rw-r--r--src/syntax/linked.rs92
1 files changed, 58 insertions, 34 deletions
diff --git a/src/syntax/linked.rs b/src/syntax/linked.rs
index 0d9d0c78..2826835e 100644
--- a/src/syntax/linked.rs
+++ b/src/syntax/linked.rs
@@ -29,6 +29,11 @@ impl<'a> LinkedNode<'a> {
self.node
}
+ /// The index of this node in its parent's children list.
+ pub fn index(&self) -> usize {
+ self.index
+ }
+
/// The absolute byte offset of the this node in the source file.
pub fn offset(&self) -> usize {
self.offset
@@ -40,18 +45,13 @@ impl<'a> LinkedNode<'a> {
}
/// Get this node's children.
- pub fn children(
- &self,
- ) -> impl DoubleEndedIterator<Item = LinkedNode<'a>>
- + ExactSizeIterator<Item = LinkedNode<'a>>
- + '_ {
- let parent = Rc::new(self.clone());
- let mut offset = self.offset;
- self.node.children().enumerate().map(move |(index, node)| {
- let child = Self { node, parent: Some(parent.clone()), index, offset };
- offset += node.len();
- child
- })
+ pub fn children(&self) -> LinkedChildren<'a> {
+ LinkedChildren {
+ parent: Rc::new(self.clone()),
+ iter: self.node.children().enumerate(),
+ front: self.offset,
+ back: self.offset + self.len(),
+ }
}
}
@@ -64,7 +64,7 @@ impl<'a> LinkedNode<'a> {
/// Get the kind of this node's parent.
pub fn parent_kind(&self) -> Option<&'a SyntaxKind> {
- self.parent().map(|parent| parent.node.kind())
+ Some(self.parent()?.node.kind())
}
/// Get the first previous non-trivia sibling node.
@@ -81,11 +81,6 @@ impl<'a> LinkedNode<'a> {
}
}
- /// Get the kind of this node's first previous non-trivia sibling.
- pub fn prev_sibling_kind(&self) -> Option<&'a SyntaxKind> {
- self.prev_sibling().map(|parent| parent.node.kind())
- }
-
/// Get the next non-trivia sibling node.
pub fn next_sibling(&self) -> Option<Self> {
let parent = self.parent()?;
@@ -99,11 +94,6 @@ impl<'a> LinkedNode<'a> {
Some(next)
}
}
-
- /// Get the kind of this node's next non-trivia sibling.
- pub fn next_sibling_kind(&self) -> Option<&'a SyntaxKind> {
- self.next_sibling().map(|parent| parent.node.kind())
- }
}
/// Access to leafs.
@@ -198,6 +188,51 @@ impl Debug for LinkedNode<'_> {
}
}
+/// An iterator over the children of a linked node.
+pub struct LinkedChildren<'a> {
+ parent: Rc<LinkedNode<'a>>,
+ iter: std::iter::Enumerate<std::slice::Iter<'a, SyntaxNode>>,
+ front: usize,
+ back: usize,
+}
+
+impl<'a> Iterator for LinkedChildren<'a> {
+ type Item = LinkedNode<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(index, node)| {
+ let offset = self.front;
+ self.front += node.len();
+ LinkedNode {
+ node,
+ parent: Some(self.parent.clone()),
+ index,
+ offset,
+ }
+ })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl DoubleEndedIterator for LinkedChildren<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back().map(|(index, node)| {
+ self.back -= node.len();
+ LinkedNode {
+ node,
+ parent: Some(self.parent.clone()),
+ index,
+ offset: self.back,
+ }
+ })
+ }
+}
+
+impl ExactSizeIterator for LinkedChildren<'_> {}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -236,15 +271,4 @@ mod tests {
assert_eq!(leaf.kind(), &SyntaxKind::Space { newlines: 0 });
assert_eq!(next.kind(), &SyntaxKind::Int(10));
}
-
- #[test]
- fn test_linked_node_leaf_at() {
- let source = Source::detached("");
- let leaf = LinkedNode::new(source.root()).leaf_at(0).unwrap();
- assert_eq!(leaf.kind(), &SyntaxKind::Markup { min_indent: 0 });
-
- let source = Source::detached("Hello\n");
- let leaf = LinkedNode::new(source.root()).leaf_at(6).unwrap();
- assert_eq!(leaf.kind(), &SyntaxKind::Space { newlines: 1 });
- }
}