diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h index b2bb04f15f..eb44e5fc58 100644 --- a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h @@ -25,4 +25,8 @@ enum NamedEnum { Fish, }; -typedef enum NamedEnum AliasOfNamedEnum; \ No newline at end of file +typedef enum NamedEnum AliasOfNamedEnum; + +// Functions + +void named_function(); diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp new file mode 100644 index 0000000000..1de8d99e4d --- /dev/null +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp @@ -0,0 +1,6 @@ +// Methods + +class SomeClass { +public: + void named_method(); +}; \ No newline at end of file diff --git a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs index 93a2b029d7..645235b254 100644 --- a/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs +++ b/bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs @@ -17,20 +17,28 @@ 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, +) { 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), @@ -87,9 +95,37 @@ 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) { @@ -142,6 +178,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) + } } } @@ -279,3 +321,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 +} diff --git a/bindgen/callbacks.rs b/bindgen/callbacks.rs index c2be66828a..cd7bb9773d 100644 --- a/bindgen/callbacks.rs +++ b/bindgen/callbacks.rs @@ -224,7 +224,21 @@ 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 diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index f5518e432d..903af6df6c 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -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 { @@ -2501,10 +2502,7 @@ impl CodeGenerator for CompInfo { }, }; - cb.new_item_found( - DiscoveredItemId::new(item.id().as_usize()), - discovered_item, - ); + cb.new_item_found(discovered_id, discovered_item); }); // The custom derives callback may return a list of derive attributes; @@ -2711,6 +2709,7 @@ impl CodeGenerator for CompInfo { &mut method_names, result, self, + discovered_id, ); } } @@ -2729,6 +2728,7 @@ impl CodeGenerator for CompInfo { &mut method_names, result, self, + discovered_id, ); } } @@ -2742,6 +2742,7 @@ impl CodeGenerator for CompInfo { &mut method_names, result, self, + discovered_id, ); } } @@ -2999,6 +3000,7 @@ impl Method { method_names: &mut HashSet, result: &mut CodegenResult<'_>, _parent: &CompInfo, + parent_id: DiscoveredItemId, ) { assert!({ let cc = &ctx.options().codegen_config; @@ -3019,6 +3021,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; } @@ -3065,6 +3068,16 @@ 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(); @@ -4540,6 +4553,7 @@ impl CodeGenerator for Function { ) -> Self::Return { debug!("::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); @@ -4650,6 +4664,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);