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