use std::{
fmt,
ops::{Deref, DerefMut},
sync::Arc as StdArc,
};
use lasso::Resolver;
use text_size::{TextRange, TextSize};
use crate::{
Direction, GreenNode, Language, NodeOrToken, SyntaxElementRef, SyntaxKind, SyntaxNode, SyntaxText, SyntaxToken,
TokenAtOffset, WalkEvent,
};
#[derive(Clone)]
#[repr(transparent)]
pub struct ResolvedNode<L: Language, D: 'static = ()> {
pub(super) syntax: SyntaxNode<L, D>,
}
impl<L: Language, D> ResolvedNode<L, D> {
pub(super) unsafe fn coerce_ref(syntax: &SyntaxNode<L, D>) -> &Self {
&*(syntax as *const _ as *const Self)
}
pub fn syntax(&self) -> &SyntaxNode<L, D> {
&self.syntax
}
}
impl<L: Language, D> Deref for ResolvedNode<L, D> {
type Target = SyntaxNode<L, D>;
fn deref(&self) -> &Self::Target {
&self.syntax
}
}
impl<L: Language, D> DerefMut for ResolvedNode<L, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.syntax
}
}
#[repr(transparent)]
pub struct ResolvedToken<L: Language, D: 'static = ()> {
syntax: SyntaxToken<L, D>,
}
impl<L: Language, D> ResolvedToken<L, D> {
pub(super) unsafe fn coerce_ref(syntax: &SyntaxToken<L, D>) -> &Self {
&*(syntax as *const _ as *const Self)
}
pub fn syntax(&self) -> &SyntaxToken<L, D> {
&self.syntax
}
}
impl<L: Language, D> Deref for ResolvedToken<L, D> {
type Target = SyntaxToken<L, D>;
fn deref(&self) -> &Self::Target {
&self.syntax
}
}
impl<L: Language, D> DerefMut for ResolvedToken<L, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.syntax
}
}
pub type ResolvedElement<L, D = ()> = NodeOrToken<ResolvedNode<L, D>, ResolvedToken<L, D>>;
impl<L: Language, D> From<ResolvedNode<L, D>> for ResolvedElement<L, D> {
fn from(node: ResolvedNode<L, D>) -> ResolvedElement<L, D> {
NodeOrToken::Node(node)
}
}
impl<L: Language, D> From<ResolvedToken<L, D>> for ResolvedElement<L, D> {
fn from(token: ResolvedToken<L, D>) -> ResolvedElement<L, D> {
NodeOrToken::Token(token)
}
}
impl<L: Language, D> ResolvedElement<L, D> {
#[allow(missing_docs)]
pub fn display(&self, resolver: &impl Resolver) -> String {
match self {
NodeOrToken::Node(it) => it.display(resolver),
NodeOrToken::Token(it) => it.display(resolver),
}
}
}
pub type ResolvedElementRef<'a, L, D = ()> = NodeOrToken<&'a ResolvedNode<L, D>, &'a ResolvedToken<L, D>>;
impl<'a, L: Language, D> ResolvedElementRef<'a, L, D> {
pub(super) unsafe fn coerce_ref(syntax: SyntaxElementRef<'a, L, D>) -> Self {
match syntax {
NodeOrToken::Node(node) => Self::Node(ResolvedNode::coerce_ref(node)),
NodeOrToken::Token(token) => Self::Token(ResolvedToken::coerce_ref(token)),
}
}
}
impl<'a, L: Language, D> From<&'a ResolvedNode<L, D>> for ResolvedElementRef<'a, L, D> {
fn from(node: &'a ResolvedNode<L, D>) -> Self {
NodeOrToken::Node(node)
}
}
impl<'a, L: Language, D> From<&'a ResolvedToken<L, D>> for ResolvedElementRef<'a, L, D> {
fn from(token: &'a ResolvedToken<L, D>) -> Self {
NodeOrToken::Token(token)
}
}
impl<'a, L: Language, D> From<&'a ResolvedElement<L, D>> for ResolvedElementRef<'a, L, D> {
fn from(element: &'a ResolvedElement<L, D>) -> Self {
match element {
NodeOrToken::Node(it) => Self::Node(it),
NodeOrToken::Token(it) => Self::Token(it),
}
}
}
impl<L: Language, D> ResolvedNode<L, D> {
#[inline]
pub fn text(&self) -> SyntaxText<'_, '_, dyn Resolver, L, D> {
SyntaxText::new(self, &**self.resolver())
}
}
impl<L: Language, D> fmt::Debug for ResolvedNode<L, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.debug(&**self.resolver(), f.alternate()))
}
}
impl<L: Language, D> fmt::Display for ResolvedNode<L, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display(&**self.resolver()))
}
}
impl<L: Language, D> ResolvedToken<L, D> {
#[inline]
pub fn text(&self) -> &str {
self.green().text(&**self.parent().resolver())
}
}
impl<L: Language, D> fmt::Debug for ResolvedToken<L, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.debug(&**self.parent().resolver()))
}
}
impl<L: Language, D> fmt::Display for ResolvedToken<L, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display(&**self.parent().resolver()))
}
}
#[cfg(feature = "serde1")]
impl<L, D> ResolvedNode<L, D>
where
L: Language,
{
pub fn as_serialize_with_data(&self) -> impl serde::Serialize + '_
where
D: serde::Serialize,
{
crate::serde_impls::SerializeWithData {
node: self,
resolver: self.resolver().as_ref(),
}
}
}
macro_rules! forward {
($e:expr) => {
($e).map(|e| unsafe { Self::coerce_ref(e) })
};
}
macro_rules! forward_as_elem {
($e:expr) => {
($e).map(|e| unsafe { ResolvedElementRef::coerce_ref(e) })
};
}
macro_rules! forward_token {
($e:expr) => {
($e).map(|e| unsafe { ResolvedToken::coerce_ref(e) })
};
}
macro_rules! forward_node {
($e:expr) => {
($e).map(|e| unsafe { ResolvedNode::coerce_ref(e) })
};
}
impl<L: Language, D> ResolvedNode<L, D> {
pub fn resolver(&self) -> &StdArc<dyn Resolver> {
self.syntax.resolver().unwrap()
}
#[inline]
pub fn new_root_with_resolver(green: GreenNode, resolver: impl Resolver + 'static) -> Self {
SyntaxNode::new_root_with_resolver(green, resolver)
}
#[inline]
pub fn try_resolved(&self) -> Option<&ResolvedNode<L, D>> {
Some(self)
}
#[inline]
pub fn resolved(&self) -> &ResolvedNode<L, D> {
self
}
#[inline]
pub fn root(&self) -> &SyntaxNode<L, D> {
unsafe { Self::coerce_ref(self.syntax.root()) }
}
#[inline]
pub fn parent(&self) -> Option<&Self> {
forward!(self.syntax.parent())
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &Self> {
forward!(self.syntax.ancestors())
}
#[inline]
pub fn children(&self) -> impl Iterator<Item = &Self> {
forward!(self.syntax.children())
}
#[inline]
pub fn children_with_tokens(&self) -> impl Iterator<Item = ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.children_with_tokens())
}
#[inline]
pub fn first_child(&self) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.first_child())
}
#[inline]
pub fn first_child_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.first_child_or_token())
}
#[inline]
pub fn last_child(&self) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.last_child())
}
#[inline]
pub fn last_child_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.last_child_or_token())
}
#[inline]
pub fn next_child_after(&self, n: usize, offset: TextSize) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.next_child_after(n, offset))
}
#[inline]
pub fn next_child_or_token_after(&self, n: usize, offset: TextSize) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.next_child_or_token_after(n, offset))
}
#[inline]
pub fn prev_child_before(&self, n: usize, offset: TextSize) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.prev_child_before(n, offset))
}
#[inline]
pub fn prev_child_or_token_before(&self, n: usize, offset: TextSize) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.prev_child_or_token_before(n, offset))
}
#[inline]
pub fn next_sibling(&self) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.next_sibling())
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.next_sibling_or_token())
}
#[inline]
pub fn prev_sibling(&self) -> Option<&ResolvedNode<L, D>> {
forward!(self.syntax.prev_sibling())
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.prev_sibling_or_token())
}
#[inline]
pub fn first_token(&self) -> Option<&ResolvedToken<L, D>> {
forward_token!(self.syntax.first_token())
}
#[inline]
pub fn last_token(&self) -> Option<&ResolvedToken<L, D>> {
forward_token!(self.syntax.last_token())
}
#[inline]
pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &ResolvedNode<L, D>> {
forward!(self.syntax.siblings(direction))
}
#[inline]
pub fn siblings_with_tokens(&self, direction: Direction) -> impl Iterator<Item = ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.siblings_with_tokens(direction))
}
#[inline]
pub fn descendants(&self) -> impl Iterator<Item = &ResolvedNode<L, D>> {
forward!(self.syntax.descendants())
}
#[inline]
pub fn descendants_with_tokens(&self) -> impl Iterator<Item = ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.descendants_with_tokens())
}
#[inline(always)]
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&ResolvedNode<L, D>>> {
self.syntax
.preorder()
.map(|event| event.map(|node| unsafe { Self::coerce_ref(node) }))
}
#[inline(always)]
pub fn preorder_with_tokens(&self) -> impl Iterator<Item = WalkEvent<ResolvedElementRef<'_, L, D>>> {
self.syntax
.preorder_with_tokens()
.map(|event| event.map(|elem| unsafe { ResolvedElementRef::coerce_ref(elem) }))
}
pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<ResolvedToken<L, D>> {
self.syntax
.token_at_offset(offset)
.map(|token| ResolvedToken { syntax: token })
}
pub fn covering_element(&self, range: TextRange) -> ResolvedElementRef<'_, L, D> {
unsafe { ResolvedElementRef::coerce_ref(self.syntax.covering_element(range)) }
}
}
impl<L: Language, D> ResolvedToken<L, D> {
#[inline]
pub fn try_resolved(&self) -> Option<&ResolvedToken<L, D>> {
Some(self)
}
#[inline]
pub fn resolved(&self) -> &ResolvedToken<L, D> {
self
}
#[inline]
pub fn parent(&self) -> &ResolvedNode<L, D> {
unsafe { ResolvedNode::coerce_ref(self.syntax.parent()) }
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &ResolvedNode<L, D>> {
forward_node!(self.syntax.ancestors())
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.next_sibling_or_token())
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.prev_sibling_or_token())
}
#[inline]
pub fn siblings_with_tokens(&self, direction: Direction) -> impl Iterator<Item = ResolvedElementRef<'_, L, D>> {
forward_as_elem!(self.syntax.siblings_with_tokens(direction))
}
pub fn next_token(&self) -> Option<&ResolvedToken<L, D>> {
forward!(self.syntax.next_token())
}
pub fn prev_token(&self) -> Option<&ResolvedToken<L, D>> {
forward!(self.syntax.prev_token())
}
}
impl<L: Language, D> ResolvedElement<L, D> {
#[inline]
pub fn text_range(&self) -> TextRange {
match self {
NodeOrToken::Node(it) => it.text_range(),
NodeOrToken::Token(it) => it.text_range(),
}
}
#[inline]
pub fn syntax_kind(&self) -> SyntaxKind {
match self {
NodeOrToken::Node(it) => it.syntax_kind(),
NodeOrToken::Token(it) => it.syntax_kind(),
}
}
#[inline]
pub fn kind(&self) -> L::Kind {
match self {
NodeOrToken::Node(it) => it.kind(),
NodeOrToken::Token(it) => it.kind(),
}
}
#[inline]
pub fn parent(&self) -> Option<&ResolvedNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &ResolvedNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&ResolvedToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&ResolvedToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
match self {
NodeOrToken::Node(it) => it.next_sibling_or_token(),
NodeOrToken::Token(it) => it.next_sibling_or_token(),
}
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, L, D>> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
}
impl<'a, L: Language, D> ResolvedElementRef<'a, L, D> {
#[inline]
pub fn text_range(&self) -> TextRange {
match self {
NodeOrToken::Node(it) => it.text_range(),
NodeOrToken::Token(it) => it.text_range(),
}
}
#[inline]
pub fn syntax_kind(&self) -> SyntaxKind {
match self {
NodeOrToken::Node(it) => it.syntax_kind(),
NodeOrToken::Token(it) => it.syntax_kind(),
}
}
#[inline]
pub fn kind(&self) -> L::Kind {
match self {
NodeOrToken::Node(it) => it.kind(),
NodeOrToken::Token(it) => it.kind(),
}
}
#[inline]
pub fn parent(&self) -> Option<&'a ResolvedNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &'a ResolvedNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&'a ResolvedToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&'a ResolvedToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'a, L, D>> {
match self {
NodeOrToken::Node(it) => it.next_sibling_or_token(),
NodeOrToken::Token(it) => it.next_sibling_or_token(),
}
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'a, L, D>> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
}
#[test]
fn assert_send_sync() {
use crate::SyntaxKind;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum L {}
#[derive(Debug)]
enum Kind {
Var,
}
impl Language for L {
type Kind = Kind;
fn kind_from_raw(_: SyntaxKind) -> Self::Kind {
Kind::Var
}
fn kind_to_raw(_: Self::Kind) -> SyntaxKind {
SyntaxKind(0)
}
}
fn f<T: Send + Sync>() {}
f::<ResolvedNode<L>>();
f::<ResolvedToken<L>>();
f::<ResolvedElement<L>>();
f::<ResolvedElementRef<'static, L>>();
}