use crate::tree::red::{SyntaxNode, SyntaxToken};
use crate::types::{FieldId, SyntaxKind};
pub trait AstNode: Sized {
fn can_cast(kind: SyntaxKind) -> bool;
fn cast(node: SyntaxNode) -> Option<Self>;
fn syntax(&self) -> &SyntaxNode;
}
pub trait AstNodeExt {
fn ast<N: AstNode>(&self) -> Option<N>;
fn child<N: AstNode>(&self) -> Option<N>;
fn children<'a, N: AstNode + 'a>(&'a self) -> impl Iterator<Item = N> + 'a;
fn field_child<N: AstNode>(&self, field_id: FieldId) -> Option<N>;
fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken>;
fn tokens(&self, kind: SyntaxKind) -> impl Iterator<Item = SyntaxToken> + '_;
}
impl AstNodeExt for SyntaxNode {
#[inline]
fn ast<N: AstNode>(&self) -> Option<N> {
N::cast(self.clone())
}
#[inline]
fn child<N: AstNode>(&self) -> Option<N> {
self.child_nodes().find_map(N::cast)
}
#[inline]
fn children<'a, N: AstNode + 'a>(&'a self) -> impl Iterator<Item = N> + 'a {
self.child_nodes().filter_map(N::cast)
}
#[inline]
fn field_child<N: AstNode>(&self, field_id: FieldId) -> Option<N> {
self.field_by_id(field_id).and_then(N::cast)
}
#[inline]
fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
self.child_tokens().find(|t| t.kind() == kind)
}
#[inline]
fn tokens(&self, kind: SyntaxKind) -> impl Iterator<Item = SyntaxToken> + '_ {
self.child_tokens().filter(move |t| t.kind() == kind)
}
}