Skip to content

Commit

Permalink
Discovery callbacks for functions and methods.
Browse files Browse the repository at this point in the history
This extends the existing discovery callback mechanism to report on functions
and methods. At this stage, we don't say much about them, in order to be
consistent with other discovery callbacks. Subsequent PRs will add
extra callbacks to provide information especially about methods
(virtualness, C++ visibility, etc.) Please request changes if you think
that sort of information should arrive in these callbacks.

Because methods are a fundamentally C++ thing, this splits the
current ParseCallbacks test to cover both a .h and a .hpp header.

Part of google/autocxx#124
  • Loading branch information
adetaylor committed Feb 19, 2025
1 parent 0df4256 commit 4c9a018
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ enum NamedEnum {
Fish,
};

typedef enum NamedEnum AliasOfNamedEnum;
typedef enum NamedEnum AliasOfNamedEnum;

// Functions

void named_function();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Methods

class SomeClass {
public:
void named_method();
};
109 changes: 102 additions & 7 deletions bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,26 @@ impl ParseCallbacks for ItemDiscovery {
self.0.borrow_mut().insert(_id, _item);
}
}
#[test]
pub fn test_item_discovery_callback() {

fn test_item_discovery_callback(header: &str, expected: HashMap<DiscoveredItemId, DiscoveredItem>) {
let discovery = ItemDiscovery::default();
let info = Rc::clone(&discovery.0);

let mut header_path = env!("CARGO_MANIFEST_DIR").to_string();
header_path.push_str(header);

Builder::default()
.header(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h"
))
.header(header_path)
.parse_callbacks(Box::new(discovery))
.generate()
.expect("TODO: panic message");


compare_item_caches(&info.borrow(), &expected);
}

#[test]
fn test_item_discovery_callback_c() {
let expected = ItemCache::from([
(
DiscoveredItemId::new(10),
Expand Down Expand Up @@ -87,9 +93,38 @@ pub fn test_item_discovery_callback() {
final_name: "_bindgen_ty_*".to_string(),
},
),
(
DiscoveredItemId::new(41),
DiscoveredItem::Function {
final_name: "named_function".to_string(),
},
),
]);
test_item_discovery_callback(
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h", expected);
}

compare_item_caches(&info.borrow(), &expected);

#[test]
fn test_item_discovery_callback_cpp() {
let expected = ItemCache::from([
(
DiscoveredItemId::new(1),
DiscoveredItem::Struct {
original_name: Some("SomeClass".to_string()),
final_name: "SomeClass".to_string(),
},
),
(
DiscoveredItemId::new(2),
DiscoveredItem::Method {
final_name: "named_method".to_string(),
parent: DiscoveredItemId::new(1),
},
),
]);
test_item_discovery_callback(
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp", expected);
}

pub fn compare_item_caches(generated: &ItemCache, expected: &ItemCache) {
Expand Down Expand Up @@ -142,6 +177,12 @@ fn compare_item_info(
DiscoveredItem::Enum { .. } => {
compare_enum_info(expected_item, generated_item)
}
DiscoveredItem::Function { .. } => {
compare_function_info(expected_item, generated_item)
}
DiscoveredItem::Method { .. } => {
compare_method_info(expected_item, generated_item)
}
}
}

Expand Down Expand Up @@ -279,3 +320,57 @@ pub fn compare_alias_info(

compare_item_info(expected_aliased, generated_aliased, expected, generated)
}

pub fn compare_function_info(
expected_item: &DiscoveredItem,
generated_item: &DiscoveredItem,
) -> bool {
let DiscoveredItem::Function {
final_name: expected_final_name,
} = expected_item
else {
unreachable!()
};

let DiscoveredItem::Function {
final_name: generated_final_name,
} = generated_item
else {
unreachable!()
};

if !compare_names(expected_final_name, generated_final_name) {
return false;
}
true
}

pub fn compare_method_info(
expected_item: &DiscoveredItem,
generated_item: &DiscoveredItem,
) -> bool {
let DiscoveredItem::Method {
final_name: expected_final_name,
parent: expected_parent,
} = expected_item
else {
unreachable!()
};

let DiscoveredItem::Method {
final_name: generated_final_name,
parent: generated_parent,
} = generated_item
else {
unreachable!()
};

if expected_parent != generated_parent {
return false;
}

if !compare_names(expected_final_name, generated_final_name) {
return false;
}
true
}
17 changes: 16 additions & 1 deletion bindgen/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,22 @@ pub enum DiscoveredItem {
/// The final name of the generated binding
final_name: String,
},
// functions, modules, etc.

/// A function or method.
Function {
/// The final name used.
final_name: String,
},

/// A method.
Method {
/// The final name used.
final_name: String,

/// Type to which this method belongs.
parent: DiscoveredItemId,
}
// modules, etc.
}

/// Relevant information about a type to which new derive attributes will be added using
Expand Down
22 changes: 21 additions & 1 deletion bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2481,6 +2481,7 @@ impl CodeGenerator for CompInfo {

let is_rust_union = is_union && struct_layout.is_rust_union();

let discovered_id = DiscoveredItemId::new(item.id().as_usize());
ctx.options().for_each_callback(|cb| {
let discovered_item = match self.kind() {
CompKind::Struct => DiscoveredItem::Struct {
Expand All @@ -2502,7 +2503,7 @@ impl CodeGenerator for CompInfo {
};

cb.new_item_found(
DiscoveredItemId::new(item.id().as_usize()),
discovered_id,
discovered_item,
);
});
Expand Down Expand Up @@ -2711,6 +2712,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand All @@ -2729,6 +2731,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand All @@ -2742,6 +2745,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand Down Expand Up @@ -2999,6 +3003,7 @@ impl Method {
method_names: &mut HashSet<String>,
result: &mut CodegenResult<'_>,
_parent: &CompInfo,
parent_id: DiscoveredItemId,
) {
assert!({
let cc = &ctx.options().codegen_config;
Expand All @@ -3019,6 +3024,7 @@ impl Method {

// First of all, output the actual function.
let function_item = ctx.resolve_item(self.signature());
let id = DiscoveredItemId::new(function_item.id().as_usize());
if !function_item.process_before_codegen(ctx, result) {
return;
}
Expand Down Expand Up @@ -3065,6 +3071,11 @@ impl Method {

method_names.insert(name.clone());

ctx.options().for_each_callback(|cb| cb.new_item_found(id, DiscoveredItem::Method {
parent: parent_id,
final_name: name.clone(),
}));

let mut function_name = function_item.canonical_name(ctx);
if times_seen > 0 {
write!(&mut function_name, "{times_seen}").unwrap();
Expand Down Expand Up @@ -4540,6 +4551,7 @@ impl CodeGenerator for Function {
) -> Self::Return {
debug!("<Function as CodeGenerator>::codegen: item = {item:?}");
debug_assert!(item.is_enabled_for_codegen(ctx));
let id = DiscoveredItemId::new(item.id().as_usize());

let is_internal = matches!(self.linkage(), Linkage::Internal);

Expand Down Expand Up @@ -4650,6 +4662,14 @@ impl CodeGenerator for Function {
if times_seen > 0 {
write!(&mut canonical_name, "{times_seen}").unwrap();
}
ctx.options().for_each_callback(|cb| {
cb.new_item_found(
id,
DiscoveredItem::Function {
final_name: canonical_name.to_string(),
}
);
});

let link_name_attr = self.link_name().or_else(|| {
let mangled_name = mangled_name.unwrap_or(name);
Expand Down

0 comments on commit 4c9a018

Please sign in to comment.