1use std::marker::PhantomData;23use crate::{SyntaxKind, SyntaxNode, SyntaxNodeChildren, SyntaxToken};45678910pub trait AstNode {11 fn can_cast(kind: SyntaxKind) -> bool12 where13 Self: Sized;1415 fn cast(syntax: SyntaxNode) -> Option<Self>16 where17 Self: Sized;1819 fn syntax(&self) -> &SyntaxNode;20 #[must_use]21 fn clone_for_update(&self) -> Self22 where23 Self: Sized,24 {25 Self::cast(self.syntax().clone_for_update()).unwrap()26 }27 #[must_use]28 fn clone_subtree(&self) -> Self29 where30 Self: Sized,31 {32 Self::cast(self.syntax().clone_subtree()).unwrap()33 }34}353637pub trait AstToken {38 fn can_cast(token: SyntaxKind) -> bool39 where40 Self: Sized;4142 fn cast(syntax: SyntaxToken) -> Option<Self>43 where44 Self: Sized;4546 fn syntax(&self) -> &SyntaxToken;4748 fn text(&self) -> &str {49 self.syntax().text()50 }51}5253#[derive(Debug, Clone)]54pub struct AstChildren<N> {55 inner: SyntaxNodeChildren,56 ph: PhantomData<N>,57}5859impl<N> AstChildren<N> {60 fn new(parent: &SyntaxNode) -> Self {61 AstChildren {62 inner: parent.children(),63 ph: PhantomData,64 }65 }66}6768impl<N: AstNode> Iterator for AstChildren<N> {69 type Item = N;70 fn next(&mut self) -> Option<N> {71 self.inner.find_map(N::cast)72 }73}7475pub mod support {76 use rowan::NodeOrToken;7778 use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7980 pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {81 parent.children().find_map(N::cast)82 }83 pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {84 parent.children_with_tokens().find_map(|n| match n {85 rowan::NodeOrToken::Node(_) => None,86 rowan::NodeOrToken::Token(t) => N::cast(t),87 })88 }8990 pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {91 AstChildren::new(parent)92 }9394 pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {95 parent96 .children_with_tokens()97 .filter_map(NodeOrToken::into_token)98 .find(|it| it.kind() == kind)99 }100}