in sdk/typespec/typespec_macros/src/safe_debug.rs [67:126]
fn generate_fields(path: &Path, fields: &Fields) -> TokenStream {
let name = &path.segments.last().expect("expected identifier").ident;
let name_str = name.to_string();
match fields {
Fields::Named(FieldsNamed { ref named, .. }) => {
let names: Vec<&Ident> = if cfg!(feature = "debug") {
named
.iter()
.map(|f| f.ident.as_ref().expect("expected named field"))
.collect()
} else {
// Should we ever add a `#[safe(bool)]` helper attribute to denote which fields we can safely include,
// filter the fields to match and emit based on the inherited value or field attribute value.
Vec::new()
};
let fields: Vec<TokenStream> = names
.iter()
.map(|field_name| {
let field_name_str = field_name.to_string();
quote! {.field(#field_name_str, &#field_name)}
})
.collect();
// Use an "and the rest" matcher as needed, along with the appropriate `DebugStruct` finisher.
let (matcher, finisher) = finish(&fields, named, false);
quote! {
#path { #(#names),* #matcher } => f
.debug_struct(#name_str)
#(#fields)*
#finisher
}
}
Fields::Unit => quote! {#path => f.write_str(#name_str)},
Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) => {
let indices: Vec<TokenStream> = if cfg!(feature = "debug") {
unnamed
.iter()
.enumerate()
.map(|(i, _)| {
Ident::new(&format!("f{i}"), Span::call_site()).into_token_stream()
})
.collect()
} else {
// Should we ever add a `#[safe(bool)]` helper attribute to denote which fields we can safely include,
// filter the fields to match and emit based on the inherited value or field attribute value.
Vec::new()
};
// Use an "and the rest" matcher as needed, along with the appropriate `DebugTuple` finisher.
let (matcher, finisher) = finish(&indices, unnamed, true);
quote! {
#path(#(#indices),* #matcher) => f
.debug_tuple(#name_str)
#(.field(&#indices))*
#finisher
}
}
}
}