@@ -11,7 +11,10 @@ pub mod make;
1111use std:: marker:: PhantomData ;
1212
1313use crate :: {
14- syntax_node:: { SyntaxNode , SyntaxNodeChildren , SyntaxToken } ,
14+ syntax_node:: {
15+ NodeOrToken , SyntaxElement , SyntaxElementChildren , SyntaxNode , SyntaxNodeChildren ,
16+ SyntaxToken ,
17+ } ,
1518 SmolStr , SyntaxKind ,
1619} ;
1720
@@ -30,16 +33,24 @@ pub use self::{
3033/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
3134/// the same representation: a pointer to the tree root and a pointer to the
3235/// node itself.
33- pub trait AstNode : std :: fmt :: Display {
36+ pub trait AstNode : AstElement {
3437 fn can_cast ( kind : SyntaxKind ) -> bool
3538 where
3639 Self : Sized ;
3740
38- fn cast ( syntax : SyntaxNode ) -> Option < Self >
41+ fn cast_or_return ( syntax : SyntaxNode ) -> Result < Self , SyntaxNode >
3942 where
4043 Self : Sized ;
4144
45+ fn cast ( syntax : SyntaxNode ) -> Option < Self >
46+ where
47+ Self : Sized ,
48+ {
49+ <Self as AstNode >:: cast_or_return ( syntax) . ok ( )
50+ }
51+
4252 fn syntax ( & self ) -> & SyntaxNode ;
53+ fn into_syntax ( self ) -> SyntaxNode ;
4354}
4455
4556#[ test]
@@ -48,16 +59,51 @@ fn assert_ast_is_object_safe() {
4859}
4960
5061/// Like `AstNode`, but wraps tokens rather than interior nodes.
51- pub trait AstToken {
52- fn cast ( token : SyntaxToken ) -> Option < Self >
62+ pub trait AstToken : AstElement {
63+ fn can_cast ( token : SyntaxKind ) -> bool
5364 where
5465 Self : Sized ;
66+
67+ fn cast_or_return ( syntax : SyntaxToken ) -> Result < Self , SyntaxToken >
68+ where
69+ Self : Sized ;
70+
71+ fn cast ( syntax : SyntaxToken ) -> Option < Self >
72+ where
73+ Self : Sized ,
74+ {
75+ <Self as AstToken >:: cast_or_return ( syntax) . ok ( )
76+ }
77+
5578 fn syntax ( & self ) -> & SyntaxToken ;
79+ fn into_syntax ( self ) -> SyntaxToken ;
80+
5681 fn text ( & self ) -> & SmolStr {
5782 self . syntax ( ) . text ( )
5883 }
5984}
6085
86+ /// Like `AstNode`, but wraps either nodes or tokens rather than interior nodes.
87+ pub trait AstElement : std:: fmt:: Display {
88+ fn can_cast_element ( kind : SyntaxKind ) -> bool
89+ where
90+ Self : Sized ;
91+
92+ fn cast_or_return_element ( syntax : SyntaxElement ) -> Result < Self , SyntaxElement >
93+ where
94+ Self : Sized ;
95+
96+ fn cast_element ( syntax : SyntaxElement ) -> Option < Self >
97+ where
98+ Self : Sized ,
99+ {
100+ <Self as AstElement >:: cast_or_return_element ( syntax) . ok ( )
101+ }
102+
103+ fn syntax_element ( & self ) -> NodeOrToken < & SyntaxNode , & SyntaxToken > ;
104+ fn into_syntax_element ( self ) -> SyntaxElement ;
105+ }
106+
61107/// An iterator over `SyntaxNode` children of a particular AST type.
62108#[ derive( Debug , Clone ) ]
63109pub struct AstChildren < N > {
@@ -86,6 +132,64 @@ fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> {
86132 AstChildren :: new ( parent. syntax ( ) )
87133}
88134
135+ /// An iterator over `SyntaxToken` children of a particular AST type.
136+ #[ derive( Debug , Clone ) ]
137+ pub struct AstChildTokens < N > {
138+ inner : SyntaxElementChildren ,
139+ ph : PhantomData < N > ,
140+ }
141+
142+ impl < N > AstChildTokens < N > {
143+ fn new ( parent : & SyntaxNode ) -> Self {
144+ AstChildTokens { inner : parent. children_with_tokens ( ) , ph : PhantomData }
145+ }
146+ }
147+
148+ impl < N : AstToken > Iterator for AstChildTokens < N > {
149+ type Item = N ;
150+ fn next ( & mut self ) -> Option < N > {
151+ self . inner . by_ref ( ) . filter_map ( |x| x. into_token ( ) ) . find_map ( N :: cast)
152+ }
153+ }
154+
155+ fn child_token_opt < P : AstNode + ?Sized , C : AstToken > ( parent : & P ) -> Option < C > {
156+ child_tokens ( parent) . next ( )
157+ }
158+
159+ fn child_tokens < P : AstNode + ?Sized , C : AstToken > ( parent : & P ) -> AstChildTokens < C > {
160+ AstChildTokens :: new ( parent. syntax ( ) )
161+ }
162+
163+ /// An iterator over `SyntaxNode` children of a particular AST type.
164+ #[ derive( Debug , Clone ) ]
165+ pub struct AstChildElements < N > {
166+ inner : SyntaxElementChildren ,
167+ ph : PhantomData < N > ,
168+ }
169+
170+ impl < N > AstChildElements < N > {
171+ fn new ( parent : & SyntaxNode ) -> Self {
172+ AstChildElements { inner : parent. children_with_tokens ( ) , ph : PhantomData }
173+ }
174+ }
175+
176+ impl < N : AstElement > Iterator for AstChildElements < N > {
177+ type Item = N ;
178+ fn next ( & mut self ) -> Option < N > {
179+ self . inner . by_ref ( ) . find_map ( N :: cast_element)
180+ }
181+ }
182+
183+ #[ allow( dead_code) ]
184+ fn child_element_opt < P : AstNode + ?Sized , C : AstElement > ( parent : & P ) -> Option < C > {
185+ child_elements ( parent) . next ( )
186+ }
187+
188+ #[ allow( dead_code) ]
189+ fn child_elements < P : AstNode + ?Sized , C : AstElement > ( parent : & P ) -> AstChildElements < C > {
190+ AstChildElements :: new ( parent. syntax ( ) )
191+ }
192+
89193#[ test]
90194fn test_doc_comment_none ( ) {
91195 let file = SourceFile :: parse (
0 commit comments