use rowan::{NodeOrToken, TextRange, TextSize};
use crate::syntax::{SyntaxKind, SyntaxNode};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct NodePtr {
kind: SyntaxKind,
start: u32,
len: u32,
}
impl NodePtr {
pub fn from_node(node: &SyntaxNode) -> Self {
Self::new(node.kind(), node.text_range())
}
pub fn kind(&self) -> SyntaxKind {
self.kind
}
pub fn text_range(&self) -> TextRange {
TextRange::at(TextSize::new(self.start), TextSize::new(self.len))
}
pub fn with_range(self, range: TextRange) -> Self {
Self::new(self.kind, range)
}
pub fn try_to_node(&self, root: &SyntaxNode) -> Option<SyntaxNode> {
if root.parent().is_some() {
return None;
}
let range = self.text_range();
if !root.text_range().contains_range(range) {
return None;
}
let start = match root.covering_element(range) {
NodeOrToken::Node(node) => node,
NodeOrToken::Token(token) => token.parent()?,
};
start
.ancestors()
.find(|node| node.text_range() == range && node.kind() == self.kind)
}
fn new(kind: SyntaxKind, range: TextRange) -> Self {
Self {
kind,
start: range.start().into(),
len: range.len().into(),
}
}
}