fn fold_expr()

in src/bindgen/bitflags.rs [147:208]


    fn fold_expr(&mut self, node: syn::Expr) -> syn::Expr {
        // bitflags 2 doesn't expose `bits` publically anymore, and the documented way to
        // combine flags is using the `bits` method, e.g.
        // ```
        // bitflags! {
        //     struct Flags: u8 {
        //         const A = 1;
        //         const B = 1 << 1;
        //         const AB = Flags::A.bits() | Flags::B.bits();
        //     }
        // }
        // ```
        // As we're transforming the struct definition into `struct StructName { bits: T }`
        // as far as our bindings generation is concerned, `bits` is available as a field,
        // so by replacing `StructName::FLAG.bits()` with `StructName::FLAG.bits`, we make
        // e.g. `Flags::AB` available in the generated bindings.
        // For out-of-line definitions of the struct(*), where the struct is defined as a
        // newtype, we replace it with `StructName::FLAGS.0`.
        // * definitions like:
        // ```
        // struct Flags(u8);
        // bitflags! {
        //    impl Flags: u8 {
        //         const A = 1;
        //         const B = 1 << 1;
        //         const AB = Flags::A.bits() | Flags::B.bits();
        //     }
        // }
        // ```
        match node {
            syn::Expr::MethodCall(syn::ExprMethodCall {
                attrs,
                receiver,
                dot_token,
                method,
                args,
                ..
            }) if method == "bits"
                && args.is_empty()
                && matches!(&*receiver,
                syn::Expr::Path(syn::ExprPath { path, .. })
                    if path.segments.len() == 2
                        && self.is_self(&path.segments.first().unwrap().ident)
                        && self
                            .flag_names
                            .contains(&path.segments.last().unwrap().ident.to_string())) =>
            {
                return syn::Expr::Field(syn::ExprField {
                    attrs,
                    base: receiver,
                    dot_token,
                    member: if self.out_of_line {
                        syn::Member::Unnamed(parse_quote! {0})
                    } else {
                        syn::Member::Named(method)
                    },
                });
            }
            _ => {}
        }
        syn::fold::fold_expr(self, node)
    }