Skip to content

Commit 72dc5f8

Browse files
jsgfemilio
authored andcommitted
Dedup code to collect custom field attributes
A single function gathers custom field attributes from cli, API and annotations, and then use it for both newtype and regular struct/union fields.
1 parent 312afb7 commit 72dc5f8

File tree

1 file changed

+56
-60
lines changed

1 file changed

+56
-60
lines changed

bindgen/codegen/mod.rs

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,40 @@ fn append_custom_derives<'a>(
212212
}
213213
}
214214

215+
/// Collects field attributes from multiple sources (annotations, callbacks, and CLI/Builder patterns).
216+
fn collect_field_attributes(
217+
ctx: &BindgenContext,
218+
annotations: &Annotations,
219+
type_name: &str,
220+
type_kind: DeriveTypeKind,
221+
field_name: &str,
222+
field_type_name: Option<&str>,
223+
) -> Vec<String> {
224+
let mut all_field_attributes = Vec::new();
225+
226+
// 1. Get attributes from annotations
227+
all_field_attributes.extend(annotations.attributes().iter().cloned());
228+
229+
// 2. Get custom attributes from callbacks
230+
all_field_attributes.extend(ctx.options().all_callbacks(|cb| {
231+
cb.field_attributes(&FieldAttributeInfo {
232+
type_name,
233+
type_kind,
234+
field_name,
235+
field_type_name,
236+
})
237+
}));
238+
239+
// 3. Get attributes from CLI/Builder patterns
240+
for (type_pat, field_pat, attr) in &ctx.options().field_attr_patterns {
241+
if type_pat.as_ref() == type_name && field_pat.as_ref() == field_name {
242+
all_field_attributes.push(attr.to_string());
243+
}
244+
}
245+
246+
all_field_attributes
247+
}
248+
215249
impl From<DerivableTraits> for Vec<&'static str> {
216250
fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> {
217251
[
@@ -1139,39 +1173,16 @@ impl CodeGenerator for Type {
11391173
.unwrap_or(ctx.options().default_visibility);
11401174
let access_spec = access_specifier(visibility);
11411175

1142-
// Collect field attributes from multiple sources for newtype tuple field
1143-
let mut all_field_attributes = Vec::new();
1144-
1145-
// 1. Get attributes from typedef annotations (if any)
1146-
all_field_attributes.extend(
1147-
item.annotations().attributes().iter().cloned(),
1148-
);
1149-
1150-
// 2. Get custom attributes from callbacks
1151-
all_field_attributes.extend(
1152-
ctx.options().all_callbacks(|cb| {
1153-
cb.field_attributes(&FieldAttributeInfo {
1154-
type_name: &item.canonical_name(ctx),
1155-
type_kind: DeriveTypeKind::Struct,
1156-
field_name: "0",
1157-
field_type_name: inner_item
1158-
.expect_type()
1159-
.name(),
1160-
})
1161-
}),
1162-
);
1163-
1164-
// 3. Get attributes from CLI/Builder patterns
1176+
// Collect field attributes for newtype tuple field
11651177
let type_name = item.canonical_name(ctx);
1166-
for (type_pat, field_pat, attr) in
1167-
&ctx.options().field_attr_patterns
1168-
{
1169-
if type_pat.as_ref() == type_name &&
1170-
field_pat.as_ref() == "0"
1171-
{
1172-
all_field_attributes.push(attr.to_string());
1173-
}
1174-
}
1178+
let all_field_attributes = collect_field_attributes(
1179+
ctx,
1180+
item.annotations(),
1181+
&type_name,
1182+
DeriveTypeKind::Struct,
1183+
"0",
1184+
inner_item.expect_type().name(),
1185+
);
11751186

11761187
// Build the field with attributes
11771188
let mut field_tokens = quote! {};
@@ -1630,35 +1641,20 @@ impl FieldCodegen<'_> for FieldData {
16301641
self.annotations().accessor_kind().unwrap_or(accessor_kind);
16311642

16321643
// Collect field attributes from multiple sources
1633-
let mut all_field_attributes = Vec::new();
1634-
1635-
// 1. Get attributes from field annotations (/// <div rustbindgen attribute="..."></div>)
1636-
all_field_attributes
1637-
.extend(self.annotations().attributes().iter().cloned());
1638-
1639-
// 2. Get custom attributes from callbacks
1640-
all_field_attributes.extend(ctx.options().all_callbacks(|cb| {
1641-
cb.field_attributes(&FieldAttributeInfo {
1642-
type_name: &parent_item.canonical_name(ctx),
1643-
type_kind: if parent.is_union() {
1644-
DeriveTypeKind::Union
1645-
} else {
1646-
DeriveTypeKind::Struct
1647-
},
1648-
field_name,
1649-
field_type_name: field_ty.name(),
1650-
})
1651-
}));
1652-
1653-
// 3. Get attributes from CLI/Builder patterns
16541644
let type_name = parent_item.canonical_name(ctx);
1655-
for (type_pat, field_pat, attr) in &ctx.options().field_attr_patterns {
1656-
if type_pat.as_ref() == type_name &&
1657-
field_pat.as_ref() == field_name
1658-
{
1659-
all_field_attributes.push(attr.to_string());
1660-
}
1661-
}
1645+
let type_kind = if parent.is_union() {
1646+
DeriveTypeKind::Union
1647+
} else {
1648+
DeriveTypeKind::Struct
1649+
};
1650+
let all_field_attributes = collect_field_attributes(
1651+
ctx,
1652+
self.annotations(),
1653+
&type_name,
1654+
type_kind,
1655+
field_name,
1656+
field_ty.name(),
1657+
);
16621658

16631659
// Apply all custom attributes to the field
16641660
for attr in &all_field_attributes {

0 commit comments

Comments
 (0)