use std::sync::atomic::AtomicU32;
use lasso::Resolver;
use text_size::{TextRange, TextSize};
use super::*;
use crate::{green::GreenElementRef, Language, NodeOrToken, SyntaxKind, TokenAtOffset};
pub type SyntaxElement<L, D = ()> = NodeOrToken<SyntaxNode<L, D>, SyntaxToken<L, D>>;
impl<L: Language, D> From<SyntaxNode<L, D>> for SyntaxElement<L, D> {
fn from(node: SyntaxNode<L, D>) -> SyntaxElement<L, D> {
NodeOrToken::Node(node)
}
}
impl<L: Language, D> From<SyntaxToken<L, D>> for SyntaxElement<L, D> {
fn from(token: SyntaxToken<L, D>) -> SyntaxElement<L, D> {
NodeOrToken::Token(token)
}
}
impl<L: Language, D> SyntaxElement<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 SyntaxElementRef<'a, L, D = ()> = NodeOrToken<&'a SyntaxNode<L, D>, &'a SyntaxToken<L, D>>;
impl<'a, L: Language, D> From<&'a SyntaxNode<L, D>> for SyntaxElementRef<'a, L, D> {
fn from(node: &'a SyntaxNode<L, D>) -> Self {
NodeOrToken::Node(node)
}
}
impl<'a, L: Language, D> From<&'a SyntaxToken<L, D>> for SyntaxElementRef<'a, L, D> {
fn from(token: &'a SyntaxToken<L, D>) -> Self {
NodeOrToken::Token(token)
}
}
impl<'a, L: Language, D> From<&'a SyntaxElement<L, D>> for SyntaxElementRef<'a, L, D> {
fn from(element: &'a SyntaxElement<L, D>) -> Self {
match element {
NodeOrToken::Node(it) => Self::Node(it),
NodeOrToken::Token(it) => Self::Token(it),
}
}
}
impl<'a, L: Language, D> SyntaxElementRef<'a, 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),
}
}
}
impl<L: Language, D> SyntaxElement<L, D> {
pub(super) fn new(
element: GreenElementRef<'_>,
parent: &SyntaxNode<L, D>,
index: u32,
offset: TextSize,
ref_count: *mut AtomicU32,
) -> SyntaxElement<L, D> {
match element {
NodeOrToken::Node(node) => SyntaxNode::new_child(node, parent, index as u32, offset, ref_count).into(),
NodeOrToken::Token(_) => SyntaxToken::new(parent, index as u32, offset).into(),
}
}
#[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<&SyntaxNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&SyntaxToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&SyntaxToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<SyntaxElementRef<'_, 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<SyntaxElementRef<'_, 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> SyntaxElementRef<'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 SyntaxNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.parent(),
NodeOrToken::Token(it) => Some(it.parent()),
}
}
#[inline]
pub fn ancestors(&self) -> impl Iterator<Item = &'a SyntaxNode<L, D>> {
match self {
NodeOrToken::Node(it) => it.ancestors(),
NodeOrToken::Token(it) => it.parent().ancestors(),
}
}
#[inline]
pub fn first_token(&self) -> Option<&'a SyntaxToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.first_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn last_token(&self) -> Option<&'a SyntaxToken<L, D>> {
match self {
NodeOrToken::Node(it) => it.last_token(),
NodeOrToken::Token(it) => Some(it),
}
}
#[inline]
pub fn next_sibling_or_token(&self) -> Option<SyntaxElementRef<'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<SyntaxElementRef<'a, L, D>> {
match self {
NodeOrToken::Node(it) => it.prev_sibling_or_token(),
NodeOrToken::Token(it) => it.prev_sibling_or_token(),
}
}
#[inline]
pub(super) fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken<L, D>> {
assert!(self.text_range().start() <= offset && offset <= self.text_range().end());
match self {
NodeOrToken::Token(token) => TokenAtOffset::Single((*token).clone()),
NodeOrToken::Node(node) => node.token_at_offset(offset),
}
}
}