1 use crate::cfg;
2 use inflections::Inflect;
3 use proc_macro2::{Ident, Span, TokenStream};
4 use syn_codegen::{Data, Definitions, Features, Node};
5
6 pub const TERMINAL_TYPES: &[&str] = &["Span", "Ident"];
7
under_name(name: &str) -> Ident8 pub fn under_name(name: &str) -> Ident {
9 Ident::new(&name.to_snake_case(), Span::call_site())
10 }
11
traverse( defs: &Definitions, node: fn(&mut TokenStream, &mut TokenStream, &Node, &Definitions), ) -> (TokenStream, TokenStream)12 pub fn traverse(
13 defs: &Definitions,
14 node: fn(&mut TokenStream, &mut TokenStream, &Node, &Definitions),
15 ) -> (TokenStream, TokenStream) {
16 let mut types = defs.types.clone();
17 for &terminal in TERMINAL_TYPES {
18 types.push(Node {
19 ident: terminal.to_owned(),
20 features: Features::default(),
21 data: Data::Private,
22 exhaustive: true,
23 });
24 }
25 types.sort_by(|a, b| a.ident.cmp(&b.ident));
26
27 let mut traits = TokenStream::new();
28 let mut impls = TokenStream::new();
29 for s in types {
30 let features = cfg::features(&s.features, None);
31 traits.extend(features.clone());
32 impls.extend(features);
33 node(&mut traits, &mut impls, &s, defs);
34 }
35
36 (traits, impls)
37 }
38