summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-12-15 22:51:55 +0100
committerLaurenz <laurmaedje@gmail.com>2022-12-15 23:11:20 +0100
commitb6202b646a0d5ecced301d9bac8bfcaf977d7ee4 (patch)
tree7d42cb50f9e66153e7e8b2217009684e25f54f42 /src/syntax
parentf3980c704544a464f9729cc8bc9f97d3a7454769 (diff)
Reflection for castables
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/ast.rs7
-rw-r--r--src/syntax/linked.rs92
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 });
- }
}