use crate::raw;
#[cfg(feature = "yak-sitter")]
use crate::PointRange;
use crate::{InputEdit, Point, Range};
pub use cursor::*;
pub use incorrect_kind::*;
pub use parser::*;
use std::fmt::Debug;
use std::hash::Hash;
#[cfg(not(feature = "yak-sitter"))]
use std::str::Utf8Error;
pub use tree::*;
pub use unwrap_and_flatten_multi::*;
pub use wrappers::*;
mod cursor;
mod incorrect_kind;
mod parser;
mod tree;
mod unwrap_and_flatten_multi;
mod wrappers;
pub trait Node<'tree>: Debug + Clone + Copy + PartialEq + Eq + Hash {
type WithLifetime<'a>: Node<'a>;
const KIND: &'static str;
fn try_from_raw(node: raw::Node<'tree>) -> NodeResult<'tree, Self>;
#[inline]
unsafe fn from_raw_unchecked(node: raw::Node<'tree>) -> Self {
Self::try_from_raw(node).expect("from_raw_unchecked failed")
}
fn raw(&self) -> &raw::Node<'tree>;
fn raw_mut(&mut self) -> &mut raw::Node<'tree>;
fn into_raw(self) -> raw::Node<'tree>;
#[inline]
fn upcast(self) -> UntypedNode<'tree> {
UntypedNode::new(self.into_raw())
}
#[cfg(feature = "yak-sitter")]
fn text(&self) -> &'tree str {
self.raw().text()
}
#[inline]
#[cfg(not(feature = "yak-sitter"))]
fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, Utf8Error> {
self.raw().utf8_text(source)
}
#[inline]
#[cfg(not(feature = "yak-sitter"))]
fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
self.raw().utf16_text(source)
}
#[inline]
fn prefixes(&self) -> impl Iterator<Item = UntypedNode<'tree>> {
Prefixes::new(*self.raw())
}
#[inline]
fn suffixes(&self) -> impl Iterator<Item = UntypedNode<'tree>> {
Suffixes::new(*self.raw())
}
#[inline]
fn walk(&self) -> TreeCursor<'tree> {
TreeCursor(self.raw().walk())
}
#[inline]
fn parent(&self) -> Option<UntypedNode<'tree>> {
self.raw().parent().map(UntypedNode::from)
}
#[inline]
fn next_sibling(&self) -> Option<UntypedNode<'tree>> {
self.raw().next_sibling().map(UntypedNode::from)
}
#[inline]
fn prev_sibling(&self) -> Option<UntypedNode<'tree>> {
self.raw().prev_named_sibling().map(UntypedNode::from)
}
#[inline]
fn child_count(&self) -> usize {
self.raw().child_count()
}
#[inline]
fn next_named_sibling(&self) -> Option<UntypedNode<'tree>> {
self.raw().next_named_sibling().map(UntypedNode::from)
}
#[inline]
fn prev_named_sibling(&self) -> Option<UntypedNode<'tree>> {
self.raw().prev_named_sibling().map(UntypedNode::from)
}
#[inline]
fn named_child_count(&self) -> usize {
self.raw().named_child_count()
}
#[inline]
fn to_sexp(&self) -> String {
self.raw().to_sexp()
}
#[inline]
fn kind(&self) -> &'static str {
self.raw().kind()
}
#[inline]
fn is_named(&self) -> bool {
self.raw().is_named()
}
#[inline]
fn has_changes(&self) -> bool {
self.raw().has_changes()
}
#[inline]
fn has_error(&self) -> bool {
self.raw().has_error()
}
#[inline]
fn start_byte(&self) -> usize {
self.raw().start_byte()
}
#[inline]
fn end_byte(&self) -> usize {
self.raw().end_byte()
}
#[inline]
fn start_position(&self) -> Point {
self.raw().start_position()
}
#[inline]
fn end_position(&self) -> Point {
self.raw().end_position()
}
#[inline]
fn range(&self) -> Range {
self.raw().range()
}
#[inline]
fn byte_range(&self) -> std::ops::Range<usize> {
self.raw().byte_range()
}
#[inline]
#[cfg(feature = "yak-sitter")]
fn position_range(&self) -> PointRange {
self.raw().position_range()
}
#[inline]
fn edit(&mut self, edit: &InputEdit) {
self.raw_mut().edit(edit)
}
}
pub trait HasOptionalChild<'tree>: Node<'tree> {
type Child: Node<'tree>;
#[inline]
fn child(&self) -> Option<NodeResult<'tree, Self::Child>> {
optional_child(self)
}
}
pub trait HasChild<'tree>: Node<'tree> {
type Child: Node<'tree>;
#[inline]
fn child(&self) -> NodeResult<'tree, Self::Child> {
optional_child(self).expect(
"required child not present, there should at least be a MISSING node in its place",
)
}
}
#[inline]
fn optional_child<'tree, Child: Node<'tree>>(
this: &impl Node<'tree>,
) -> Option<NodeResult<'tree, Child>> {
(0..this.raw().named_child_count())
.map(|i| this.raw().named_child(i.try_into().unwrap()).unwrap())
.filter(|n| !n.is_extra())
.next()
.map(Child::try_from_raw)
}
pub trait HasChildren<'tree>: Node<'tree> {
type Child: Node<'tree>;
#[inline]
fn children<'a>(
&self,
c: &'a mut TreeCursor<'tree>,
) -> impl Iterator<Item = NodeResult<'tree, Self::Child>> + 'a
where
Self: 'a,
{
self.raw()
.named_children(&mut c.0)
.filter(|n| !n.is_extra())
.map(Self::Child::try_from_raw)
}
}
struct Prefixes<'tree> {
cursor: raw::TreeCursor<'tree>,
end: raw::Node<'tree>,
}
struct Suffixes<'tree> {
cursor: raw::TreeCursor<'tree>,
}
impl<'tree> Prefixes<'tree> {
fn new(raw: raw::Node<'tree>) -> Self {
let Some(parent) = raw.parent() else {
return Self {
cursor: raw.walk(),
end: raw,
};
};
let mut cursor = parent.walk();
cursor.goto_first_child();
'outer: loop {
if cursor.node() == raw {
break Self {
cursor: raw.walk(),
end: raw,
};
}
if cursor.node().is_extra() {
let mut cursor2 = cursor.clone();
while cursor2.node().is_extra() {
if !cursor2.goto_next_sibling() {
break 'outer Self {
cursor: raw.walk(),
end: raw,
};
}
if cursor2.node() == raw {
break 'outer Self { cursor, end: raw };
}
}
}
if !cursor.goto_next_sibling() {
break Self {
cursor: raw.walk(),
end: raw,
};
}
}
}
}
impl<'tree> Suffixes<'tree> {
fn new(raw: raw::Node<'tree>) -> Self {
let Some(parent) = raw.parent() else {
return Self { cursor: raw.walk() };
};
let mut cursor = parent.walk();
cursor.goto_first_child();
while cursor.node() != raw {
let next = cursor.goto_next_sibling();
assert!(next, "node not found in parent");
}
Self { cursor }
}
}
impl<'tree> Iterator for Prefixes<'tree> {
type Item = UntypedNode<'tree>;
fn next(&mut self) -> Option<Self::Item> {
if self.cursor.node() == self.end {
return None;
}
let result = UntypedNode::new(self.cursor.node());
debug_assert!(
self.cursor.node().is_extra(),
"node before our iteration target isn't an extra, but we thought it would be"
);
let next = self.cursor.goto_next_sibling();
assert!(
next,
"node (that we've been iterating the prefixes of) not found in parent"
);
Some(result)
}
}
impl<'tree> Iterator for Suffixes<'tree> {
type Item = UntypedNode<'tree>;
fn next(&mut self) -> Option<Self::Item> {
if !self.cursor.goto_next_sibling() || !self.cursor.node().is_extra() {
return None;
}
Some(UntypedNode::new(self.cursor.node()))
}
}