aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src/codegen')
-rw-r--r--xtask/src/codegen/gen_syntax.rs87
1 files changed, 58 insertions, 29 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index 2dfb68371..6dae93aa2 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -146,14 +146,23 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
146 FieldSrc::Many(_) => { 146 FieldSrc::Many(_) => {
147 quote! { 147 quote! {
148 pub fn #method_name(&self) -> AstChildren<#ty> { 148 pub fn #method_name(&self) -> AstChildren<#ty> {
149 AstChildren::new(&self.syntax) 149 support::children(&self.syntax)
150 } 150 }
151 } 151 }
152 } 152 }
153 FieldSrc::Optional(_) | FieldSrc::Shorthand => { 153 FieldSrc::Optional(_) | FieldSrc::Shorthand => {
154 quote! { 154 let is_token = element_kinds_map[&ty.to_string()].has_tokens;
155 pub fn #method_name(&self) -> Option<#ty> { 155 if is_token {
156 AstChildren::new(&self.syntax).next() 156 quote! {
157 pub fn #method_name(&self) -> Option<#ty> {
158 support::token(&self.syntax)
159 }
160 }
161 } else {
162 quote! {
163 pub fn #method_name(&self) -> Option<#ty> {
164 support::child(&self.syntax)
165 }
157 } 166 }
158 } 167 }
159 } 168 }
@@ -205,6 +214,48 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
205 quote!(impl ast::#trait_name for #name {}) 214 quote!(impl ast::#trait_name for #name {})
206 }); 215 });
207 216
217 let element_kinds = &element_kinds_map[&en.name.to_string()];
218 assert!(
219 element_kinds.has_nodes ^ element_kinds.has_tokens,
220 "{}: {:#?}",
221 name,
222 element_kinds
223 );
224 let specific_ast_trait = {
225 let (ast_trait, syntax_type) = if element_kinds.has_tokens {
226 (quote!(AstToken), quote!(SyntaxToken))
227 } else {
228 (quote!(AstNode), quote!(SyntaxNode))
229 };
230
231 quote! {
232 impl #ast_trait for #name {
233 fn can_cast(kind: SyntaxKind) -> bool {
234 match kind {
235 #(#kinds)|* => true,
236 _ => false,
237 }
238 }
239 fn cast(syntax: #syntax_type) -> Option<Self> {
240 let res = match syntax.kind() {
241 #(
242 #kinds => #name::#variants(#variants { syntax }),
243 )*
244 _ => return None,
245 };
246 Some(res)
247 }
248 fn syntax(&self) -> &#syntax_type {
249 match self {
250 #(
251 #name::#variants(it) => &it.syntax,
252 )*
253 }
254 }
255 }
256 }
257 };
258
208 quote! { 259 quote! {
209 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 260 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
210 pub enum #name { 261 pub enum #name {
@@ -225,30 +276,8 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
225 } 276 }
226 } 277 }
227 278
228 impl AstNode for #name { 279 #specific_ast_trait
229 fn can_cast(kind: SyntaxKind) -> bool { 280
230 match kind {
231 #(#kinds)|* => true,
232 _ => false,
233 }
234 }
235 fn cast(syntax: SyntaxNode) -> Option<Self> {
236 let res = match syntax.kind() {
237 #(
238 #kinds => #name::#variants(#variants { syntax }),
239 )*
240 _ => return None,
241 };
242 Some(res)
243 }
244 fn syntax(&self) -> &SyntaxNode {
245 match self {
246 #(
247 #name::#variants(it) => &it.syntax,
248 )*
249 }
250 }
251 }
252 #(#traits)* 281 #(#traits)*
253 } 282 }
254 }); 283 });
@@ -268,7 +297,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
268 #[allow(unused_imports)] 297 #[allow(unused_imports)]
269 use crate::{ 298 use crate::{
270 SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, 299 SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
271 ast::{self, AstNode, AstToken, AstChildren}, 300 ast::{self, AstNode, AstToken, AstChildren, support},
272 }; 301 };
273 302
274 #(#tokens)* 303 #(#tokens)*