diff options
Diffstat (limited to 'crates/ra_syntax/src/ast.rs')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 108 |
1 files changed, 5 insertions, 103 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 1ac0201b8..ab0f44dd2 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -11,10 +11,7 @@ pub mod make; | |||
11 | use std::marker::PhantomData; | 11 | use std::marker::PhantomData; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | syntax_node::{ | 14 | syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, |
15 | NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, | ||
16 | SyntaxToken, | ||
17 | }, | ||
18 | SmolStr, SyntaxKind, | 15 | SmolStr, SyntaxKind, |
19 | }; | 16 | }; |
20 | 17 | ||
@@ -33,24 +30,16 @@ pub use self::{ | |||
33 | /// conversion itself has zero runtime cost: ast and syntax nodes have exactly | 30 | /// conversion itself has zero runtime cost: ast and syntax nodes have exactly |
34 | /// the same representation: a pointer to the tree root and a pointer to the | 31 | /// the same representation: a pointer to the tree root and a pointer to the |
35 | /// node itself. | 32 | /// node itself. |
36 | pub trait AstNode: AstElement { | 33 | pub trait AstNode { |
37 | fn can_cast(kind: SyntaxKind) -> bool | 34 | fn can_cast(kind: SyntaxKind) -> bool |
38 | where | 35 | where |
39 | Self: Sized; | 36 | Self: Sized; |
40 | 37 | ||
41 | fn cast_or_return(syntax: SyntaxNode) -> Result<Self, SyntaxNode> | ||
42 | where | ||
43 | Self: Sized; | ||
44 | |||
45 | fn cast(syntax: SyntaxNode) -> Option<Self> | 38 | fn cast(syntax: SyntaxNode) -> Option<Self> |
46 | where | 39 | where |
47 | Self: Sized, | 40 | Self: Sized; |
48 | { | ||
49 | <Self as AstNode>::cast_or_return(syntax).ok() | ||
50 | } | ||
51 | 41 | ||
52 | fn syntax(&self) -> &SyntaxNode; | 42 | fn syntax(&self) -> &SyntaxNode; |
53 | fn into_syntax(self) -> SyntaxNode; | ||
54 | } | 43 | } |
55 | 44 | ||
56 | #[test] | 45 | #[test] |
@@ -59,51 +48,22 @@ fn assert_ast_is_object_safe() { | |||
59 | } | 48 | } |
60 | 49 | ||
61 | /// Like `AstNode`, but wraps tokens rather than interior nodes. | 50 | /// Like `AstNode`, but wraps tokens rather than interior nodes. |
62 | pub trait AstToken: AstElement { | 51 | pub trait AstToken { |
63 | fn can_cast(token: SyntaxKind) -> bool | 52 | fn can_cast(token: SyntaxKind) -> bool |
64 | where | 53 | where |
65 | Self: Sized; | 54 | Self: Sized; |
66 | 55 | ||
67 | fn cast_or_return(syntax: SyntaxToken) -> Result<Self, SyntaxToken> | ||
68 | where | ||
69 | Self: Sized; | ||
70 | |||
71 | fn cast(syntax: SyntaxToken) -> Option<Self> | 56 | fn cast(syntax: SyntaxToken) -> Option<Self> |
72 | where | 57 | where |
73 | Self: Sized, | 58 | Self: Sized; |
74 | { | ||
75 | <Self as AstToken>::cast_or_return(syntax).ok() | ||
76 | } | ||
77 | 59 | ||
78 | fn syntax(&self) -> &SyntaxToken; | 60 | fn syntax(&self) -> &SyntaxToken; |
79 | fn into_syntax(self) -> SyntaxToken; | ||
80 | 61 | ||
81 | fn text(&self) -> &SmolStr { | 62 | fn text(&self) -> &SmolStr { |
82 | self.syntax().text() | 63 | self.syntax().text() |
83 | } | 64 | } |
84 | } | 65 | } |
85 | 66 | ||
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 | |||
107 | /// An iterator over `SyntaxNode` children of a particular AST type. | 67 | /// An iterator over `SyntaxNode` children of a particular AST type. |
108 | #[derive(Debug, Clone)] | 68 | #[derive(Debug, Clone)] |
109 | pub struct AstChildren<N> { | 69 | pub struct AstChildren<N> { |
@@ -132,64 +92,6 @@ fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> { | |||
132 | AstChildren::new(parent.syntax()) | 92 | AstChildren::new(parent.syntax()) |
133 | } | 93 | } |
134 | 94 | ||
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 | |||
193 | #[test] | 95 | #[test] |
194 | fn test_doc_comment_none() { | 96 | fn test_doc_comment_none() { |
195 | let file = SourceFile::parse( | 97 | let file = SourceFile::parse( |