1fad3a1d3Sopenharmony_ciuse crate::operand::{Borrowed, Operand, Owned}; 2fad3a1d3Sopenharmony_ciuse crate::{file, lookup}; 3fad3a1d3Sopenharmony_ciuse anyhow::Result; 4fad3a1d3Sopenharmony_ciuse proc_macro2::{Ident, Span, TokenStream}; 5fad3a1d3Sopenharmony_ciuse quote::{format_ident, quote}; 6fad3a1d3Sopenharmony_ciuse syn::Index; 7fad3a1d3Sopenharmony_ciuse syn_codegen::{Data, Definitions, Node, Type}; 8fad3a1d3Sopenharmony_ci 9fad3a1d3Sopenharmony_ciconst TESTS_DEBUG_SRC: &str = "tests/debug/gen.rs"; 10fad3a1d3Sopenharmony_ci 11fad3a1d3Sopenharmony_cifn rust_type(ty: &Type) -> TokenStream { 12fad3a1d3Sopenharmony_ci match ty { 13fad3a1d3Sopenharmony_ci Type::Syn(ty) => { 14fad3a1d3Sopenharmony_ci let ident = Ident::new(ty, Span::call_site()); 15fad3a1d3Sopenharmony_ci quote!(syn::#ident) 16fad3a1d3Sopenharmony_ci } 17fad3a1d3Sopenharmony_ci Type::Std(ty) => { 18fad3a1d3Sopenharmony_ci let ident = Ident::new(ty, Span::call_site()); 19fad3a1d3Sopenharmony_ci quote!(#ident) 20fad3a1d3Sopenharmony_ci } 21fad3a1d3Sopenharmony_ci Type::Ext(ty) => { 22fad3a1d3Sopenharmony_ci let ident = Ident::new(ty, Span::call_site()); 23fad3a1d3Sopenharmony_ci quote!(proc_macro2::#ident) 24fad3a1d3Sopenharmony_ci } 25fad3a1d3Sopenharmony_ci Type::Token(ty) | Type::Group(ty) => { 26fad3a1d3Sopenharmony_ci let ident = Ident::new(ty, Span::call_site()); 27fad3a1d3Sopenharmony_ci quote!(syn::token::#ident) 28fad3a1d3Sopenharmony_ci } 29fad3a1d3Sopenharmony_ci Type::Punctuated(ty) => { 30fad3a1d3Sopenharmony_ci let element = rust_type(&ty.element); 31fad3a1d3Sopenharmony_ci let punct = Ident::new(&ty.punct, Span::call_site()); 32fad3a1d3Sopenharmony_ci quote!(syn::punctuated::Punctuated<#element, #punct>) 33fad3a1d3Sopenharmony_ci } 34fad3a1d3Sopenharmony_ci Type::Option(ty) => { 35fad3a1d3Sopenharmony_ci let inner = rust_type(ty); 36fad3a1d3Sopenharmony_ci quote!(Option<#inner>) 37fad3a1d3Sopenharmony_ci } 38fad3a1d3Sopenharmony_ci Type::Box(ty) => { 39fad3a1d3Sopenharmony_ci let inner = rust_type(ty); 40fad3a1d3Sopenharmony_ci quote!(Box<#inner>) 41fad3a1d3Sopenharmony_ci } 42fad3a1d3Sopenharmony_ci Type::Vec(ty) => { 43fad3a1d3Sopenharmony_ci let inner = rust_type(ty); 44fad3a1d3Sopenharmony_ci quote!(Vec<#inner>) 45fad3a1d3Sopenharmony_ci } 46fad3a1d3Sopenharmony_ci Type::Tuple(ty) => { 47fad3a1d3Sopenharmony_ci let inner = ty.iter().map(rust_type); 48fad3a1d3Sopenharmony_ci quote!((#(#inner,)*)) 49fad3a1d3Sopenharmony_ci } 50fad3a1d3Sopenharmony_ci } 51fad3a1d3Sopenharmony_ci} 52fad3a1d3Sopenharmony_ci 53fad3a1d3Sopenharmony_cifn is_printable(ty: &Type) -> bool { 54fad3a1d3Sopenharmony_ci match ty { 55fad3a1d3Sopenharmony_ci Type::Ext(name) => name != "Span", 56fad3a1d3Sopenharmony_ci Type::Box(ty) => is_printable(ty), 57fad3a1d3Sopenharmony_ci Type::Tuple(ty) => ty.iter().any(is_printable), 58fad3a1d3Sopenharmony_ci Type::Token(_) | Type::Group(_) => false, 59fad3a1d3Sopenharmony_ci Type::Syn(_) | Type::Std(_) | Type::Punctuated(_) | Type::Option(_) | Type::Vec(_) => true, 60fad3a1d3Sopenharmony_ci } 61fad3a1d3Sopenharmony_ci} 62fad3a1d3Sopenharmony_ci 63fad3a1d3Sopenharmony_cifn format_field(val: &Operand, ty: &Type) -> Option<TokenStream> { 64fad3a1d3Sopenharmony_ci if !is_printable(ty) { 65fad3a1d3Sopenharmony_ci return None; 66fad3a1d3Sopenharmony_ci } 67fad3a1d3Sopenharmony_ci let format = match ty { 68fad3a1d3Sopenharmony_ci Type::Option(ty) => { 69fad3a1d3Sopenharmony_ci if let Some(format) = format_field(&Borrowed(quote!(_val)), ty) { 70fad3a1d3Sopenharmony_ci let ty = rust_type(ty); 71fad3a1d3Sopenharmony_ci let val = val.ref_tokens(); 72fad3a1d3Sopenharmony_ci quote!({ 73fad3a1d3Sopenharmony_ci #[derive(RefCast)] 74fad3a1d3Sopenharmony_ci #[repr(transparent)] 75fad3a1d3Sopenharmony_ci struct Print(Option<#ty>); 76fad3a1d3Sopenharmony_ci impl Debug for Print { 77fad3a1d3Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 78fad3a1d3Sopenharmony_ci match &self.0 { 79fad3a1d3Sopenharmony_ci Some(_val) => { 80fad3a1d3Sopenharmony_ci formatter.write_str("Some(")?; 81fad3a1d3Sopenharmony_ci Debug::fmt(#format, formatter)?; 82fad3a1d3Sopenharmony_ci formatter.write_str(")")?; 83fad3a1d3Sopenharmony_ci Ok(()) 84fad3a1d3Sopenharmony_ci } 85fad3a1d3Sopenharmony_ci None => formatter.write_str("None"), 86fad3a1d3Sopenharmony_ci } 87fad3a1d3Sopenharmony_ci } 88fad3a1d3Sopenharmony_ci } 89fad3a1d3Sopenharmony_ci Print::ref_cast(#val) 90fad3a1d3Sopenharmony_ci }) 91fad3a1d3Sopenharmony_ci } else { 92fad3a1d3Sopenharmony_ci let val = val.tokens(); 93fad3a1d3Sopenharmony_ci quote! { 94fad3a1d3Sopenharmony_ci &super::Option { present: #val.is_some() } 95fad3a1d3Sopenharmony_ci } 96fad3a1d3Sopenharmony_ci } 97fad3a1d3Sopenharmony_ci } 98fad3a1d3Sopenharmony_ci Type::Tuple(ty) => { 99fad3a1d3Sopenharmony_ci let printable: Vec<TokenStream> = ty 100fad3a1d3Sopenharmony_ci .iter() 101fad3a1d3Sopenharmony_ci .enumerate() 102fad3a1d3Sopenharmony_ci .filter_map(|(i, ty)| { 103fad3a1d3Sopenharmony_ci let index = Index::from(i); 104fad3a1d3Sopenharmony_ci let val = val.tokens(); 105fad3a1d3Sopenharmony_ci let inner = Owned(quote!(#val.#index)); 106fad3a1d3Sopenharmony_ci format_field(&inner, ty) 107fad3a1d3Sopenharmony_ci }) 108fad3a1d3Sopenharmony_ci .collect(); 109fad3a1d3Sopenharmony_ci if printable.len() == 1 { 110fad3a1d3Sopenharmony_ci printable.into_iter().next().unwrap() 111fad3a1d3Sopenharmony_ci } else { 112fad3a1d3Sopenharmony_ci quote! { 113fad3a1d3Sopenharmony_ci &(#(#printable),*) 114fad3a1d3Sopenharmony_ci } 115fad3a1d3Sopenharmony_ci } 116fad3a1d3Sopenharmony_ci } 117fad3a1d3Sopenharmony_ci _ => { 118fad3a1d3Sopenharmony_ci let val = val.ref_tokens(); 119fad3a1d3Sopenharmony_ci quote! { Lite(#val) } 120fad3a1d3Sopenharmony_ci } 121fad3a1d3Sopenharmony_ci }; 122fad3a1d3Sopenharmony_ci Some(format) 123fad3a1d3Sopenharmony_ci} 124fad3a1d3Sopenharmony_ci 125fad3a1d3Sopenharmony_cifn syntax_tree_enum<'a>(outer: &str, inner: &str, fields: &'a [Type]) -> Option<&'a str> { 126fad3a1d3Sopenharmony_ci if fields.len() != 1 { 127fad3a1d3Sopenharmony_ci return None; 128fad3a1d3Sopenharmony_ci } 129fad3a1d3Sopenharmony_ci const WHITELIST: &[(&str, &str)] = &[ 130fad3a1d3Sopenharmony_ci ("Meta", "Path"), 131fad3a1d3Sopenharmony_ci ("PathArguments", "AngleBracketed"), 132fad3a1d3Sopenharmony_ci ("PathArguments", "Parenthesized"), 133fad3a1d3Sopenharmony_ci ("Stmt", "Local"), 134fad3a1d3Sopenharmony_ci ("TypeParamBound", "Lifetime"), 135fad3a1d3Sopenharmony_ci ("Visibility", "Public"), 136fad3a1d3Sopenharmony_ci ("Visibility", "Restricted"), 137fad3a1d3Sopenharmony_ci ]; 138fad3a1d3Sopenharmony_ci match &fields[0] { 139fad3a1d3Sopenharmony_ci Type::Syn(ty) if WHITELIST.contains(&(outer, inner)) || outer.to_owned() + inner == *ty => { 140fad3a1d3Sopenharmony_ci Some(ty) 141fad3a1d3Sopenharmony_ci } 142fad3a1d3Sopenharmony_ci _ => None, 143fad3a1d3Sopenharmony_ci } 144fad3a1d3Sopenharmony_ci} 145fad3a1d3Sopenharmony_ci 146fad3a1d3Sopenharmony_cifn expand_impl_body(defs: &Definitions, node: &Node, name: &str, val: &Operand) -> TokenStream { 147fad3a1d3Sopenharmony_ci let ident = Ident::new(&node.ident, Span::call_site()); 148fad3a1d3Sopenharmony_ci 149fad3a1d3Sopenharmony_ci match &node.data { 150fad3a1d3Sopenharmony_ci Data::Enum(variants) if variants.is_empty() => quote!(unreachable!()), 151fad3a1d3Sopenharmony_ci Data::Enum(variants) => { 152fad3a1d3Sopenharmony_ci let arms = variants.iter().map(|(v, fields)| { 153fad3a1d3Sopenharmony_ci let path = format!("{}::{}", name, v); 154fad3a1d3Sopenharmony_ci let variant = Ident::new(v, Span::call_site()); 155fad3a1d3Sopenharmony_ci if fields.is_empty() { 156fad3a1d3Sopenharmony_ci quote! { 157fad3a1d3Sopenharmony_ci syn::#ident::#variant => formatter.write_str(#path), 158fad3a1d3Sopenharmony_ci } 159fad3a1d3Sopenharmony_ci } else if let Some(inner) = syntax_tree_enum(name, v, fields) { 160fad3a1d3Sopenharmony_ci let format = expand_impl_body( 161fad3a1d3Sopenharmony_ci defs, 162fad3a1d3Sopenharmony_ci lookup::node(defs, inner), 163fad3a1d3Sopenharmony_ci &path, 164fad3a1d3Sopenharmony_ci &Borrowed(quote!(_val)), 165fad3a1d3Sopenharmony_ci ); 166fad3a1d3Sopenharmony_ci quote! { 167fad3a1d3Sopenharmony_ci syn::#ident::#variant(_val) => { 168fad3a1d3Sopenharmony_ci #format 169fad3a1d3Sopenharmony_ci } 170fad3a1d3Sopenharmony_ci } 171fad3a1d3Sopenharmony_ci } else if fields.len() == 1 { 172fad3a1d3Sopenharmony_ci let val = quote!(_val); 173fad3a1d3Sopenharmony_ci let format = if variant == "Verbatim" { 174fad3a1d3Sopenharmony_ci Some(quote! { 175fad3a1d3Sopenharmony_ci formatter.write_str("(`")?; 176fad3a1d3Sopenharmony_ci Display::fmt(#val, formatter)?; 177fad3a1d3Sopenharmony_ci formatter.write_str("`)")?; 178fad3a1d3Sopenharmony_ci }) 179fad3a1d3Sopenharmony_ci } else { 180fad3a1d3Sopenharmony_ci let ty = &fields[0]; 181fad3a1d3Sopenharmony_ci format_field(&Borrowed(val), ty).map(|format| { 182fad3a1d3Sopenharmony_ci quote! { 183fad3a1d3Sopenharmony_ci formatter.write_str("(")?; 184fad3a1d3Sopenharmony_ci Debug::fmt(#format, formatter)?; 185fad3a1d3Sopenharmony_ci formatter.write_str(")")?; 186fad3a1d3Sopenharmony_ci } 187fad3a1d3Sopenharmony_ci }) 188fad3a1d3Sopenharmony_ci }; 189fad3a1d3Sopenharmony_ci quote! { 190fad3a1d3Sopenharmony_ci syn::#ident::#variant(_val) => { 191fad3a1d3Sopenharmony_ci formatter.write_str(#path)?; 192fad3a1d3Sopenharmony_ci #format 193fad3a1d3Sopenharmony_ci Ok(()) 194fad3a1d3Sopenharmony_ci } 195fad3a1d3Sopenharmony_ci } 196fad3a1d3Sopenharmony_ci } else { 197fad3a1d3Sopenharmony_ci let pats = (0..fields.len()).map(|i| format_ident!("_v{}", i)); 198fad3a1d3Sopenharmony_ci let fields = fields.iter().enumerate().filter_map(|(i, ty)| { 199fad3a1d3Sopenharmony_ci let index = format_ident!("_v{}", i); 200fad3a1d3Sopenharmony_ci let val = quote!(#index); 201fad3a1d3Sopenharmony_ci let format = format_field(&Borrowed(val), ty)?; 202fad3a1d3Sopenharmony_ci Some(quote! { 203fad3a1d3Sopenharmony_ci formatter.field(#format); 204fad3a1d3Sopenharmony_ci }) 205fad3a1d3Sopenharmony_ci }); 206fad3a1d3Sopenharmony_ci quote! { 207fad3a1d3Sopenharmony_ci syn::#ident::#variant(#(#pats),*) => { 208fad3a1d3Sopenharmony_ci let mut formatter = formatter.debug_tuple(#path); 209fad3a1d3Sopenharmony_ci #(#fields)* 210fad3a1d3Sopenharmony_ci formatter.finish() 211fad3a1d3Sopenharmony_ci } 212fad3a1d3Sopenharmony_ci } 213fad3a1d3Sopenharmony_ci } 214fad3a1d3Sopenharmony_ci }); 215fad3a1d3Sopenharmony_ci let nonexhaustive = if node.exhaustive { 216fad3a1d3Sopenharmony_ci None 217fad3a1d3Sopenharmony_ci } else { 218fad3a1d3Sopenharmony_ci Some(quote!(_ => unreachable!())) 219fad3a1d3Sopenharmony_ci }; 220fad3a1d3Sopenharmony_ci let val = val.ref_tokens(); 221fad3a1d3Sopenharmony_ci quote! { 222fad3a1d3Sopenharmony_ci match #val { 223fad3a1d3Sopenharmony_ci #(#arms)* 224fad3a1d3Sopenharmony_ci #nonexhaustive 225fad3a1d3Sopenharmony_ci } 226fad3a1d3Sopenharmony_ci } 227fad3a1d3Sopenharmony_ci } 228fad3a1d3Sopenharmony_ci Data::Struct(fields) => { 229fad3a1d3Sopenharmony_ci let fields = fields.iter().filter_map(|(f, ty)| { 230fad3a1d3Sopenharmony_ci let ident = Ident::new(f, Span::call_site()); 231fad3a1d3Sopenharmony_ci if let Type::Option(ty) = ty { 232fad3a1d3Sopenharmony_ci Some(if let Some(format) = format_field(&Owned(quote!(self.0)), ty) { 233fad3a1d3Sopenharmony_ci let val = val.tokens(); 234fad3a1d3Sopenharmony_ci let ty = rust_type(ty); 235fad3a1d3Sopenharmony_ci quote! { 236fad3a1d3Sopenharmony_ci if let Some(val) = &#val.#ident { 237fad3a1d3Sopenharmony_ci #[derive(RefCast)] 238fad3a1d3Sopenharmony_ci #[repr(transparent)] 239fad3a1d3Sopenharmony_ci struct Print(#ty); 240fad3a1d3Sopenharmony_ci impl Debug for Print { 241fad3a1d3Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 242fad3a1d3Sopenharmony_ci formatter.write_str("Some(")?; 243fad3a1d3Sopenharmony_ci Debug::fmt(#format, formatter)?; 244fad3a1d3Sopenharmony_ci formatter.write_str(")")?; 245fad3a1d3Sopenharmony_ci Ok(()) 246fad3a1d3Sopenharmony_ci } 247fad3a1d3Sopenharmony_ci } 248fad3a1d3Sopenharmony_ci formatter.field(#f, Print::ref_cast(val)); 249fad3a1d3Sopenharmony_ci } 250fad3a1d3Sopenharmony_ci } 251fad3a1d3Sopenharmony_ci } else { 252fad3a1d3Sopenharmony_ci let val = val.tokens(); 253fad3a1d3Sopenharmony_ci quote! { 254fad3a1d3Sopenharmony_ci if #val.#ident.is_some() { 255fad3a1d3Sopenharmony_ci formatter.field(#f, &Present); 256fad3a1d3Sopenharmony_ci } 257fad3a1d3Sopenharmony_ci } 258fad3a1d3Sopenharmony_ci }) 259fad3a1d3Sopenharmony_ci } else { 260fad3a1d3Sopenharmony_ci let val = val.tokens(); 261fad3a1d3Sopenharmony_ci let inner = Owned(quote!(#val.#ident)); 262fad3a1d3Sopenharmony_ci let format = format_field(&inner, ty)?; 263fad3a1d3Sopenharmony_ci let mut call = quote! { 264fad3a1d3Sopenharmony_ci formatter.field(#f, #format); 265fad3a1d3Sopenharmony_ci }; 266fad3a1d3Sopenharmony_ci if node.ident == "Block" && f == "stmts" { 267fad3a1d3Sopenharmony_ci // Format regardless of whether is_empty(). 268fad3a1d3Sopenharmony_ci } else if let Type::Vec(_) | Type::Punctuated(_) = ty { 269fad3a1d3Sopenharmony_ci call = quote! { 270fad3a1d3Sopenharmony_ci if !#val.#ident.is_empty() { 271fad3a1d3Sopenharmony_ci #call 272fad3a1d3Sopenharmony_ci } 273fad3a1d3Sopenharmony_ci }; 274fad3a1d3Sopenharmony_ci } else if let Type::Syn(inner) = ty { 275fad3a1d3Sopenharmony_ci for node in &defs.types { 276fad3a1d3Sopenharmony_ci if node.ident == *inner { 277fad3a1d3Sopenharmony_ci if let Data::Enum(variants) = &node.data { 278fad3a1d3Sopenharmony_ci if variants.get("None").map_or(false, Vec::is_empty) { 279fad3a1d3Sopenharmony_ci let ty = rust_type(ty); 280fad3a1d3Sopenharmony_ci call = quote! { 281fad3a1d3Sopenharmony_ci match #val.#ident { 282fad3a1d3Sopenharmony_ci #ty::None => {} 283fad3a1d3Sopenharmony_ci _ => { #call } 284fad3a1d3Sopenharmony_ci } 285fad3a1d3Sopenharmony_ci }; 286fad3a1d3Sopenharmony_ci } 287fad3a1d3Sopenharmony_ci } 288fad3a1d3Sopenharmony_ci break; 289fad3a1d3Sopenharmony_ci } 290fad3a1d3Sopenharmony_ci } 291fad3a1d3Sopenharmony_ci } 292fad3a1d3Sopenharmony_ci Some(call) 293fad3a1d3Sopenharmony_ci } 294fad3a1d3Sopenharmony_ci }); 295fad3a1d3Sopenharmony_ci quote! { 296fad3a1d3Sopenharmony_ci let mut formatter = formatter.debug_struct(#name); 297fad3a1d3Sopenharmony_ci #(#fields)* 298fad3a1d3Sopenharmony_ci formatter.finish() 299fad3a1d3Sopenharmony_ci } 300fad3a1d3Sopenharmony_ci } 301fad3a1d3Sopenharmony_ci Data::Private => { 302fad3a1d3Sopenharmony_ci if node.ident == "LitInt" || node.ident == "LitFloat" { 303fad3a1d3Sopenharmony_ci let val = val.ref_tokens(); 304fad3a1d3Sopenharmony_ci quote! { 305fad3a1d3Sopenharmony_ci write!(formatter, "{}", #val) 306fad3a1d3Sopenharmony_ci } 307fad3a1d3Sopenharmony_ci } else { 308fad3a1d3Sopenharmony_ci let val = val.tokens(); 309fad3a1d3Sopenharmony_ci quote! { 310fad3a1d3Sopenharmony_ci write!(formatter, "{:?}", #val.value()) 311fad3a1d3Sopenharmony_ci } 312fad3a1d3Sopenharmony_ci } 313fad3a1d3Sopenharmony_ci } 314fad3a1d3Sopenharmony_ci } 315fad3a1d3Sopenharmony_ci} 316fad3a1d3Sopenharmony_ci 317fad3a1d3Sopenharmony_cifn expand_impl(defs: &Definitions, node: &Node) -> TokenStream { 318fad3a1d3Sopenharmony_ci let ident = Ident::new(&node.ident, Span::call_site()); 319fad3a1d3Sopenharmony_ci let body = expand_impl_body(defs, node, &node.ident, &Owned(quote!(self.value))); 320fad3a1d3Sopenharmony_ci let formatter = match &node.data { 321fad3a1d3Sopenharmony_ci Data::Enum(variants) if variants.is_empty() => quote!(_formatter), 322fad3a1d3Sopenharmony_ci _ => quote!(formatter), 323fad3a1d3Sopenharmony_ci }; 324fad3a1d3Sopenharmony_ci 325fad3a1d3Sopenharmony_ci quote! { 326fad3a1d3Sopenharmony_ci impl Debug for Lite<syn::#ident> { 327fad3a1d3Sopenharmony_ci fn fmt(&self, #formatter: &mut fmt::Formatter) -> fmt::Result { 328fad3a1d3Sopenharmony_ci #body 329fad3a1d3Sopenharmony_ci } 330fad3a1d3Sopenharmony_ci } 331fad3a1d3Sopenharmony_ci } 332fad3a1d3Sopenharmony_ci} 333fad3a1d3Sopenharmony_ci 334fad3a1d3Sopenharmony_cifn expand_token_impl(name: &str, symbol: &str) -> TokenStream { 335fad3a1d3Sopenharmony_ci let ident = Ident::new(name, Span::call_site()); 336fad3a1d3Sopenharmony_ci let repr = format!("Token![{}]", symbol); 337fad3a1d3Sopenharmony_ci 338fad3a1d3Sopenharmony_ci quote! { 339fad3a1d3Sopenharmony_ci impl Debug for Lite<syn::token::#ident> { 340fad3a1d3Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 341fad3a1d3Sopenharmony_ci formatter.write_str(#repr) 342fad3a1d3Sopenharmony_ci } 343fad3a1d3Sopenharmony_ci } 344fad3a1d3Sopenharmony_ci } 345fad3a1d3Sopenharmony_ci} 346fad3a1d3Sopenharmony_ci 347fad3a1d3Sopenharmony_cipub fn generate(defs: &Definitions) -> Result<()> { 348fad3a1d3Sopenharmony_ci let mut impls = TokenStream::new(); 349fad3a1d3Sopenharmony_ci for node in &defs.types { 350fad3a1d3Sopenharmony_ci impls.extend(expand_impl(defs, node)); 351fad3a1d3Sopenharmony_ci } 352fad3a1d3Sopenharmony_ci for (name, symbol) in &defs.tokens { 353fad3a1d3Sopenharmony_ci impls.extend(expand_token_impl(name, symbol)); 354fad3a1d3Sopenharmony_ci } 355fad3a1d3Sopenharmony_ci 356fad3a1d3Sopenharmony_ci file::write( 357fad3a1d3Sopenharmony_ci TESTS_DEBUG_SRC, 358fad3a1d3Sopenharmony_ci quote! { 359fad3a1d3Sopenharmony_ci // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482 360fad3a1d3Sopenharmony_ci #![allow(repr_transparent_external_private_fields)] 361fad3a1d3Sopenharmony_ci 362fad3a1d3Sopenharmony_ci #![allow(clippy::match_wildcard_for_single_variants)] 363fad3a1d3Sopenharmony_ci 364fad3a1d3Sopenharmony_ci use super::{Lite, Present}; 365fad3a1d3Sopenharmony_ci use ref_cast::RefCast; 366fad3a1d3Sopenharmony_ci use std::fmt::{self, Debug, Display}; 367fad3a1d3Sopenharmony_ci 368fad3a1d3Sopenharmony_ci #impls 369fad3a1d3Sopenharmony_ci }, 370fad3a1d3Sopenharmony_ci )?; 371fad3a1d3Sopenharmony_ci 372fad3a1d3Sopenharmony_ci Ok(()) 373fad3a1d3Sopenharmony_ci} 374