diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-12-15 22:51:55 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-12-15 23:11:20 +0100 |
| commit | b6202b646a0d5ecced301d9bac8bfcaf977d7ee4 (patch) | |
| tree | 7d42cb50f9e66153e7e8b2217009684e25f54f42 /src/syntax | |
| parent | f3980c704544a464f9729cc8bc9f97d3a7454769 (diff) | |
Reflection for castables
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/ast.rs | 7 | ||||
| -rw-r--r-- | src/syntax/linked.rs | 92 |
2 files changed, 64 insertions, 35 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 77c788d3..56d4415e 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -1577,12 +1577,17 @@ impl Ident { _ => panic!("identifier is of wrong kind"), } } + + /// Get the identifier as a string slice. + pub fn as_str(&self) -> &str { + self.get() + } } impl Deref for Ident { type Target = str; fn deref(&self) -> &Self::Target { - self.get() + self.as_str() } } 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 }); - } } |
