Skip to content

Commit 199dfcc

Browse files
authored
Extend generated_name_override callback to variables (#2351)
* This change updates `ParseCallbacks::generated_name_override` to accept a second parameter indicating the kind of item the name applies to (currently, either `Function` or `Var`). * A `CallbackItemKind` enum was added to serve as the type for this second parameter. * Tests have been updated to verify that the names of both function and variable can be updated by this callback.
1 parent 690feb3 commit 199dfcc

File tree

6 files changed

+72
-20
lines changed

6 files changed

+72
-20
lines changed

bindgen-tests/tests/expectations/tests/issue-1375-prefixed-functions.rs

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// bindgen-parse-callbacks: remove-function-prefix-my_custom_prefix_
22

3+
extern const int my_custom_prefix_var_const_name;
4+
5+
extern int my_custom_prefix_var_mut_name;
6+
37
void my_custom_prefix_function_name(const int x);
48

bindgen-tests/tests/parse_callbacks/mod.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
use bindgen::callbacks::*;
22

33
#[derive(Debug)]
4-
pub struct RemoveFunctionPrefixParseCallback {
5-
pub remove_function_prefix: Option<String>,
4+
pub struct RemovePrefixParseCallback {
5+
pub remove_prefix: Option<String>,
66
}
77

8-
impl RemoveFunctionPrefixParseCallback {
8+
impl RemovePrefixParseCallback {
99
pub fn new(prefix: &str) -> Self {
10-
RemoveFunctionPrefixParseCallback {
11-
remove_function_prefix: Some(prefix.to_string()),
10+
RemovePrefixParseCallback {
11+
remove_prefix: Some(prefix.to_string()),
1212
}
1313
}
1414
}
1515

16-
impl ParseCallbacks for RemoveFunctionPrefixParseCallback {
17-
fn generated_name_override(&self, function_name: &str) -> Option<String> {
18-
if let Some(prefix) = &self.remove_function_prefix {
19-
if let Some(name) = function_name.strip_prefix(prefix) {
16+
impl ParseCallbacks for RemovePrefixParseCallback {
17+
fn generated_name_override(&self, item_info: ItemInfo) -> Option<String> {
18+
if let Some(prefix) = &self.remove_prefix {
19+
let (expected_prefix, expected_suffix) = match item_info.kind {
20+
ItemKind::Function => ("function_", "_name"),
21+
ItemKind::Var => ("var_", "_name"),
22+
_ => todo!(),
23+
};
24+
if let Some(name) = item_info.name.strip_prefix(prefix) {
25+
assert!(name.starts_with(expected_prefix));
26+
assert!(name.ends_with(expected_suffix));
2027
return Some(name.to_string());
2128
}
2229
}
@@ -67,8 +74,7 @@ pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
6774
.split("remove-function-prefix-")
6875
.last()
6976
.to_owned();
70-
let lnopc =
71-
RemoveFunctionPrefixParseCallback::new(prefix.unwrap());
77+
let lnopc = RemovePrefixParseCallback::new(prefix.unwrap());
7278
Box::new(lnopc)
7379
} else {
7480
panic!("Couldn't find name ParseCallbacks: {}", cb)

bindgen/callbacks.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ pub trait ParseCallbacks: fmt::Debug {
3030
MacroParsingBehavior::Default
3131
}
3232

33-
/// This function will run for every function. The returned value determines the name visible
34-
/// in the bindings.
35-
fn generated_name_override(&self, _function_name: &str) -> Option<String> {
33+
/// This function will run for every extern variable and function. The returned value determines
34+
/// the name visible in the bindings.
35+
fn generated_name_override(&self, _item_info: ItemInfo) -> Option<String> {
3636
None
3737
}
3838

@@ -122,3 +122,21 @@ pub struct DeriveInfo<'a> {
122122
/// The name of the type.
123123
pub name: &'a str,
124124
}
125+
126+
/// An struct providing information about the item being passed to `ParseCallbacks::generated_name_override`.
127+
#[non_exhaustive]
128+
pub struct ItemInfo<'a> {
129+
/// The name of the item
130+
pub name: &'a str,
131+
/// The kind of item
132+
pub kind: ItemKind,
133+
}
134+
135+
/// An enum indicating the kind of item for an ItemInfo.
136+
#[non_exhaustive]
137+
pub enum ItemKind {
138+
/// A Function
139+
Function,
140+
/// A Variable
141+
Var,
142+
}

bindgen/ir/function.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use super::dot::DotAttributes;
66
use super::item::Item;
77
use super::traversal::{EdgeKind, Trace, Tracer};
88
use super::ty::TypeKind;
9+
use crate::callbacks::{ItemInfo, ItemKind};
910
use crate::clang::{self, Attribute};
1011
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
1112
use clang_sys::{self, CXCallingConv};
@@ -712,10 +713,12 @@ impl ClangSubItemParser for Function {
712713
// but seems easy enough to handle it here.
713714
name.push_str("_destructor");
714715
}
715-
if let Some(nm) = context
716-
.options()
717-
.last_callback(|callbacks| callbacks.generated_name_override(&name))
718-
{
716+
if let Some(nm) = context.options().last_callback(|callbacks| {
717+
callbacks.generated_name_override(ItemInfo {
718+
name: name.as_str(),
719+
kind: ItemKind::Function,
720+
})
721+
}) {
719722
name = nm;
720723
}
721724
assert!(!name.is_empty(), "Empty function name.");

bindgen/ir/var.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::function::cursor_mangling;
77
use super::int::IntKind;
88
use super::item::Item;
99
use super::ty::{FloatKind, TypeKind};
10-
use crate::callbacks::MacroParsingBehavior;
10+
use crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior};
1111
use crate::clang;
1212
use crate::clang::ClangToken;
1313
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
@@ -272,7 +272,20 @@ impl ClangSubItemParser for Var {
272272
))
273273
}
274274
CXCursor_VarDecl => {
275-
let name = cursor.spelling();
275+
let mut name = cursor.spelling();
276+
if cursor.linkage() == CXLinkage_External {
277+
if let Some(nm) = ctx.options().last_callback(|callbacks| {
278+
callbacks.generated_name_override(ItemInfo {
279+
name: name.as_str(),
280+
kind: ItemKind::Var,
281+
})
282+
}) {
283+
name = nm;
284+
}
285+
}
286+
// No more changes to name
287+
let name = name;
288+
276289
if name.is_empty() {
277290
warn!("Empty constant name?");
278291
return Err(ParseError::Continue);

0 commit comments

Comments
 (0)