1use crate::cfg; 2use inflections::Inflect; 3use proc_macro2::{Ident, Span, TokenStream}; 4use syn_codegen::{Data, Definitions, Features, Node}; 5 6pub const TERMINAL_TYPES: &[&str] = &["Span", "Ident"]; 7 8pub fn under_name(name: &str) -> Ident { 9 Ident::new(&name.to_snake_case(), Span::call_site()) 10} 11 12pub 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