1use std::marker::PhantomData;23use crate::{SyntaxKind, SyntaxNode, SyntaxNodeChildren, SyntaxToken};456789pub trait AstNode {10 fn can_cast(kind: SyntaxKind) -> bool11 where12 Self: Sized;1314 fn cast(syntax: SyntaxNode) -> Option<Self>15 where16 Self: Sized;1718 fn syntax(&self) -> &SyntaxNode;19 fn clone_for_update(&self) -> Self20 where21 Self: Sized,22 {23 Self::cast(self.syntax().clone_for_update()).unwrap()24 }25 fn clone_subtree(&self) -> Self26 where27 Self: Sized,28 {29 Self::cast(self.syntax().clone_subtree()).unwrap()30 }31}323334pub trait AstToken {35 fn can_cast(token: SyntaxKind) -> bool36 where37 Self: Sized;3839 fn cast(syntax: SyntaxToken) -> Option<Self>40 where41 Self: Sized;4243 fn syntax(&self) -> &SyntaxToken;4445 fn text(&self) -> &str {46 self.syntax().text()47 }48}4950#[derive(Debug, Clone)]51pub struct AstChildren<N> {52 inner: SyntaxNodeChildren,53 ph: PhantomData<N>,54}5556impl<N> AstChildren<N> {57 fn new(parent: &SyntaxNode) -> Self {58 AstChildren {59 inner: parent.children(),60 ph: PhantomData,61 }62 }63}6465impl<N: AstNode> Iterator for AstChildren<N> {66 type Item = N;67 fn next(&mut self) -> Option<N> {68 self.inner.find_map(N::cast)69 }70}7172pub mod support {73 use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7475 pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {76 parent.children().find_map(N::cast)77 }78 pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {79 parent.children_with_tokens().find_map(|n| match n {80 rowan::NodeOrToken::Node(_) => None,81 rowan::NodeOrToken::Token(t) => N::cast(t),82 })83 }8485 pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {86 AstChildren::new(parent)87 }8889 pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {90 parent91 .children_with_tokens()92 .filter_map(|it| it.into_token())93 .find(|it| it.kind() == kind)94 }95}