mod element;
mod node;
mod token;
mod trivia;
use std::{iter, ops};
use std::{ptr, rc::Rc};
pub(crate) use trivia::{SyntaxTrivia, SyntaxTriviaPiecesIterator};
use crate::cursor::node::Siblings;
pub(crate) use crate::cursor::token::SyntaxToken;
use crate::green::{self, GreenElement, GreenNodeData, GreenTokenData};
use crate::{
NodeOrToken, TextRange, TextSize,
green::{GreenElementRef, RawSyntaxKind},
};
pub(crate) use element::SyntaxElement;
pub(crate) use node::{
Preorder, PreorderTokens, PreorderWithTokens, SyntaxElementChildren, SyntaxNode,
SyntaxNodeChildren, SyntaxSlot, SyntaxSlots,
};
#[derive(Debug)]
struct _SyntaxElement;
#[cfg(feature = "countme")]
pub(crate) fn has_live() -> bool {
countme::get::<_SyntaxElement>().live > 0
}
#[derive(Debug)]
struct NodeData {
#[cfg(feature = "countme")]
_c: countme::Count<_SyntaxElement>,
kind: NodeKind,
slot: u32,
offset: TextSize,
}
#[derive(Debug)]
enum NodeKind {
Root {
green: GreenElement,
},
Child {
green: WeakGreenElement,
parent: Rc<NodeData>,
},
}
#[derive(Debug, Clone)]
enum WeakGreenElement {
Node { ptr: ptr::NonNull<GreenNodeData> },
Token { ptr: ptr::NonNull<GreenTokenData> },
}
impl WeakGreenElement {
fn new(green: GreenElementRef) -> Self {
match green {
NodeOrToken::Node(ptr) => Self::Node {
ptr: ptr::NonNull::from(ptr),
},
NodeOrToken::Token(ptr) => Self::Token {
ptr: ptr::NonNull::from(ptr),
},
}
}
fn as_deref(&self) -> GreenElementRef<'_> {
match self {
Self::Node { ptr } => GreenElementRef::Node(unsafe { ptr.as_ref() }),
Self::Token { ptr } => GreenElementRef::Token(unsafe { ptr.as_ref() }),
}
}
fn to_owned(&self) -> GreenElement {
match self {
Self::Node { ptr } => GreenElement::Node(unsafe { ptr.as_ref().to_owned() }),
Self::Token { ptr } => GreenElement::Token(unsafe { ptr.as_ref().to_owned() }),
}
}
}
impl NodeData {
#[inline]
fn new(kind: NodeKind, slot: u32, offset: TextSize) -> Rc<Self> {
let res = Self {
#[cfg(feature = "countme")]
_c: countme::Count::new(),
kind,
slot,
offset,
};
Rc::new(res)
}
#[inline]
fn key(&self) -> (ptr::NonNull<()>, TextSize) {
let weak = match &self.kind {
NodeKind::Root { green } => WeakGreenElement::new(green.as_deref()),
NodeKind::Child { green, .. } => green.clone(),
};
let ptr = match weak {
WeakGreenElement::Node { ptr } => ptr.cast(),
WeakGreenElement::Token { ptr } => ptr.cast(),
};
(ptr, self.offset())
}
#[inline]
fn parent_node(&self) -> Option<SyntaxNode> {
debug_assert!(matches!(
self.parent()?.green(),
GreenElementRef::Node { .. }
));
match &self.kind {
NodeKind::Child { parent, .. } => Some(SyntaxNode {
ptr: parent.clone(),
}),
NodeKind::Root { .. } => None,
}
}
#[inline]
fn parent(&self) -> Option<&Self> {
match &self.kind {
NodeKind::Child { parent, .. } => Some(&**parent),
NodeKind::Root { .. } => None,
}
}
#[inline]
fn green(&self) -> GreenElementRef<'_> {
match &self.kind {
NodeKind::Root { green } => green.as_deref(),
NodeKind::Child { green, .. } => green.as_deref(),
}
}
#[inline]
fn green_siblings(&self) -> Option<Siblings<'_>> {
match &self.parent()?.green() {
GreenElementRef::Node(ptr) => Some(Siblings::new(ptr, self.slot())),
GreenElementRef::Token(_) => {
debug_assert!(
false,
"A token should never be a parent of a token or node."
);
None
}
}
}
#[inline]
fn slot(&self) -> u32 {
self.slot
}
#[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) -> RawSyntaxKind {
self.green().kind()
}
fn next_sibling(&self) -> Option<SyntaxNode> {
let siblings = self.green_siblings()?;
siblings.following().find_map(|child| {
child.element().into_node().and_then(|green| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxNode::new_child(green, parent, child.slot(), offset))
})
})
}
fn prev_sibling(&self) -> Option<SyntaxNode> {
let siblings = self.green_siblings()?;
siblings.previous().find_map(|child| {
child.element().into_node().and_then(|green| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxNode::new_child(green, parent, child.slot(), offset))
})
})
}
fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
let siblings = self.green_siblings()?;
siblings.following().next().and_then(|child| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxElement::new(
child.element(),
parent,
child.slot(),
offset,
))
})
}
fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
let siblings = self.green_siblings()?;
siblings.previous().next().and_then(|child| {
let parent = self.parent_node()?;
let offset = parent.offset() + child.rel_offset();
Some(SyntaxElement::new(
child.element(),
parent,
child.slot(),
offset,
))
})
}
fn into_green(self: Rc<Self>) -> GreenElement {
match Rc::try_unwrap(self) {
Ok(data) => match data.kind {
NodeKind::Root { green } => green,
NodeKind::Child { green, .. } => green.to_owned(),
},
Err(ptr) => ptr.green().to_owned(),
}
}
#[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
fn detach(self: Rc<Self>) -> Rc<Self> {
match &self.kind {
NodeKind::Child { green, .. } => Self::new(
NodeKind::Root {
green: green.to_owned(),
},
0,
0.into(),
),
NodeKind::Root { .. } => self.clone(),
}
}
#[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
fn splice_slots<R, I>(mut self: Rc<Self>, range: R, replace_with: I) -> Rc<Self>
where
R: ops::RangeBounds<usize>,
I: Iterator<Item = Option<green::GreenElement>>,
{
let green = match self.green() {
NodeOrToken::Node(green) => green.splice_slots(range, replace_with).into(),
NodeOrToken::Token(_) => panic!("called splice_slots on a token node"),
};
match Rc::get_mut(&mut self) {
Some(node) => {
node.kind = NodeKind::Root { green };
node.slot = 0;
node.offset = TextSize::from(0);
self
}
None => Self::new(NodeKind::Root { green }, 0, 0.into()),
}
}
#[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
fn replace_child(
mut self: Rc<Self>,
prev_elem: SyntaxElement,
next_elem: SyntaxElement,
) -> Option<Rc<Self>> {
let mut green = next_elem.into_green();
let mut elem = prev_elem;
loop {
let node = elem.parent()?;
let is_self = node.key() == self.key();
let index = elem.index();
let range = index..=index;
let replace_with = iter::once(Some(green));
green = node.green().splice_slots(range, replace_with).into();
elem = node.into();
if is_self {
break;
}
}
let result = match Rc::get_mut(&mut self) {
Some(node) => {
node.kind = NodeKind::Root { green };
node.slot = 0;
node.offset = TextSize::from(0);
self
}
None => Self::new(NodeKind::Root { green }, 0, 0.into()),
};
Some(result)
}
}