fn generate_fields()

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
            }
        }
    }
}