use std::{
fmt,
hash::Hash,
ops::{Deref, DerefMut},
sync::Arc as StdArc,
};
use text_size::{TextRange, TextSize};
use crate::{
RawSyntaxKind,
Syntax,
green::GreenNode,
interning::{Resolver, TokenKey},
syntax::*,
traversal::*,
util::*,
};
#[repr(transparent)]
pub struct ResolvedNode<S: Syntax, D: 'static = ()> {
pub(super) syntax: SyntaxNode<S, D>,
}
impl<S: Syntax, D> ResolvedNode<S, D> {
pub(super) unsafe fn coerce_ref(syntax: &SyntaxNode<S, D>) -> &Self {
unsafe { &*(syntax as *const _ as *const Self) }
}
pub fn syntax(&self) -> &SyntaxNode<S, D> {
&self.syntax
}
}
impl<S: Syntax, D> Clone for ResolvedNode<S, D> {
fn clone(&self) -> Self {
Self {
syntax: self.syntax.clone(),
}
}
}
impl<S: Syntax, D> Deref for ResolvedNode<S, D> {
type Target = SyntaxNode<S, D>;
fn deref(&self) -> &Self::Target {
&self.syntax
}
}
impl<S: Syntax, D> DerefMut for ResolvedNode<S, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.syntax
}
}
impl<S: Syntax, D> PartialEq for ResolvedNode<S, D> {
fn eq(&self, other: &Self) -> bool {
self.syntax == other.syntax
}
}
impl<S: Syntax, D> Eq for ResolvedNode<S, D> {}
impl<S: Syntax, D> Hash for ResolvedNode<S, D> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.syntax.hash(state);
}
}
#[repr(transparent)]
pub struct ResolvedToken<S: Syntax, D: 'static = ()> {
syntax: SyntaxToken<S, D>,
}
impl<S: Syntax, D> ResolvedToken<S, D> {
pub(super) unsafe fn coerce_ref(syntax: &SyntaxToken<S, D>) -> &Self {
unsafe { &*(syntax as *const _ as *const Self) }
}
pub fn syntax(&self) -> &SyntaxToken<S, D> {
&self.syntax
}
}
impl<S: Syntax, D> Clone for ResolvedToken<S, D> {
fn clone(&self) -> Self {
Self {
syntax: self.syntax.clone(),
}
}
}
impl<S: Syntax, D> Deref for ResolvedToken<S, D> {
type Target = SyntaxToken<S, D>;
fn deref(&self) -> &Self::Target {
&self.syntax
}
}
impl<S: Syntax, D> DerefMut for ResolvedToken<S, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.syntax
}
}
impl<S: Syntax, D> PartialEq for ResolvedToken<S, D> {
fn eq(&self, other: &Self) -> bool {
self.syntax == other.syntax
}
}
impl<S: Syntax, D> Eq for ResolvedToken<S, D> {}
impl<S: Syntax, D> Hash for ResolvedToken<S, D> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.syntax.hash(state);
}
}
pub type ResolvedElement<S, D = ()> = NodeOrToken<ResolvedNode<S, D>, ResolvedToken<S, D>>;
impl<S: Syntax, D> From<ResolvedNode<S, D>> for ResolvedElement<S, D> {
fn from(node: ResolvedNode<S, D>) -> ResolvedElement<S, D> {
NodeOrToken::Node(node)
}
}
impl<S: Syntax, D> From<ResolvedToken<S, D>> for ResolvedElement<S, D> {
fn from(token: ResolvedToken<S, D>) -> ResolvedElement<S, D> {
NodeOrToken::Token(token)
}
}
impl<S: Syntax, D> ResolvedElement<S, D> {
#[allow(missing_docs)]
pub fn display(&self, resolver: &impl Resolver<TokenKey>) -> String {
match self {
NodeOrToken::Node(it) => it.display(resolver),
NodeOrToken::Token(it) => it.display(resolver),
}
}
}
pub type ResolvedElementRef<'a, S, D = ()> = NodeOrToken<&'a ResolvedNode<S, D>, &'a ResolvedToken<S, D>>;
impl<'a, S: Syntax, D> ResolvedElementRef<'a, S, D> {
pub(super) unsafe fn coerce_ref(syntax: SyntaxElementRef<'a, S, D>) -> Self {
unsafe {
match syntax {
NodeOrToken::Node(node) => Self::Node(ResolvedNode::coerce_ref(node)),
NodeOrToken::Token(token) => Self::Token(ResolvedToken::coerce_ref(token)),
}
}
}
}
impl<'a, S: Syntax, D> From<&'a ResolvedNode<S, D>> for ResolvedElementRef<'a, S, D> {
fn from(node: &'a ResolvedNode<S, D>) -> Self {
NodeOrToken::Node(node)
}
}
impl<'a, S: Syntax, D> From<&'a ResolvedToken<S, D>> for ResolvedElementRef<'a, S, D> {
fn from(token: &'a ResolvedToken<S, D>) -> Self {
NodeOrToken::Token(token)
}
}
impl<'a, S: Syntax, D> From<&'a ResolvedElement<S, D>> for ResolvedElementRef<'a, S, D> {
fn from(element: &'a ResolvedElement<S, D>) -> Self {
match element {
NodeOrToken::Node(it) => Self::Node(it),
NodeOrToken::Token(it) => Self::Token(it),
}
}
}
impl<S: Syntax, D> ResolvedNode<S, D> {
#[inline]
pub fn text(&self) -> SyntaxText<'_, '_, dyn Resolver<TokenKey>, S, D> {
SyntaxText::new(self, &**self.resolver())
}
}
impl<S: Syntax, D> fmt::Debug for ResolvedNode<S, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.write_debug(&**self.resolver(), f, f.alternate())
}
}
impl<S: Syntax, D> fmt::Display for ResolvedNode<S, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.write_display(&**self.resolver(), f)
}
}
impl<S: Syntax, D> ResolvedToken<S, D> {
#[inline]
pub fn text(&self) -> &str {
self.static_text()
.or_else(|| self.green().text(&**self.resolver()))
.unwrap()
}
}
impl<S: Syntax, D> fmt::Debug for ResolvedToken<S, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.write_debug(&**self.resolver(), f)
}
}
impl<S: Syntax, D> fmt::Display for ResolvedToken<S, D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.write_display(&**self.resolver(), f)
}
}
#[cfg(feature = "serialize")]
impl<S, D> ResolvedNode<S, D>
where
S: Syntax,
{
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<S: Syntax, D> ResolvedNode<S, D> {
pub fn resolver(&self) -> &StdArc<dyn Resolver<TokenKey>> {
self.syntax.resolver().unwrap()
}
#[inline]
pub fn new_root_with_resolver(green: GreenNode, resolver: impl Resolver<TokenKey> + 'static) -> Self {
SyntaxNode::new_root_with_resolver(green, resolver)
}
#[inline]
pub fn try_resolved(&self) -> Option<&ResolvedNode<S, D>> {
Some(self)
}
#[inline]
pub fn resolved(&self) -> &ResolvedNode<S, D> {
self
}
#[inline]
pub fn root(&self) -> &SyntaxNode<S, 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<'_, S, D>> {
forward_as_elem!(self.syntax.children_with_tokens())
}
#[inline]
pub fn first_child(&self) -> Option<&ResolvedNode<S, D>> {
forward!(self.syntax.first_child())
}
#[inline]
pub fn first_child_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.first_child_or_token())
}
#[inline]
pub fn last_child(&self) -> Option<&ResolvedNode<S, D>> {
forward!(self.syntax.last_child())
}
#[inline]
pub fn last_child_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.last_child_or_token())
}
#[inline]
pub fn next_child_after(&self, n: usize, offset: TextSize) -> Option<&ResolvedNode<S, D>> {
forward!(self.syntax.next_child_after(n, offset))
}
#[inline]
pub fn next_child_or_token_after(&self, n: usize, offset: TextSize) -> Option<ResolvedElementRef<'_, S, 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<S, D>> {
forward!(self.syntax.prev_child_before(n, offset))
}
#[inline]
pub fn prev_child_or_token_before(&self, n: usize, offset: TextSize) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.prev_child_or_token_before(n, offset))
}
#[inline]
pub fn next_sibling(&self) -> Option<&ResolvedNode<S, D>> {
forward!(self.syntax.next_sibling())
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.next_sibling_or_token())
}
#[inline]
pub fn prev_sibling(&self) -> Option<&ResolvedNode<S, D>> {
forward!(self.syntax.prev_sibling())
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.prev_sibling_or_token())
}
#[inline]
pub fn first_token(&self) -> Option<&ResolvedToken<S, D>> {
forward_token!(self.syntax.first_token())
}
#[inline]
pub fn last_token(&self) -> Option<&ResolvedToken<S, D>> {
forward_token!(self.syntax.last_token())
}
#[inline]
pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &ResolvedNode<S, D>> {
forward!(self.syntax.siblings(direction))
}
#[inline]
pub fn siblings_with_tokens(&self, direction: Direction) -> impl Iterator<Item = ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.siblings_with_tokens(direction))
}
#[inline]
pub fn descendants(&self) -> impl Iterator<Item = &ResolvedNode<S, D>> {
forward!(self.syntax.descendants())
}
#[inline]
pub fn descendants_with_tokens(&self) -> impl Iterator<Item = ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.descendants_with_tokens())
}
#[inline(always)]
pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&ResolvedNode<S, 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<'_, S, 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<S, D>> {
self.syntax
.token_at_offset(offset)
.map(|token| ResolvedToken { syntax: token })
}
pub fn covering_element(&self, range: TextRange) -> ResolvedElementRef<'_, S, D> {
unsafe { ResolvedElementRef::coerce_ref(self.syntax.covering_element(range)) }
}
}
impl<S: Syntax, D> ResolvedToken<S, D> {
pub fn resolver(&self) -> &StdArc<dyn Resolver<TokenKey>> {
self.syntax.resolver().unwrap()
}
#[inline]
pub fn try_resolved(&self) -> Option<&ResolvedToken<S, D>> {
Some(self)
}
#[inline]
pub fn resolved(&self) -> &ResolvedToken<S, D> {
self
}
#[inline]
pub fn parent(&self) -> &ResolvedNode<S, D> {
unsafe { ResolvedNode::coerce_ref(self.syntax.parent()) }
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &ResolvedNode<S, D>> {
forward_node!(self.syntax.ancestors())
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.next_sibling_or_token())
}
#[inline]
pub fn prev_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.prev_sibling_or_token())
}
#[inline]
pub fn siblings_with_tokens(&self, direction: Direction) -> impl Iterator<Item = ResolvedElementRef<'_, S, D>> {
forward_as_elem!(self.syntax.siblings_with_tokens(direction))
}
pub fn next_token(&self) -> Option<&ResolvedToken<S, D>> {
forward!(self.syntax.next_token())
}
pub fn prev_token(&self) -> Option<&ResolvedToken<S, D>> {
forward!(self.syntax.prev_token())
}
}
impl<S: Syntax, D> ResolvedElement<S, 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) -> RawSyntaxKind {
match self {
NodeOrToken::Node(it) => it.syntax_kind(),
NodeOrToken::Token(it) => it.syntax_kind(),
}
}
#[inline]
pub fn kind(&self) -> S {
match self {
NodeOrToken::Node(it) => it.kind(),
NodeOrToken::Token(it) => it.kind(),
}
}
#[inline]
pub fn parent(&self) -> Option<&ResolvedNode<S, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &ResolvedNode<S, D>> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&ResolvedToken<S, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&ResolvedToken<S, D>> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<ResolvedElementRef<'_, S, 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<'_, S, D>> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
}
impl<'a, S: Syntax, D> ResolvedElementRef<'a, S, 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) -> RawSyntaxKind {
match self {
NodeOrToken::Node(it) => it.syntax_kind(),
NodeOrToken::Token(it) => it.syntax_kind(),
}
}
#[inline]
pub fn kind(&self) -> S {
match self {
NodeOrToken::Node(it) => it.kind(),
NodeOrToken::Token(it) => it.kind(),
}
}
#[inline]
pub fn parent(&self) -> Option<&'a ResolvedNode<S, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &'a ResolvedNode<S, D>> + use<'a, S, D> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&'a ResolvedToken<S, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&'a ResolvedToken<S, 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, S, 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, S, D>> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
}