use crate::ast::{
node::{NodeRef, SubNodeRef},
Ast,
};
#[derive(Clone)]
pub struct AstPathIter<'a> {
next: Option<NodeRef<'a>>,
offset: u32,
}
impl<'a> AstPathIter<'a> {
pub(crate) fn from_ast(ast: &'a Ast, offset: u32) -> Self {
Self {
next: ast
.root_entries()
.find(|o| o.span().contains_inclusive(offset))
.map(NodeRef::RootEntry),
offset,
}
}
pub(crate) fn from_node(node: NodeRef<'a>, offset: u32) -> Self {
Self {
next: node.span().contains_inclusive(offset).then_some(node),
offset,
}
}
}
impl<'a> Iterator for AstPathIter<'a> {
type Item = NodeRef<'a>;
fn next(&mut self) -> Option<NodeRef<'a>> {
let current = self.next.take()?;
self.next = current
.children()
.find(|c| c.span().contains_inclusive(self.offset));
Some(current)
}
}
#[derive(Clone)]
pub struct AstFinePathIter<'a> {
next: Option<SubNodeRef<'a>>,
offset: u32,
}
impl<'a> AstFinePathIter<'a> {
pub(crate) fn from_ast(ast: &'a Ast, offset: u32) -> Self {
Self {
next: ast
.roots
.iter()
.find(|r| r.span().contains_inclusive(offset))
.map(|r| SubNodeRef::Root(r, crate::ast::query::AstRootDetail::Node)),
offset,
}
}
}
impl<'a> Iterator for AstFinePathIter<'a> {
type Item = SubNodeRef<'a>;
fn next(&mut self) -> Option<SubNodeRef<'a>> {
let current = self.next.take()?;
if current.detail().is_node() {
self.next = match current {
SubNodeRef::Root(v, _) => v
.detailed_children()
.find(|c| c.span().contains_inclusive(self.offset)),
SubNodeRef::RootEntry(v, _) => v
.detailed_children()
.find(|c| c.span().contains_inclusive(self.offset)),
SubNodeRef::Object(v, _) => v
.detailed_children()
.find(|c| c.span().contains_inclusive(self.offset)),
SubNodeRef::Property(v, _) => v
.detailed_children()
.find(|c| c.span().contains_inclusive(self.offset)),
SubNodeRef::Value(v) => v
.children()
.find(|c| c.span().contains_inclusive(self.offset))
.map(|c| c.into()),
};
}
Some(current)
}
}