]> git.lizzy.rs Git - rust.git/blob - xtask/src/codegen/gen_syntax.rs
df3ec22c8d4c9170c765dc533a8b5cccda329372
[rust.git] / xtask / src / codegen / gen_syntax.rs
1 //! This module generates AST datatype used by rust-analyzer.
2 //!
3 //! Specifically, it generates the `SyntaxKind` enum and a number of newtype
4 //! wrappers around `SyntaxNode` which implement `syntax::AstNode`.
5
6 use std::{
7     collections::{BTreeSet, HashSet},
8     fmt::Write,
9 };
10
11 use proc_macro2::{Punct, Spacing};
12 use quote::{format_ident, quote};
13 use ungrammar::{rust_grammar, Grammar, Rule};
14
15 use crate::{
16     ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC},
17     codegen::{self, reformat, update, Mode},
18     project_root, Result,
19 };
20
21 pub fn generate_syntax(mode: Mode) -> Result<()> {
22     let grammar = rust_grammar();
23     let ast = lower(&grammar);
24
25     let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS);
26     let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
27     update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
28
29     let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
30     let contents = generate_tokens(&ast)?;
31     update(ast_tokens_file.as_path(), &contents, mode)?;
32
33     let ast_nodes_file = project_root().join(codegen::AST_NODES);
34     let contents = generate_nodes(KINDS_SRC, &ast)?;
35     update(ast_nodes_file.as_path(), &contents, mode)?;
36
37     Ok(())
38 }
39
40 fn generate_tokens(grammar: &AstSrc) -> Result<String> {
41     let tokens = grammar.tokens.iter().map(|token| {
42         let name = format_ident!("{}", token);
43         let kind = format_ident!("{}", to_upper_snake_case(token));
44         quote! {
45             #[derive(Debug, Clone, PartialEq, Eq, Hash)]
46             pub struct #name {
47                 pub(crate) syntax: SyntaxToken,
48             }
49             impl std::fmt::Display for #name {
50                 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51                     std::fmt::Display::fmt(&self.syntax, f)
52                 }
53             }
54             impl AstToken for #name {
55                 fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
56                 fn cast(syntax: SyntaxToken) -> Option<Self> {
57                     if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
58                 }
59                 fn syntax(&self) -> &SyntaxToken { &self.syntax }
60             }
61         }
62     });
63
64     let pretty = reformat(quote! {
65         use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
66         #(#tokens)*
67     })?
68     .replace("#[derive", "\n#[derive");
69     Ok(pretty)
70 }
71
72 fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
73     let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
74         .nodes
75         .iter()
76         .map(|node| {
77             let name = format_ident!("{}", node.name);
78             let kind = format_ident!("{}", to_upper_snake_case(&node.name));
79             let traits = node.traits.iter().map(|trait_name| {
80                 let trait_name = format_ident!("{}", trait_name);
81                 quote!(impl ast::#trait_name for #name {})
82             });
83
84             let methods = node.fields.iter().map(|field| {
85                 let method_name = field.method_name();
86                 let ty = field.ty();
87
88                 if field.is_many() {
89                     quote! {
90                         pub fn #method_name(&self) -> AstChildren<#ty> {
91                             support::children(&self.syntax)
92                         }
93                     }
94                 } else {
95                     if let Some(token_kind) = field.token_kind() {
96                         quote! {
97                             pub fn #method_name(&self) -> Option<#ty> {
98                                 support::token(&self.syntax, #token_kind)
99                             }
100                         }
101                     } else {
102                         quote! {
103                             pub fn #method_name(&self) -> Option<#ty> {
104                                 support::child(&self.syntax)
105                             }
106                         }
107                     }
108                 }
109             });
110             (
111                 quote! {
112                     #[pretty_doc_comment_placeholder_workaround]
113                     #[derive(Debug, Clone, PartialEq, Eq, Hash)]
114                     pub struct #name {
115                         pub(crate) syntax: SyntaxNode,
116                     }
117
118                     #(#traits)*
119
120                     impl #name {
121                         #(#methods)*
122                     }
123                 },
124                 quote! {
125                     impl AstNode for #name {
126                         fn can_cast(kind: SyntaxKind) -> bool {
127                             kind == #kind
128                         }
129                         fn cast(syntax: SyntaxNode) -> Option<Self> {
130                             if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
131                         }
132                         fn syntax(&self) -> &SyntaxNode { &self.syntax }
133                     }
134                 },
135             )
136         })
137         .unzip();
138
139     let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
140         .enums
141         .iter()
142         .map(|en| {
143             let variants: Vec<_> = en.variants.iter().map(|var| format_ident!("{}", var)).collect();
144             let name = format_ident!("{}", en.name);
145             let kinds: Vec<_> = variants
146                 .iter()
147                 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
148                 .collect();
149             let traits = en.traits.iter().map(|trait_name| {
150                 let trait_name = format_ident!("{}", trait_name);
151                 quote!(impl ast::#trait_name for #name {})
152             });
153
154             let ast_node = if en.name == "Stmt" {
155                 quote! {}
156             } else {
157                 quote! {
158                     impl AstNode for #name {
159                         fn can_cast(kind: SyntaxKind) -> bool {
160                             match kind {
161                                 #(#kinds)|* => true,
162                                 _ => false,
163                             }
164                         }
165                         fn cast(syntax: SyntaxNode) -> Option<Self> {
166                             let res = match syntax.kind() {
167                                 #(
168                                 #kinds => #name::#variants(#variants { syntax }),
169                                 )*
170                                 _ => return None,
171                             };
172                             Some(res)
173                         }
174                         fn syntax(&self) -> &SyntaxNode {
175                             match self {
176                                 #(
177                                 #name::#variants(it) => &it.syntax,
178                                 )*
179                             }
180                         }
181                     }
182                 }
183             };
184
185             (
186                 quote! {
187                     #[pretty_doc_comment_placeholder_workaround]
188                     #[derive(Debug, Clone, PartialEq, Eq, Hash)]
189                     pub enum #name {
190                         #(#variants(#variants),)*
191                     }
192
193                     #(#traits)*
194                 },
195                 quote! {
196                     #(
197                         impl From<#variants> for #name {
198                             fn from(node: #variants) -> #name {
199                                 #name::#variants(node)
200                             }
201                         }
202                     )*
203                     #ast_node
204                 },
205             )
206         })
207         .unzip();
208
209     let enum_names = grammar.enums.iter().map(|it| &it.name);
210     let node_names = grammar.nodes.iter().map(|it| &it.name);
211
212     let display_impls =
213         enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
214             quote! {
215                 impl std::fmt::Display for #name {
216                     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217                         std::fmt::Display::fmt(self.syntax(), f)
218                     }
219                 }
220             }
221         });
222
223     let defined_nodes: HashSet<_> = node_names.collect();
224
225     for node in kinds
226         .nodes
227         .iter()
228         .map(|kind| to_pascal_case(kind))
229         .filter(|name| !defined_nodes.iter().any(|&it| it == name))
230     {
231         drop(node)
232         // TODO: restore this
233         // eprintln!("Warning: node {} not defined in ast source", node);
234     }
235
236     let ast = quote! {
237         use crate::{
238             SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
239             ast::{self, AstNode, AstChildren, support},
240             T,
241         };
242
243         #(#node_defs)*
244         #(#enum_defs)*
245         #(#node_boilerplate_impls)*
246         #(#enum_boilerplate_impls)*
247         #(#display_impls)*
248     };
249
250     let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])");
251
252     let mut res = String::with_capacity(ast.len() * 2);
253
254     let mut docs =
255         grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));
256
257     for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") {
258         res.push_str(chunk);
259         if let Some(doc) = docs.next() {
260             write_doc_comment(&doc, &mut res);
261         }
262     }
263
264     let pretty = reformat(res)?;
265     Ok(pretty)
266 }
267
268 fn write_doc_comment(contents: &[String], dest: &mut String) {
269     for line in contents {
270         writeln!(dest, "///{}", line).unwrap();
271     }
272 }
273
274 fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> {
275     let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
276         .punct
277         .iter()
278         .filter(|(token, _name)| token.len() == 1)
279         .map(|(token, name)| (token.chars().next().unwrap(), format_ident!("{}", name)))
280         .unzip();
281
282     let punctuation_values = grammar.punct.iter().map(|(token, _name)| {
283         if "{}[]()".contains(token) {
284             let c = token.chars().next().unwrap();
285             quote! { #c }
286         } else {
287             let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));
288             quote! { #(#cs)* }
289         }
290     });
291     let punctuation =
292         grammar.punct.iter().map(|(_token, name)| format_ident!("{}", name)).collect::<Vec<_>>();
293
294     let full_keywords_values = &grammar.keywords;
295     let full_keywords =
296         full_keywords_values.iter().map(|kw| format_ident!("{}_KW", to_upper_snake_case(&kw)));
297
298     let all_keywords_values =
299         grammar.keywords.iter().chain(grammar.contextual_keywords.iter()).collect::<Vec<_>>();
300     let all_keywords_idents = all_keywords_values.iter().map(|kw| format_ident!("{}", kw));
301     let all_keywords = all_keywords_values
302         .iter()
303         .map(|name| format_ident!("{}_KW", to_upper_snake_case(&name)))
304         .collect::<Vec<_>>();
305
306     let literals =
307         grammar.literals.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
308
309     let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
310
311     let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
312
313     let ast = quote! {
314         #![allow(bad_style, missing_docs, unreachable_pub)]
315         /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
316         #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
317         #[repr(u16)]
318         pub enum SyntaxKind {
319             // Technical SyntaxKinds: they appear temporally during parsing,
320             // but never end up in the final tree
321             #[doc(hidden)]
322             TOMBSTONE,
323             #[doc(hidden)]
324             EOF,
325             #(#punctuation,)*
326             #(#all_keywords,)*
327             #(#literals,)*
328             #(#tokens,)*
329             #(#nodes,)*
330
331             // Technical kind so that we can cast from u16 safely
332             #[doc(hidden)]
333             __LAST,
334         }
335         use self::SyntaxKind::*;
336
337         impl SyntaxKind {
338             pub fn is_keyword(self) -> bool {
339                 match self {
340                     #(#all_keywords)|* => true,
341                     _ => false,
342                 }
343             }
344
345             pub fn is_punct(self) -> bool {
346                 match self {
347                     #(#punctuation)|* => true,
348                     _ => false,
349                 }
350             }
351
352             pub fn is_literal(self) -> bool {
353                 match self {
354                     #(#literals)|* => true,
355                     _ => false,
356                 }
357             }
358
359             pub fn from_keyword(ident: &str) -> Option<SyntaxKind> {
360                 let kw = match ident {
361                     #(#full_keywords_values => #full_keywords,)*
362                     _ => return None,
363                 };
364                 Some(kw)
365             }
366
367             pub fn from_char(c: char) -> Option<SyntaxKind> {
368                 let tok = match c {
369                     #(#single_byte_tokens_values => #single_byte_tokens,)*
370                     _ => return None,
371                 };
372                 Some(tok)
373             }
374         }
375
376         #[macro_export]
377         macro_rules! T {
378             #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
379             #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)*
380             [lifetime] => { $crate::SyntaxKind::LIFETIME };
381             [ident] => { $crate::SyntaxKind::IDENT };
382             [shebang] => { $crate::SyntaxKind::SHEBANG };
383         }
384     };
385
386     reformat(ast)
387 }
388
389 fn to_upper_snake_case(s: &str) -> String {
390     let mut buf = String::with_capacity(s.len());
391     let mut prev = false;
392     for c in s.chars() {
393         if c.is_ascii_uppercase() && prev {
394             buf.push('_')
395         }
396         prev = true;
397
398         buf.push(c.to_ascii_uppercase());
399     }
400     buf
401 }
402
403 fn to_lower_snake_case(s: &str) -> String {
404     let mut buf = String::with_capacity(s.len());
405     let mut prev = false;
406     for c in s.chars() {
407         if c.is_ascii_uppercase() && prev {
408             buf.push('_')
409         }
410         prev = true;
411
412         buf.push(c.to_ascii_lowercase());
413     }
414     buf
415 }
416
417 fn to_pascal_case(s: &str) -> String {
418     let mut buf = String::with_capacity(s.len());
419     let mut prev_is_underscore = true;
420     for c in s.chars() {
421         if c == '_' {
422             prev_is_underscore = true;
423         } else if prev_is_underscore {
424             buf.push(c.to_ascii_uppercase());
425             prev_is_underscore = false;
426         } else {
427             buf.push(c.to_ascii_lowercase());
428         }
429     }
430     buf
431 }
432
433 fn pluralize(s: &str) -> String {
434     format!("{}s", s)
435 }
436
437 impl Field {
438     fn is_many(&self) -> bool {
439         matches!(self, Field::Node { cardinality: Cardinality::Many, .. })
440     }
441     fn token_kind(&self) -> Option<proc_macro2::TokenStream> {
442         match self {
443             Field::Token(token) => {
444                 let token: proc_macro2::TokenStream = token.parse().unwrap();
445                 Some(quote! { T![#token] })
446             }
447             _ => None,
448         }
449     }
450     fn method_name(&self) -> proc_macro2::Ident {
451         match self {
452             Field::Token(name) => {
453                 let name = match name.as_str() {
454                     ";" => "semicolon",
455                     "->" => "thin_arrow",
456                     "'{'" => "l_curly",
457                     "'}'" => "r_curly",
458                     "'('" => "l_paren",
459                     "')'" => "r_paren",
460                     "'['" => "l_brack",
461                     "']'" => "r_brack",
462                     "<" => "l_angle",
463                     ">" => "r_angle",
464                     "=" => "eq",
465                     "!" => "excl",
466                     "*" => "star",
467                     "&" => "amp",
468                     "_" => "underscore",
469                     "." => "dot",
470                     ".." => "dotdot",
471                     "..." => "dotdotdot",
472                     "..=" => "dotdoteq",
473                     "=>" => "fat_arrow",
474                     "@" => "at",
475                     ":" => "colon",
476                     "::" => "coloncolon",
477                     "#" => "pound",
478                     "?" => "question_mark",
479                     "," => "comma",
480                     _ => name,
481                 };
482                 format_ident!("{}_token", name)
483             }
484             Field::Node { name, .. } => {
485                 if name == "type" {
486                     format_ident!("ty")
487                 } else {
488                     format_ident!("{}", name)
489                 }
490             }
491         }
492     }
493     fn ty(&self) -> proc_macro2::Ident {
494         match self {
495             Field::Token(_) => format_ident!("SyntaxToken"),
496             Field::Node { ty, .. } => format_ident!("{}", ty),
497         }
498     }
499 }
500
501 fn lower(grammar: &Grammar) -> AstSrc {
502     let mut res = AstSrc::default();
503     res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()];
504
505     let nodes = grammar.iter().collect::<Vec<_>>();
506
507     for &node in &nodes {
508         let name = grammar[node].name.clone();
509         let rule = &grammar[node].rule;
510         match lower_enum(grammar, rule) {
511             Some(variants) => {
512                 let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants };
513                 res.enums.push(enum_src);
514             }
515             None => {
516                 let mut fields = Vec::new();
517                 lower_rule(&mut fields, grammar, None, rule);
518                 res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields });
519             }
520         }
521     }
522
523     deduplicate_fields(&mut res);
524     extract_enums(&mut res);
525     extract_struct_traits(&mut res);
526     extract_enum_traits(&mut res);
527     res
528 }
529
530 fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
531     let alternatives = match rule {
532         Rule::Alt(it) => it,
533         _ => return None,
534     };
535     let mut variants = Vec::new();
536     for alternative in alternatives {
537         match alternative {
538             Rule::Node(it) => variants.push(grammar[*it].name.clone()),
539             Rule::Token(it) if grammar[*it].name == ";" => (),
540             _ => return None,
541         }
542     }
543     Some(variants)
544 }
545
546 fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, rule: &Rule) {
547     if lower_comma_list(acc, grammar, label, rule) {
548         return;
549     }
550
551     match rule {
552         Rule::Node(node) => {
553             let ty = grammar[*node].name.clone();
554             let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty));
555             let field = Field::Node { name, ty, cardinality: Cardinality::Optional };
556             acc.push(field);
557         }
558         Rule::Token(token) => {
559             assert!(label.is_none());
560             let mut name = grammar[*token].name.clone();
561             if name != "int_number" && name != "string" {
562                 if "[]{}()".contains(&name) {
563                     name = format!("'{}'", name);
564                 }
565                 let field = Field::Token(name);
566                 acc.push(field);
567             }
568         }
569         Rule::Rep(inner) => {
570             if let Rule::Node(node) = &**inner {
571                 let ty = grammar[*node].name.clone();
572                 let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
573                 let field = Field::Node { name, ty, cardinality: Cardinality::Many };
574                 acc.push(field);
575                 return;
576             }
577             todo!("{:?}", rule)
578         }
579         Rule::Labeled { label: l, rule } => {
580             assert!(label.is_none());
581             let manually_implemented = matches!(
582                 l.as_str(),
583                 "lhs"
584                     | "rhs"
585                     | "then_branch"
586                     | "else_branch"
587                     | "start"
588                     | "end"
589                     | "op"
590                     | "index"
591                     | "base"
592                     | "value"
593                     | "trait"
594                     | "self_ty"
595             );
596             if manually_implemented {
597                 return;
598             }
599             lower_rule(acc, grammar, Some(l), rule);
600         }
601         Rule::Seq(rules) | Rule::Alt(rules) => {
602             for rule in rules {
603                 lower_rule(acc, grammar, label, rule)
604             }
605         }
606         Rule::Opt(rule) => lower_rule(acc, grammar, label, rule),
607     }
608 }
609
610 // (T (',' T)* ','?)
611 fn lower_comma_list(
612     acc: &mut Vec<Field>,
613     grammar: &Grammar,
614     label: Option<&String>,
615     rule: &Rule,
616 ) -> bool {
617     let rule = match rule {
618         Rule::Seq(it) => it,
619         _ => return false,
620     };
621     let (node, repeat, trailing_comma) = match rule.as_slice() {
622         [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => {
623             (node, repeat, trailing_comma)
624         }
625         _ => return false,
626     };
627     let repeat = match &**repeat {
628         Rule::Seq(it) => it,
629         _ => return false,
630     };
631     match repeat.as_slice() {
632         [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (),
633         _ => return false,
634     }
635     let ty = grammar[*node].name.clone();
636     let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
637     let field = Field::Node { name, ty, cardinality: Cardinality::Many };
638     acc.push(field);
639     true
640 }
641
642 fn deduplicate_fields(ast: &mut AstSrc) {
643     for node in &mut ast.nodes {
644         let mut i = 0;
645         'outer: while i < node.fields.len() {
646             for j in 0..i {
647                 let f1 = &node.fields[i];
648                 let f2 = &node.fields[j];
649                 if f1 == f2 {
650                     node.fields.remove(i);
651                     continue 'outer;
652                 }
653             }
654             i += 1;
655         }
656     }
657 }
658
659 fn extract_enums(ast: &mut AstSrc) {
660     for node in &mut ast.nodes {
661         for enm in &ast.enums {
662             let mut to_remove = Vec::new();
663             for (i, field) in node.fields.iter().enumerate() {
664                 let ty = field.ty().to_string();
665                 if enm.variants.iter().any(|it| it == &ty) {
666                     to_remove.push(i);
667                 }
668             }
669             if to_remove.len() == enm.variants.len() {
670                 node.remove_field(to_remove);
671                 let ty = enm.name.clone();
672                 let name = to_lower_snake_case(&ty);
673                 node.fields.push(Field::Node { name, ty, cardinality: Cardinality::Optional });
674             }
675         }
676     }
677 }
678
679 fn extract_struct_traits(ast: &mut AstSrc) {
680     let traits: &[(&str, &[&str])] = &[
681         ("AttrsOwner", &["attrs"]),
682         ("NameOwner", &["name"]),
683         ("VisibilityOwner", &["visibility"]),
684         ("GenericParamsOwner", &["generic_param_list", "where_clause"]),
685         ("TypeBoundsOwner", &["type_bound_list", "colon_token"]),
686         ("ModuleItemOwner", &["items"]),
687         ("LoopBodyOwner", &["label", "loop_body"]),
688         ("ArgListOwner", &["arg_list"]),
689     ];
690
691     for node in &mut ast.nodes {
692         for (name, methods) in traits {
693             extract_struct_trait(node, name, methods);
694         }
695     }
696 }
697
698 fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) {
699     let mut to_remove = Vec::new();
700     for (i, field) in node.fields.iter().enumerate() {
701         let method_name = field.method_name().to_string();
702         if methods.iter().any(|&it| it == &method_name) {
703             to_remove.push(i);
704         }
705     }
706     if to_remove.len() == methods.len() {
707         node.traits.push(trait_name.to_string());
708         node.remove_field(to_remove);
709     }
710 }
711
712 fn extract_enum_traits(ast: &mut AstSrc) {
713     for enm in &mut ast.enums {
714         if enm.name == "Stmt" {
715             continue;
716         }
717         let nodes = &ast.nodes;
718         let mut variant_traits = enm
719             .variants
720             .iter()
721             .map(|var| nodes.iter().find(|it| &it.name == var).unwrap())
722             .map(|node| node.traits.iter().cloned().collect::<BTreeSet<_>>());
723
724         let mut enum_traits = match variant_traits.next() {
725             Some(it) => it,
726             None => continue,
727         };
728         for traits in variant_traits {
729             enum_traits = enum_traits.intersection(&traits).cloned().collect();
730         }
731         enm.traits = enum_traits.into_iter().collect();
732     }
733 }
734
735 impl AstNodeSrc {
736     fn remove_field(&mut self, to_remove: Vec<usize>) {
737         to_remove.into_iter().rev().for_each(|idx| {
738             self.fields.remove(idx);
739         });
740     }
741 }