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 #[must_use]20 fn clone_for_update(&self) -> Self21 where22 Self: Sized,23 {24 Self::cast(self.syntax().clone_for_update()).unwrap()25 }26 #[must_use]27 fn clone_subtree(&self) -> Self28 where29 Self: Sized,30 {31 Self::cast(self.syntax().clone_subtree()).unwrap()32 }33}343536pub trait AstToken {37 fn can_cast(token: SyntaxKind) -> bool38 where39 Self: Sized;4041 fn cast(syntax: SyntaxToken) -> Option<Self>42 where43 Self: Sized;4445 fn syntax(&self) -> &SyntaxToken;4647 fn text(&self) -> &str {48 self.syntax().text()49 }50}5152#[derive(Debug, Clone)]53pub struct AstChildren<N> {54 inner: SyntaxNodeChildren,55 ph: PhantomData<N>,56}5758impl<N> AstChildren<N> {59 fn new(parent: &SyntaxNode) -> Self {60 AstChildren {61 inner: parent.children(),62 ph: PhantomData,63 }64 }65}6667impl<N: AstNode> Iterator for AstChildren<N> {68 type Item = N;69 fn next(&mut self) -> Option<N> {70 self.inner.find_map(N::cast)71 }72}7374pub mod support {75 use rowan::NodeOrToken;7677 use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7879 pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {80 parent.children().find_map(N::cast)81 }82 pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {83 parent.children_with_tokens().find_map(|n| match n {84 rowan::NodeOrToken::Node(_) => None,85 rowan::NodeOrToken::Token(t) => N::cast(t),86 })87 }8889 pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {90 AstChildren::new(parent)91 }9293 pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {94 parent95 .children_with_tokens()96 .filter_map(NodeOrToken::into_token)97 .find(|it| it.kind() == kind)98 }99}