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.
This commit is contained in:
Justin W Smith 2022-11-28 13:16:10 -05:00 committed by GitHub
parent 690feb398b
commit 199dfcc8e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 20 deletions

View File

@ -5,6 +5,14 @@
non_upper_case_globals
)]
extern "C" {
#[link_name = "\u{1}my_custom_prefix_var_const_name"]
pub static var_const_name: ::std::os::raw::c_int;
}
extern "C" {
#[link_name = "\u{1}my_custom_prefix_var_mut_name"]
pub static mut var_mut_name: ::std::os::raw::c_int;
}
extern "C" {
#[link_name = "\u{1}my_custom_prefix_function_name"]
pub fn function_name(x: ::std::os::raw::c_int);

View File

@ -1,4 +1,8 @@
// bindgen-parse-callbacks: remove-function-prefix-my_custom_prefix_
extern const int my_custom_prefix_var_const_name;
extern int my_custom_prefix_var_mut_name;
void my_custom_prefix_function_name(const int x);

View File

@ -1,22 +1,29 @@
use bindgen::callbacks::*;
#[derive(Debug)]
pub struct RemoveFunctionPrefixParseCallback {
pub remove_function_prefix: Option<String>,
pub struct RemovePrefixParseCallback {
pub remove_prefix: Option<String>,
}
impl RemoveFunctionPrefixParseCallback {
impl RemovePrefixParseCallback {
pub fn new(prefix: &str) -> Self {
RemoveFunctionPrefixParseCallback {
remove_function_prefix: Some(prefix.to_string()),
RemovePrefixParseCallback {
remove_prefix: Some(prefix.to_string()),
}
}
}
impl ParseCallbacks for RemoveFunctionPrefixParseCallback {
fn generated_name_override(&self, function_name: &str) -> Option<String> {
if let Some(prefix) = &self.remove_function_prefix {
if let Some(name) = function_name.strip_prefix(prefix) {
impl ParseCallbacks for RemovePrefixParseCallback {
fn generated_name_override(&self, item_info: ItemInfo) -> Option<String> {
if let Some(prefix) = &self.remove_prefix {
let (expected_prefix, expected_suffix) = match item_info.kind {
ItemKind::Function => ("function_", "_name"),
ItemKind::Var => ("var_", "_name"),
_ => todo!(),
};
if let Some(name) = item_info.name.strip_prefix(prefix) {
assert!(name.starts_with(expected_prefix));
assert!(name.ends_with(expected_suffix));
return Some(name.to_string());
}
}
@ -67,8 +74,7 @@ pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
.split("remove-function-prefix-")
.last()
.to_owned();
let lnopc =
RemoveFunctionPrefixParseCallback::new(prefix.unwrap());
let lnopc = RemovePrefixParseCallback::new(prefix.unwrap());
Box::new(lnopc)
} else {
panic!("Couldn't find name ParseCallbacks: {}", cb)

View File

@ -30,9 +30,9 @@ pub trait ParseCallbacks: fmt::Debug {
MacroParsingBehavior::Default
}
/// This function will run for every function. The returned value determines the name visible
/// in the bindings.
fn generated_name_override(&self, _function_name: &str) -> Option<String> {
/// This function will run for every extern variable and function. The returned value determines
/// the name visible in the bindings.
fn generated_name_override(&self, _item_info: ItemInfo) -> Option<String> {
None
}
@ -122,3 +122,21 @@ pub struct DeriveInfo<'a> {
/// The name of the type.
pub name: &'a str,
}
/// An struct providing information about the item being passed to `ParseCallbacks::generated_name_override`.
#[non_exhaustive]
pub struct ItemInfo<'a> {
/// The name of the item
pub name: &'a str,
/// The kind of item
pub kind: ItemKind,
}
/// An enum indicating the kind of item for an ItemInfo.
#[non_exhaustive]
pub enum ItemKind {
/// A Function
Function,
/// A Variable
Var,
}

View File

@ -6,6 +6,7 @@ use super::dot::DotAttributes;
use super::item::Item;
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
use crate::callbacks::{ItemInfo, ItemKind};
use crate::clang::{self, Attribute};
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
use clang_sys::{self, CXCallingConv};
@ -712,10 +713,12 @@ impl ClangSubItemParser for Function {
// but seems easy enough to handle it here.
name.push_str("_destructor");
}
if let Some(nm) = context
.options()
.last_callback(|callbacks| callbacks.generated_name_override(&name))
{
if let Some(nm) = context.options().last_callback(|callbacks| {
callbacks.generated_name_override(ItemInfo {
name: name.as_str(),
kind: ItemKind::Function,
})
}) {
name = nm;
}
assert!(!name.is_empty(), "Empty function name.");

View File

@ -7,7 +7,7 @@ use super::function::cursor_mangling;
use super::int::IntKind;
use super::item::Item;
use super::ty::{FloatKind, TypeKind};
use crate::callbacks::MacroParsingBehavior;
use crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior};
use crate::clang;
use crate::clang::ClangToken;
use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
@ -272,7 +272,20 @@ impl ClangSubItemParser for Var {
))
}
CXCursor_VarDecl => {
let name = cursor.spelling();
let mut name = cursor.spelling();
if cursor.linkage() == CXLinkage_External {
if let Some(nm) = ctx.options().last_callback(|callbacks| {
callbacks.generated_name_override(ItemInfo {
name: name.as_str(),
kind: ItemKind::Var,
})
}) {
name = nm;
}
}
// No more changes to name
let name = name;
if name.is_empty() {
warn!("Empty constant name?");
return Err(ParseError::Continue);