From 0a72d4312f059b36c2d692eca56cb5c85943f45a Mon Sep 17 00:00:00 2001 From: rowan Date: Wed, 9 Jul 2025 12:47:46 -0400 Subject: [PATCH] aa --- crates/osstr_traits_derive/src/lib.rs | 92 ++++++++++++++++----------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/crates/osstr_traits_derive/src/lib.rs b/crates/osstr_traits_derive/src/lib.rs index 55fb4e5..55254cd 100644 --- a/crates/osstr_traits_derive/src/lib.rs +++ b/crates/osstr_traits_derive/src/lib.rs @@ -2,7 +2,7 @@ mod attr_args; extern crate proc_macro; -use crate::attr_args::{OsDisplayAttribute}; +use crate::attr_args::OsDisplayAttribute; use proc_macro::TokenStream; use quote::{quote, quote_spanned}; use syn::parse::Parse; @@ -36,12 +36,13 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { match parsed_attr { OsDisplayAttribute::Transparent => { + match &variant.fields { Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { quote_spanned! {variant.span() => match self { #name::#variant_name(value) => value.fmt_os(f), - _ => unreachable!(), + _ => unreachable!(), } } } @@ -50,7 +51,7 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { quote_spanned! {variant.span() => match self { #name::#variant_name{#field_ident} => #field_ident.fmt_os(f), - _ => unreachable!(), + _ => unreachable!(), } } } @@ -61,13 +62,15 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } } } - OsDisplayAttribute::FromDisplay => { + OsDisplayAttribute::FromDisplay => { + + match &variant.fields { Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { quote_spanned! {variant.span() => match self { #name::#variant_name(value) => f.write_str(&value.to_string()), - _ => unreachable!(), + _ => unreachable!(), } } } @@ -76,7 +79,7 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { quote_spanned! {variant.span() => match self { #name::#variant_name{#field_ident} => f.write_str(&#field_ident.to_string()), - _ => unreachable!(), + _ => unreachable!(), } } } @@ -88,13 +91,14 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } } OsDisplayAttribute::Format(format_args) => { + let format_str_value = format_args.format_string.value(); let positional_expressions: Vec<&Expr> = format_args.positional_args.iter().collect(); let named_expressions: HashMap = format_args.named_args .into_iter() - .map(|(ident, expr)| (ident.to_string(), expr)) + .map(|(ident, expr)| (ident.to_string(), expr)) .collect(); parse_os_display_format_string( @@ -106,10 +110,12 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } } } else { - let variant_name_str = format!("{variant_name}"); + + let variant_name_str = format!("{}", variant_name); quote! { f.write_str(#variant_name_str)?; } }; + match &variant.fields { Fields::Unit => { quote! { @@ -121,19 +127,24 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { .unnamed .iter() .enumerate() - .map(|(i, _)| Ident::new(&format!("_{i}"), variant.span())) + .map(|(i, _)| Ident::new(&format!("_{}", i), variant.span())) .collect(); - if let Some(attr) = os_display_attr { - if let Ok(OsDisplayAttribute::Transparent) = attr.parse_args_with(OsDisplayAttribute::parse) { - quote! { - #name::#variant_name(value) => { #format_tokens } - } - } else { - quote! { - #name::#variant_name(#(#field_idents),*) => { #format_tokens } - } + + + let should_capture_value = if let Some(attr) = os_display_attr { + if let Ok(parsed) = attr.parse_args_with(OsDisplayAttribute::parse) { + matches!(parsed, OsDisplayAttribute::Transparent | OsDisplayAttribute::FromDisplay) + } else { false } + } else { false }; + + if should_capture_value { + + + quote! { + #name::#variant_name(value) => { #format_tokens } } } else { + quote! { #name::#variant_name(#(#field_idents),*) => { #format_tokens } } @@ -145,18 +156,21 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { .iter() .map(|f| f.ident.as_ref().unwrap().clone()) .collect(); - if let Some(attr) = os_display_attr { - if let Ok(OsDisplayAttribute::Transparent) = attr.parse_args_with(OsDisplayAttribute::parse) { - let field_ident = fields.named.first().unwrap().ident.as_ref().unwrap(); - quote! { - #name::#variant_name{#field_ident} => { #format_tokens } - } - } else { - quote! { - #name::#variant_name{#(#field_idents),*} => { #format_tokens } - } + + let should_capture_value = if let Some(attr) = os_display_attr { + if let Ok(parsed) = attr.parse_args_with(OsDisplayAttribute::parse) { + matches!(parsed, OsDisplayAttribute::Transparent | OsDisplayAttribute::FromDisplay) + } else { false } + } else { false }; + + if should_capture_value { + + let field_ident = fields.named.first().unwrap().ident.as_ref().unwrap(); + quote! { + #name::#variant_name{#field_ident} => { #format_tokens } } } else { + quote! { #name::#variant_name{#(#field_idents),*} => { #format_tokens } } @@ -190,6 +204,7 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { match parsed_attr { OsDisplayAttribute::Transparent => { + match &data_struct.fields { Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { quote! { @@ -217,16 +232,20 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } } } - OsDisplayAttribute::FromDisplay => { + OsDisplayAttribute::FromDisplay => { + + quote! { - impl #impl_generics my_os_traits::OsDisplay for #name #ty_generics #where_clause { - fn fmt_os(&self, f: &mut my_os_traits::OsStringFormatter) -> std::fmt::Result { + impl #impl_generics osstr_traits::OsDisplay for #name #ty_generics #where_clause { + fn fmt_os(&self, f: &mut osstr_traits::OsStringFormatter) -> std::fmt::Result { + f.write_str(&self.to_string()) } } } } OsDisplayAttribute::Format(format_args) => { + let format_str_value = format_args.format_string.value(); let positional_expressions: Vec<&Expr> = format_args.positional_args.iter().collect(); let named_expressions: HashMap = format_args.named_args @@ -249,7 +268,7 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } }, Fields::Unnamed(fields) => { - let idents: Vec = fields.unnamed.iter().enumerate().map(|(i, _)| Ident::new(&format!("_{i}"), name.span())).collect(); + let idents: Vec = fields.unnamed.iter().enumerate().map(|(i, _)| Ident::new(&format!("_{}", i), name.span())).collect(); quote! { let Self(#(#idents),*) = self; } @@ -269,8 +288,9 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { } } } else { + quote_spanned! {name.span() => - compile_error!("OsDisplay derive macro is not yet implemented for structs without #[os_display] attribute. Consider adding #[os_display(transparent)] for newtypes or specifying a format string using #[os_display(\"...\")] syntax."); + compile_error!("OsDisplay derive macro is not yet implemented for structs without an #[os_display] attribute. Consider adding #[os_display(transparent)], #[os_display(from_display)], or specifying a format string using #[os_display(\"...\")] syntax."); } } } @@ -284,6 +304,7 @@ pub fn os_display_derive(input: TokenStream) -> TokenStream { os_display_impl.into() } + fn parse_os_display_format_string( format_str: &str, positional_expressions: &[&syn::Expr], @@ -308,8 +329,7 @@ fn parse_os_display_format_string( } let mut placeholder_content = String::new(); - - for p in &mut chars { + while let Some(p) = chars.next() { if p == '}' { break; } @@ -381,6 +401,6 @@ fn parse_os_display_format_string( compile_error!("Too many positional arguments for format string: unused arguments provided."); }; } + quote! { #(#generated_code_parts)* } } -