Skip to content

Commit f2ef849

Browse files
committed
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/unions fields.
1 parent 5b9816f commit f2ef849

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! {};
@@ -1618,35 +1629,20 @@ impl FieldCodegen<'_> for FieldData {
16181629
self.annotations().accessor_kind().unwrap_or(accessor_kind);
16191630

16201631
// Collect field attributes from multiple sources
1621-
let mut all_field_attributes = Vec::new();
1622-
1623-
// 1. Get attributes from field annotations (/// <div rustbindgen attribute="..."></div>)
1624-
all_field_attributes
1625-
.extend(self.annotations().attributes().iter().cloned());
1626-
1627-
// 2. Get custom attributes from callbacks
1628-
all_field_attributes.extend(ctx.options().all_callbacks(|cb| {
1629-
cb.field_attributes(&FieldAttributeInfo {
1630-
type_name: &parent_item.canonical_name(ctx),
1631-
type_kind: if parent.is_union() {
1632-
DeriveTypeKind::Union
1633-
} else {
1634-
DeriveTypeKind::Struct
1635-
},
1636-
field_name,
1637-
field_type_name: field_ty.name(),
1638-
})
1639-
}));
1640-
1641-
// 3. Get attributes from CLI/Builder patterns
16421632
let type_name = parent_item.canonical_name(ctx);
1643-
for (type_pat, field_pat, attr) in &ctx.options().field_attr_patterns {
1644-
if type_pat.as_ref() == type_name &&
1645-
field_pat.as_ref() == field_name
1646-
{
1647-
all_field_attributes.push(attr.to_string());
1648-
}
1649-
}
1633+
let type_kind = if parent.is_union() {
1634+
DeriveTypeKind::Union
1635+
} else {
1636+
DeriveTypeKind::Struct
1637+
};
1638+
let all_field_attributes = collect_field_attributes(
1639+
ctx,
1640+
self.annotations(),
1641+
&type_name,
1642+
type_kind,
1643+
field_name,
1644+
field_ty.name(),
1645+
);
16501646

16511647
// Apply all custom attributes to the field
16521648
for attr in &all_field_attributes {

0 commit comments

Comments
 (0)