Skip to content

Commit

Permalink
Implement cli option for custom derive
Browse files Browse the repository at this point in the history
  • Loading branch information
hcldan committed Nov 1, 2022
1 parent a2fe04c commit 4342828
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
48 changes: 48 additions & 0 deletions bindgen-cli/options.rs
Expand Up @@ -225,6 +225,24 @@ where
"Create PartialEq implementation, if it can not be derived \
automatically.",
),
Arg::new("with-derive-custom")
.long("with-derive-custom")
.help(
"Derive custom traits on any type. \
Don't use with --with-derive-custom-struct.",
)
.value_name("trait")
.multiple_occurrences(true)
.number_of_values(1),
Arg::new("with-derive-custom-struct")
.long("with-derive-custom-struct")
.help(
"Derive custom traits on any struct.\
Don't use with --with-derive-custom.",
)
.value_name("trait")
.multiple_occurrences(true)
.number_of_values(1),
Arg::new("with-derive-default")
.long("with-derive-default")
.help("Derive Default on any type."),
Expand Down Expand Up @@ -744,6 +762,36 @@ where
builder = builder.impl_partialeq(true);
}

if let Some(traits) = matches.values_of("with-derive-custom") {
#[derive(Debug)]
struct CustomTraitCallback {
derives: Vec<String>
}
impl bindgen::callbacks::ParseCallbacks for CustomTraitCallback {
fn add_derives(&self, _name: &str) -> Vec<String> {
self.derives.to_owned()
}
}

let derives: Vec<String> = traits.into_iter().map(|t| t.to_string()).collect();
builder = builder.parse_callbacks(Box::new(CustomTraitCallback { derives }));
}

if let Some(traits) = matches.values_of("with-derive-custom-struct") {
#[derive(Debug)]
struct CustomTraitCallback {
derives: Vec<String>
}
impl bindgen::callbacks::ParseCallbacks for CustomTraitCallback {
fn add_derives_struct(&self, _name: &str) -> Vec<String> {
self.derives.to_owned()
}
}

let derives: Vec<String> = traits.into_iter().map(|t| t.to_string()).collect();
builder = builder.parse_callbacks(Box::new(CustomTraitCallback { derives }));
}

if matches.is_present("with-derive-default") {
builder = builder.derive_default(true);
}
Expand Down
9 changes: 9 additions & 0 deletions bindgen/callbacks.rs
@@ -1,5 +1,6 @@
//! A public API for more fine-grained customization of bindgen behavior.


pub use crate::ir::analysis::DeriveTrait;
pub use crate::ir::derive::CanDerive as ImplementsTrait;
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
Expand Down Expand Up @@ -108,4 +109,12 @@ pub trait ParseCallbacks: fmt::Debug {
fn add_derives(&self, _name: &str) -> Vec<String> {
vec![]
}

/// Provide a list of custom derive attributes.
///
/// If no additional attributes are wanted, this function should return an
/// empty `Vec`.
fn add_derives_struct(&self, _name: &str) -> Vec<String> {
vec![]
}
}
4 changes: 4 additions & 0 deletions bindgen/codegen/mod.rs
Expand Up @@ -2113,10 +2113,14 @@ impl CodeGenerator for CompInfo {
// The custom derives callback may return a list of derive attributes;
// add them to the end of the list.
let custom_derives;
let custom_ident_derives;
if let Some(cb) = &ctx.options().parse_callbacks {
custom_derives = cb.add_derives(&canonical_name);
// In most cases this will be a no-op, since custom_derives will be empty.
derives.extend(custom_derives.iter().map(|s| s.as_str()));

custom_ident_derives = cb.add_derives_struct(&canonical_name);
derives.extend(custom_ident_derives.iter().map(|s| s.as_str()));
};

if !derives.is_empty() {
Expand Down

0 comments on commit 4342828

Please sign in to comment.