use crate::{decl::Decl, expr::Expr, stmt::Stmt};
mod parents;
use bitflags::bitflags;
use gramatika::{ArcStr, Span, Spanned, Substr};
use lsp_types::{Position, Range};
pub use parents::{find_parent, find_parents};
#[derive(DebugLisp, Clone)]
pub enum SyntaxNode {
Decl(Decl),
Stmt(Stmt),
Expr(Expr),
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct SyntaxKind: u8 {
const DECL = 0b001;
const STMT = 0b010;
const EXPR = 0b100;
}
}
pub trait GetSyntaxKind {
const KIND: SyntaxKind;
}
impl GetSyntaxKind for Decl {
const KIND: SyntaxKind = SyntaxKind::DECL;
}
impl GetSyntaxKind for Stmt {
const KIND: SyntaxKind = SyntaxKind::STMT;
}
impl GetSyntaxKind for Expr {
const KIND: SyntaxKind = SyntaxKind::EXPR;
}
impl GetSyntaxKind for SyntaxNode {
const KIND: SyntaxKind = SyntaxKind::all();
}
impl Spanned for SyntaxNode {
fn span(&self) -> gramatika::Span {
match self {
SyntaxNode::Decl(decl) => decl.span(),
SyntaxNode::Stmt(stmt) => stmt.span(),
SyntaxNode::Expr(expr) => expr.span(),
}
}
}
impl From<SyntaxNode> for Decl {
fn from(value: SyntaxNode) -> Self {
match value {
SyntaxNode::Decl(inner) => inner,
_ => panic!("Expected a `SyntaxNode::Decl(...)`"),
}
}
}
impl From<SyntaxNode> for Stmt {
fn from(value: SyntaxNode) -> Self {
match value {
SyntaxNode::Stmt(inner) => inner,
_ => panic!("Expected a `SyntaxNode::Stmt(...)`"),
}
}
}
impl From<SyntaxNode> for Expr {
fn from(value: SyntaxNode) -> Self {
match value {
SyntaxNode::Expr(inner) => inner,
_ => panic!("Expected a `SyntaxNode::Expr(...)`"),
}
}
}
pub trait ToRange {
fn to_range(self) -> Range;
}
impl ToRange for Span {
fn to_range(self) -> Range {
Range {
start: Position {
line: self.start.line as _,
character: self.start.character as _,
},
end: Position {
line: self.end.line as _,
character: self.end.character as _,
},
}
}
}
pub(crate) fn join_substrs(start: &Substr, end: &Substr) -> Substr {
assert!(ArcStr::ptr_eq(start.parent(), end.parent()));
assert!(end.range().end > start.range().start);
let source = start.parent().clone();
let range = start.range().start..end.range().end;
unsafe { Substr::from_parts_unchecked(source, range) }
}
#[cfg(test)]
pub(crate) trait WithComments {
type Output: Sized + std::fmt::Debug;
fn get(&self) -> &[Self::Output];
}
#[cfg(test)]
pub(crate) trait WithTokens {
type Output: Sized + std::fmt::Debug;
fn into(self) -> Vec<Self::Output>;
}
#[cfg(test)]
pub(crate) trait WithErrors {
type Output: Sized + std::fmt::Display;
fn get(&self) -> &[Self::Output];
}