use std::{
cell::Cell,
fmt,
hash::{Hash, Hasher},
iter,
mem::ManuallyDrop,
ptr, slice,
};
use countme::Count;
use crate::{
green::{GreenChild, GreenElementRef, GreenNodeData, GreenTokenData, SyntaxKind},
Direction, GreenNode, GreenToken, NodeOrToken, SyntaxText, TextRange, TextSize, TokenAtOffset,
WalkEvent,
};
enum Green {
Node { ptr: ptr::NonNull<GreenNodeData> },
Token { ptr: ptr::NonNull<GreenTokenData> },
}
struct _SyntaxElement;
struct NodeData {
_c: Count<_SyntaxElement>,
rc: Cell<u32>,
parent: Option<ptr::NonNull<NodeData>>,
index: u32,
green: Green,
offset: TextSize,
}
pub type SyntaxElement = NodeOrToken<SyntaxNode, SyntaxToken>;
pub struct SyntaxNode {
ptr: ptr::NonNull<NodeData>,
}
impl Clone for SyntaxNode {
#[inline]
fn clone(&self) -> Self {
self.data().inc_rc();
SyntaxNode { ptr: self.ptr }
}
}
impl Drop for SyntaxNode {
#[inline]
fn drop(&mut self) {
if self.data().dec_rc() {
unsafe { free(self.ptr) }
}
}
}
#[derive(Debug)]
pub struct SyntaxToken {
ptr: ptr::NonNull<NodeData>,
}
impl Clone for SyntaxToken {
#[inline]
fn clone(&self) -> Self {
self.data().inc_rc();
SyntaxToken { ptr: self.ptr }
}
}
impl Drop for SyntaxToken {
#[inline]
fn drop(&mut self) {
if self.data().dec_rc() {
unsafe { free(self.ptr) }
}
}
}
#[inline(never)]
unsafe fn free(mut data: ptr::NonNull<NodeData>) {
loop {
debug_assert_eq!(data.as_ref().rc.get(), 0);
let node = Box::from_raw(data.as_ptr());
match node.parent {
Some(parent) => {
debug_assert!(parent.as_ref().rc.get() > 0);
if parent.as_ref().dec_rc() {
data = parent;
} else {
break;
}
}
None => {
if let Green::Node { ptr } = &node.green {
let _ = GreenNode::from_raw(*ptr);
} else {
unreachable!("a token cannot be a root");
}
break;
}
}
}
}
impl NodeData {
#[inline]
fn new(
parent: Option<SyntaxNode>,
index: u32,
offset: TextSize,
green: Green,
) -> ptr::NonNull<NodeData> {
let parent = ManuallyDrop::new(parent);
let res = NodeData {
_c: Count::new(),
rc: Cell::new(1),
parent: parent.as_ref().map(|it| it.ptr),
index,
green,
offset,
};
unsafe { ptr::NonNull::new_unchecked(Box::into_raw(Box::new(res))) }
}
#[inline]
fn inc_rc(&self) {
let rc = match self.rc.get().checked_add(1) {
Some(it) => it,
None => std::process::abort(),
};
self.rc.set(rc)
}
#[inline]
fn dec_rc(&self) -> bool {
let rc = self.rc.get() - 1;
self.rc.set(rc);
rc == 0
}
#[inline]
fn key(&self) -> (ptr::NonNull<()>, TextSize) {
let ptr = match &self.green {
Green::Node { ptr } => ptr.cast(),
Green::Token { ptr } => ptr.cast(),
};
(ptr, self.offset())
}
#[inline]
fn parent_node(&self) -> Option<SyntaxNode> {
let parent = self.parent()?;
debug_assert!(matches!(parent.green, Green::Node { .. }));
parent.inc_rc();
Some(SyntaxNode { ptr: ptr::NonNull::from(parent) })
}
#[inline]
fn parent(&self) -> Option<&NodeData> {
self.parent.map(|it| unsafe { &*it.as_ptr() })
}
#[inline]
fn green(&self) -> GreenElementRef<'_> {
match &self.green {
Green::Node { ptr } => GreenElementRef::Node(unsafe { &*ptr.as_ptr() }),
Green::Token { ptr } => GreenElementRef::Token(unsafe { ptr.as_ref() }),
}
}
#[inline]
fn green_siblings(&self) -> slice::Iter<'_, GreenChild> {
match &self.parent().map(|it| &it.green) {
Some(Green::Node { ptr }) => unsafe { &*ptr.as_ptr() }.children().raw,
Some(Green::Token { .. }) => {
debug_assert!(false);
[].iter()
}
None => [].iter(),
}
}
#[inline]
fn index(&self) -> u32 {
self.index
}
#[inline]
fn offset(&self) -> TextSize {
self.offset
}
#[inline]
fn text_range(&self) -> TextRange {
let offset = self.offset();
let len = self.green().text_len();
TextRange::at(offset, len)
}
#[inline]
fn kind(&self) -> SyntaxKind {
self.green().kind()
}
fn next_sibling(&self) -> Option<SyntaxNode> {
let mut siblings = self.green_siblings().enumerate();
let index = self.index() as usize;
siblings.nth(index);
siblings.find_map(|(index, child)| {
child.as_ref().into_node().and_then(|green| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxNode::new_child(green, parent, index as u32, offset))
})
})
}
fn prev_sibling(&self) -> Option<SyntaxNode> {
let mut rev_siblings = self.green_siblings().enumerate().rev();
let index = rev_siblings.len().checked_sub(self.index() as usize + 1)?;
rev_siblings.nth(index);
rev_siblings.find_map(|(index, child)| {
child.as_ref().into_node().and_then(|green| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxNode::new_child(green, parent, index as u32, offset))
})
})
}
fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
let mut siblings = self.green_siblings().enumerate();
let index = self.index() as usize + 1;
siblings.nth(index).and_then(|(index, child)| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset))
})
}
fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
let mut siblings = self.green_siblings().enumerate();
let index = self.index().checked_sub(1)? as usize;
siblings.nth(index).and_then(|(index, child)| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset))
})
}
}
impl SyntaxNode {
pub fn new_root(green: GreenNode) -> SyntaxNode {
let green = GreenNode::into_raw(green);
let green = Green::Node { ptr: green };
SyntaxNode { ptr: NodeData::new(None, 0, 0.into(), green) }
}
fn new_child(
green: &GreenNodeData,
parent: SyntaxNode,
index: u32,
offset: TextSize,
) -> SyntaxNode {
let green = Green::Node { ptr: green.into() };
SyntaxNode { ptr: NodeData::new(Some(parent), index, offset, green) }
}
pub fn clone_subtree(&self) -> SyntaxNode {
SyntaxNode::new_root(self.green().to_owned())
}
#[inline]
fn data(&self) -> &NodeData {
unsafe { self.ptr.as_ref() }
}
pub fn replace_with(&self, replacement: GreenNode) -> GreenNode {
assert_eq!(self.kind(), replacement.kind());
match &self.parent() {
None => replacement,
Some(parent) => {
let new_parent = parent
.green_ref()
.replace_child(self.data().index() as usize, replacement.into());
parent.replace_with(new_parent)
}
}
}
#[inline]
pub fn kind(&self) -> SyntaxKind {
self.data().kind()
}
#[inline]
fn offset(&self) -> TextSize {
self.data().offset()
}
#[inline]
pub fn text_range(&self) -> TextRange {
self.data().text_range()
}
#[inline]
pub fn index(&self) -> usize {
self.data().index() as usize
}
#[inline]
pub fn text(&self) -> SyntaxText {
SyntaxText::new(self.clone())
}
#[inline]
pub fn green(&self) -> &GreenNodeData {
self.green_ref()
}
#[inline]
fn green_ref(&self) -> &GreenNodeData {
self.data().green().into_node().unwrap()
}
#[inline]
pub fn parent(&self) -> Option<SyntaxNode> {
self.data().parent_node()
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
iter::successors(Some(self.clone()), SyntaxNode::parent)
}
#[inline]
pub fn tree_top(&self) -> SyntaxNode {
self.ancestors().last().unwrap()
}
#[inline]
pub fn children(&self) -> SyntaxNodeChildren {
SyntaxNodeChildren::new(self.clone())
}
#[inline]
pub fn children_with_tokens(&self) -> SyntaxElementChildren {
SyntaxElementChildren::new(self.clone())
}
pub fn first_child(&self) -> Option<SyntaxNode> {
self.green_ref().children().raw.enumerate().find_map(|(index, child)| {
child.as_ref().into_node().map(|green| {
SyntaxNode::new_child(
green,
self.clone(),
index as u32,
self.offset() + child.rel_offset(),
)
})
})
}
pub fn last_child(&self) -> Option<SyntaxNode> {
self.green_ref().children().raw.enumerate().rev().find_map(|(index, child)| {
child.as_ref().into_node().map(|green| {
SyntaxNode::new_child(
green,
self.clone(),
index as u32,
self.offset() + child.rel_offset(),
)
})
})
}
pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
self.green_ref().children().raw.next().map(|child| {
SyntaxElement::new(child.as_ref(), self.clone(), 0, self.offset() + child.rel_offset())
})
}
pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
self.green_ref().children().raw.enumerate().next_back().map(|(index, child)| {
SyntaxElement::new(
child.as_ref(),
self.clone(),
index as u32,
self.offset() + child.rel_offset(),
)
})
}
pub fn next_sibling(&self) -> Option<SyntaxNode> {
self.data().next_sibling()
}
pub fn prev_sibling(&self) -> Option<SyntaxNode> {
self.data().prev_sibling()
}
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
self.data().next_sibling_or_token()
}
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
self.data().prev_sibling_or_token()
}
pub fn first_token(&self) -> Option<SyntaxToken> {
self.first_child_or_token()?.first_token()
}
pub fn last_token(&self) -> Option<SyntaxToken> {
self.last_child_or_token()?.last_token()
}
#[inline]
pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = SyntaxNode> {
iter::successors(Some(self.clone()), move |node| match direction {
Direction::Next => node.next_sibling(),
Direction::Prev => node.prev_sibling(),
})
}
#[inline]
pub fn siblings_with_tokens(
&self,
direction: Direction,
) -> impl Iterator<Item = SyntaxElement> {
let me: SyntaxElement = self.clone().into();
iter::successors(Some(me), move |el| match direction {
Direction::Next => el.next_sibling_or_token(),
Direction::Prev => el.prev_sibling_or_token(),
})
}
#[inline]
pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
self.preorder().filter_map(|event| match event {
WalkEvent::Enter(node) => Some(node),
WalkEvent::Leave(_) => None,
})
}
#[inline]
pub fn descendants_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
self.preorder_with_tokens().filter_map(|event| match event {
WalkEvent::Enter(it) => Some(it),
WalkEvent::Leave(_) => None,
})
}
#[inline]
pub fn preorder(&self) -> Preorder {
Preorder::new(self.clone())
}
#[inline]
pub fn preorder_with_tokens(&self) -> PreorderWithTokens {
PreorderWithTokens::new(self.clone())
}
pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
let range = self.text_range();
assert!(
range.start() <= offset && offset <= range.end(),
"Bad offset: range {:?} offset {:?}",
range,
offset
);
if range.is_empty() {
return TokenAtOffset::None;
}
let mut children = self.children_with_tokens().filter(|child| {
let child_range = child.text_range();
!child_range.is_empty()
&& (child_range.start() <= offset && offset <= child_range.end())
});
let left = children.next().unwrap();
let right = children.next();
assert!(children.next().is_none());
if let Some(right) = right {
match (left.token_at_offset(offset), right.token_at_offset(offset)) {
(TokenAtOffset::Single(left), TokenAtOffset::Single(right)) => {
TokenAtOffset::Between(left, right)
}
_ => unreachable!(),
}
} else {
left.token_at_offset(offset)
}
}
pub fn covering_element(&self, range: TextRange) -> SyntaxElement {
let mut res: SyntaxElement = self.clone().into();
loop {
assert!(
res.text_range().contains_range(range),
"Bad range: node range {:?}, range {:?}",
res.text_range(),
range,
);
res = match &res {
NodeOrToken::Token(_) => return res,
NodeOrToken::Node(node) => match node.child_or_token_at_range(range) {
Some(it) => it,
None => return res,
},
};
}
}
pub fn child_or_token_at_range(&self, range: TextRange) -> Option<SyntaxElement> {
let rel_range = range - self.offset();
self.green_ref().child_at_range(rel_range).map(|(index, rel_offset, green)| {
SyntaxElement::new(green, self.clone(), index as u32, self.offset() + rel_offset)
})
}
}
impl SyntaxToken {
fn new(
green: &GreenTokenData,
parent: SyntaxNode,
index: u32,
offset: TextSize,
) -> SyntaxToken {
let green = Green::Token { ptr: green.into() };
SyntaxToken { ptr: NodeData::new(Some(parent), index, offset, green) }
}
#[inline]
fn data(&self) -> &NodeData {
unsafe { self.ptr.as_ref() }
}
pub fn replace_with(&self, replacement: GreenToken) -> GreenNode {
assert_eq!(self.kind(), replacement.kind());
let parent = self.parent().unwrap();
let me: u32 = self.data().index();
let new_parent = parent.green_ref().replace_child(me as usize, replacement.into());
parent.replace_with(new_parent)
}
#[inline]
pub fn kind(&self) -> SyntaxKind {
self.data().kind()
}
#[inline]
pub fn text_range(&self) -> TextRange {
self.data().text_range()
}
#[inline]
pub fn index(&self) -> usize {
self.data().index() as usize
}
#[inline]
pub fn text(&self) -> &str {
match self.data().green().as_token() {
Some(it) => it.text(),
None => {
debug_assert!(
false,
"corrupted tree: a node thinks it is a token: {:?}",
self.data().green().as_node().unwrap().to_string()
);
""
}
}
}
#[inline]
pub fn green(&self) -> &GreenTokenData {
self.data().green().into_token().unwrap()
}
#[inline]
pub fn parent(&self) -> Option<SyntaxNode> {
self.data().parent_node()
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
std::iter::successors(self.parent(), SyntaxNode::parent)
}
#[inline]
pub fn tree_top(&self) -> SyntaxNode {
self.ancestors().last().unwrap()
}
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
self.data().next_sibling_or_token()
}
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
self.data().prev_sibling_or_token()
}
#[inline]
pub fn siblings_with_tokens(
&self,
direction: Direction,
) -> impl Iterator<Item = SyntaxElement> {
let me: SyntaxElement = self.clone().into();
iter::successors(Some(me), move |el| match direction {
Direction::Next => el.next_sibling_or_token(),
Direction::Prev => el.prev_sibling_or_token(),
})
}
pub fn next_token(&self) -> Option<SyntaxToken> {
match self.next_sibling_or_token() {
Some(element) => element.first_token(),
None => self
.ancestors()
.find_map(|it| it.next_sibling_or_token())
.and_then(|element| element.first_token()),
}
}
pub fn prev_token(&self) -> Option<SyntaxToken> {
match self.prev_sibling_or_token() {
Some(element) => element.last_token(),
None => self
.ancestors()
.find_map(|it| it.prev_sibling_or_token())
.and_then(|element| element.last_token()),
}
}
}
impl SyntaxElement {
fn new(
element: GreenElementRef<'_>,
parent: SyntaxNode,
index: u32,
offset: TextSize,
) -> SyntaxElement {
match element {
NodeOrToken::Node(node) => {
SyntaxNode::new_child(node, parent, index as u32, offset).into()
}
NodeOrToken::Token(token) => {
SyntaxToken::new(token, parent, index as u32, offset).into()
}
}
}
#[inline]
pub fn text_range(&self) -> TextRange {
match self {
NodeOrToken::Node(it) => it.text_range(),
NodeOrToken::Token(it) => it.text_range(),
}
}
#[inline]
pub fn index(&self) -> usize {
match self {
NodeOrToken::Node(it) => it.index(),
NodeOrToken::Token(it) => it.index(),
}
}
#[inline]
pub fn kind(&self) -> SyntaxKind {
match self {
NodeOrToken::Node(it) => it.kind(),
NodeOrToken::Token(it) => it.kind(),
}
}
#[inline]
pub fn parent(&self) -> Option<SyntaxNode> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => it.parent(),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
let first = match self {
NodeOrToken::Node(it) => Some(it.clone()),
NodeOrToken::Token(it) => it.parent(),
};
iter::successors(first, SyntaxNode::parent)
}
#[inline]
pub fn tree_top(&self) -> SyntaxNode {
match self {
NodeOrToken::Node(it) => it.tree_top(),
NodeOrToken::Token(it) => it.tree_top(),
}
}
pub fn first_token(&self) -> Option<SyntaxToken> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it.clone()),
}
}
pub fn last_token(&self) -> Option<SyntaxToken> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it.clone()),
}
}
pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
match self {
NodeOrToken::Node(it) => it.next_sibling_or_token(),
NodeOrToken::Token(it) => it.next_sibling_or_token(),
}
}
pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
assert!(self.text_range().start() <= offset && offset <= self.text_range().end());
match self {
NodeOrToken::Token(token) => TokenAtOffset::Single(token.clone()),
NodeOrToken::Node(node) => node.token_at_offset(offset),
}
}
}
impl PartialEq for SyntaxNode {
#[inline]
fn eq(&self, other: &SyntaxNode) -> bool {
self.data().key() == other.data().key()
}
}
impl Eq for SyntaxNode {}
impl Hash for SyntaxNode {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.data().key().hash(state);
}
}
impl fmt::Debug for SyntaxNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SyntaxNode")
.field("kind", &self.kind())
.field("text_range", &self.text_range())
.finish()
}
}
impl fmt::Display for SyntaxNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.preorder_with_tokens()
.filter_map(|event| match event {
WalkEvent::Enter(NodeOrToken::Token(token)) => Some(token),
_ => None,
})
.try_for_each(|it| fmt::Display::fmt(&it, f))
}
}
impl PartialEq for SyntaxToken {
#[inline]
fn eq(&self, other: &SyntaxToken) -> bool {
self.data().key() == other.data().key()
}
}
impl Eq for SyntaxToken {}
impl Hash for SyntaxToken {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.data().key().hash(state);
}
}
impl fmt::Display for SyntaxToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.text(), f)
}
}
impl From<SyntaxNode> for SyntaxElement {
#[inline]
fn from(node: SyntaxNode) -> SyntaxElement {
NodeOrToken::Node(node)
}
}
impl From<SyntaxToken> for SyntaxElement {
#[inline]
fn from(token: SyntaxToken) -> SyntaxElement {
NodeOrToken::Token(token)
}
}
#[derive(Clone, Debug)]
pub struct SyntaxNodeChildren {
next: Option<SyntaxNode>,
}
impl SyntaxNodeChildren {
fn new(parent: SyntaxNode) -> SyntaxNodeChildren {
SyntaxNodeChildren { next: parent.first_child() }
}
}
impl Iterator for SyntaxNodeChildren {
type Item = SyntaxNode;
fn next(&mut self) -> Option<SyntaxNode> {
self.next.take().map(|next| {
self.next = next.next_sibling();
next
})
}
}
#[derive(Clone, Debug)]
pub struct SyntaxElementChildren {
next: Option<SyntaxElement>,
}
impl SyntaxElementChildren {
fn new(parent: SyntaxNode) -> SyntaxElementChildren {
SyntaxElementChildren { next: parent.first_child_or_token() }
}
}
impl Iterator for SyntaxElementChildren {
type Item = SyntaxElement;
fn next(&mut self) -> Option<SyntaxElement> {
self.next.take().map(|next| {
self.next = next.next_sibling_or_token();
next
})
}
}
#[derive(Debug, Clone)]
pub struct Preorder {
start: SyntaxNode,
next: Option<WalkEvent<SyntaxNode>>,
skip_subtree: bool,
}
impl Preorder {
fn new(start: SyntaxNode) -> Preorder {
let next = Some(WalkEvent::Enter(start.clone()));
Preorder { start, next, skip_subtree: false }
}
pub fn skip_subtree(&mut self) {
self.skip_subtree = true;
}
#[cold]
fn do_skip(&mut self) {
self.next = self.next.take().map(|next| match next {
WalkEvent::Enter(first_child) => WalkEvent::Leave(first_child.parent().unwrap()),
WalkEvent::Leave(parent) => WalkEvent::Leave(parent),
})
}
}
impl Iterator for Preorder {
type Item = WalkEvent<SyntaxNode>;
fn next(&mut self) -> Option<WalkEvent<SyntaxNode>> {
if self.skip_subtree {
self.do_skip();
self.skip_subtree = false;
}
let next = self.next.take();
self.next = next.as_ref().and_then(|next| {
Some(match next {
WalkEvent::Enter(node) => match node.first_child() {
Some(child) => WalkEvent::Enter(child),
None => WalkEvent::Leave(node.clone()),
},
WalkEvent::Leave(node) => {
if node == &self.start {
return None;
}
match node.next_sibling() {
Some(sibling) => WalkEvent::Enter(sibling),
None => WalkEvent::Leave(node.parent()?),
}
}
})
});
next
}
}
#[derive(Debug, Clone)]
pub struct PreorderWithTokens {
start: SyntaxElement,
next: Option<WalkEvent<SyntaxElement>>,
skip_subtree: bool,
}
impl PreorderWithTokens {
fn new(start: SyntaxNode) -> PreorderWithTokens {
let next = Some(WalkEvent::Enter(start.clone().into()));
PreorderWithTokens { start: start.into(), next, skip_subtree: false }
}
pub fn skip_subtree(&mut self) {
self.skip_subtree = true;
}
#[cold]
fn do_skip(&mut self) {
self.next = self.next.take().map(|next| match next {
WalkEvent::Enter(first_child) => WalkEvent::Leave(first_child.parent().unwrap().into()),
WalkEvent::Leave(parent) => WalkEvent::Leave(parent),
})
}
}
impl Iterator for PreorderWithTokens {
type Item = WalkEvent<SyntaxElement>;
fn next(&mut self) -> Option<WalkEvent<SyntaxElement>> {
if self.skip_subtree {
self.do_skip();
self.skip_subtree = false;
}
let next = self.next.take();
self.next = next.as_ref().and_then(|next| {
Some(match next {
WalkEvent::Enter(el) => match el {
NodeOrToken::Node(node) => match node.first_child_or_token() {
Some(child) => WalkEvent::Enter(child),
None => WalkEvent::Leave(node.clone().into()),
},
NodeOrToken::Token(token) => WalkEvent::Leave(token.clone().into()),
},
WalkEvent::Leave(el) if el == &self.start => return None,
WalkEvent::Leave(el) => match el.next_sibling_or_token() {
Some(sibling) => WalkEvent::Enter(sibling),
None => WalkEvent::Leave(el.parent()?.into()),
},
})
});
next
}
}